11ac5a404SSelvin Xavier /* 21ac5a404SSelvin Xavier * Broadcom NetXtreme-E RoCE driver. 31ac5a404SSelvin Xavier * 41ac5a404SSelvin Xavier * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term 51ac5a404SSelvin Xavier * Broadcom refers to Broadcom Limited and/or its subsidiaries. 61ac5a404SSelvin Xavier * 71ac5a404SSelvin Xavier * This software is available to you under a choice of one of two 81ac5a404SSelvin Xavier * licenses. You may choose to be licensed under the terms of the GNU 91ac5a404SSelvin Xavier * General Public License (GPL) Version 2, available from the file 101ac5a404SSelvin Xavier * COPYING in the main directory of this source tree, or the 111ac5a404SSelvin Xavier * BSD license below: 121ac5a404SSelvin Xavier * 131ac5a404SSelvin Xavier * Redistribution and use in source and binary forms, with or without 141ac5a404SSelvin Xavier * modification, are permitted provided that the following conditions 151ac5a404SSelvin Xavier * are met: 161ac5a404SSelvin Xavier * 171ac5a404SSelvin Xavier * 1. Redistributions of source code must retain the above copyright 181ac5a404SSelvin Xavier * notice, this list of conditions and the following disclaimer. 191ac5a404SSelvin Xavier * 2. Redistributions in binary form must reproduce the above copyright 201ac5a404SSelvin Xavier * notice, this list of conditions and the following disclaimer in 211ac5a404SSelvin Xavier * the documentation and/or other materials provided with the 221ac5a404SSelvin Xavier * distribution. 231ac5a404SSelvin Xavier * 241ac5a404SSelvin Xavier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 251ac5a404SSelvin Xavier * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 261ac5a404SSelvin Xavier * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 271ac5a404SSelvin Xavier * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 281ac5a404SSelvin Xavier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 291ac5a404SSelvin Xavier * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 301ac5a404SSelvin Xavier * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 311ac5a404SSelvin Xavier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 321ac5a404SSelvin Xavier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 331ac5a404SSelvin Xavier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 341ac5a404SSelvin Xavier * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 351ac5a404SSelvin Xavier * 361ac5a404SSelvin Xavier * Description: QPLib resource manager 371ac5a404SSelvin Xavier */ 381ac5a404SSelvin Xavier 3908920b8fSJoe Perches #define dev_fmt(fmt) "QPLIB: " fmt 4008920b8fSJoe Perches 411ac5a404SSelvin Xavier #include <linux/spinlock.h> 421ac5a404SSelvin Xavier #include <linux/pci.h> 431ac5a404SSelvin Xavier #include <linux/interrupt.h> 441ac5a404SSelvin Xavier #include <linux/inetdevice.h> 451ac5a404SSelvin Xavier #include <linux/dma-mapping.h> 461ac5a404SSelvin Xavier #include <linux/if_vlan.h> 4765a16620SJason Gunthorpe #include <linux/vmalloc.h> 486ef999f5SJason Gunthorpe #include <rdma/ib_verbs.h> 496ef999f5SJason Gunthorpe #include <rdma/ib_umem.h> 506ef999f5SJason Gunthorpe 511ac5a404SSelvin Xavier #include "roce_hsi.h" 521ac5a404SSelvin Xavier #include "qplib_res.h" 531ac5a404SSelvin Xavier #include "qplib_sp.h" 541ac5a404SSelvin Xavier #include "qplib_rcfw.h" 551ac5a404SSelvin Xavier 561ac5a404SSelvin Xavier static void bnxt_qplib_free_stats_ctx(struct pci_dev *pdev, 571ac5a404SSelvin Xavier struct bnxt_qplib_stats *stats); 581ac5a404SSelvin Xavier static int bnxt_qplib_alloc_stats_ctx(struct pci_dev *pdev, 590c23af52SNaresh Kumar PBS struct bnxt_qplib_chip_ctx *cctx, 601ac5a404SSelvin Xavier struct bnxt_qplib_stats *stats); 611ac5a404SSelvin Xavier 621ac5a404SSelvin Xavier /* PBL */ 630c4dcd60SDevesh Sharma static void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl, 641ac5a404SSelvin Xavier bool is_umem) 651ac5a404SSelvin Xavier { 660c4dcd60SDevesh Sharma struct pci_dev *pdev = res->pdev; 671ac5a404SSelvin Xavier int i; 681ac5a404SSelvin Xavier 691ac5a404SSelvin Xavier if (!is_umem) { 701ac5a404SSelvin Xavier for (i = 0; i < pbl->pg_count; i++) { 711ac5a404SSelvin Xavier if (pbl->pg_arr[i]) 721ac5a404SSelvin Xavier dma_free_coherent(&pdev->dev, pbl->pg_size, 731ac5a404SSelvin Xavier (void *)((unsigned long) 741ac5a404SSelvin Xavier pbl->pg_arr[i] & 751ac5a404SSelvin Xavier PAGE_MASK), 761ac5a404SSelvin Xavier pbl->pg_map_arr[i]); 771ac5a404SSelvin Xavier else 781ac5a404SSelvin Xavier dev_warn(&pdev->dev, 7908920b8fSJoe Perches "PBL free pg_arr[%d] empty?!\n", i); 801ac5a404SSelvin Xavier pbl->pg_arr[i] = NULL; 811ac5a404SSelvin Xavier } 821ac5a404SSelvin Xavier } 830c4dcd60SDevesh Sharma vfree(pbl->pg_arr); 841ac5a404SSelvin Xavier pbl->pg_arr = NULL; 850c4dcd60SDevesh Sharma vfree(pbl->pg_map_arr); 861ac5a404SSelvin Xavier pbl->pg_map_arr = NULL; 871ac5a404SSelvin Xavier pbl->pg_count = 0; 881ac5a404SSelvin Xavier pbl->pg_size = 0; 891ac5a404SSelvin Xavier } 901ac5a404SSelvin Xavier 910c4dcd60SDevesh Sharma static void bnxt_qplib_fill_user_dma_pages(struct bnxt_qplib_pbl *pbl, 920c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info *sginfo) 931ac5a404SSelvin Xavier { 946ef999f5SJason Gunthorpe struct ib_block_iter biter; 950c4dcd60SDevesh Sharma int i = 0; 960c4dcd60SDevesh Sharma 976ef999f5SJason Gunthorpe rdma_umem_for_each_dma_block(sginfo->umem, &biter, sginfo->pgsize) { 986ef999f5SJason Gunthorpe pbl->pg_map_arr[i] = rdma_block_iter_dma_address(&biter); 990c4dcd60SDevesh Sharma pbl->pg_arr[i] = NULL; 1000c4dcd60SDevesh Sharma pbl->pg_count++; 1010c4dcd60SDevesh Sharma i++; 1020c4dcd60SDevesh Sharma } 1030c4dcd60SDevesh Sharma } 1040c4dcd60SDevesh Sharma 1050c4dcd60SDevesh Sharma static int __alloc_pbl(struct bnxt_qplib_res *res, 1060c4dcd60SDevesh Sharma struct bnxt_qplib_pbl *pbl, 1070c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info *sginfo) 1080c4dcd60SDevesh Sharma { 1090c4dcd60SDevesh Sharma struct pci_dev *pdev = res->pdev; 1101ac5a404SSelvin Xavier bool is_umem = false; 1116be2067dSYueHaibing u32 pages; 1121ac5a404SSelvin Xavier int i; 1131ac5a404SSelvin Xavier 1140c4dcd60SDevesh Sharma if (sginfo->nopte) 1150c4dcd60SDevesh Sharma return 0; 1166ef999f5SJason Gunthorpe if (sginfo->umem) 1176ef999f5SJason Gunthorpe pages = ib_umem_num_dma_blocks(sginfo->umem, sginfo->pgsize); 1186ef999f5SJason Gunthorpe else 1190c4dcd60SDevesh Sharma pages = sginfo->npages; 1201ac5a404SSelvin Xavier /* page ptr arrays */ 1210c4dcd60SDevesh Sharma pbl->pg_arr = vmalloc(pages * sizeof(void *)); 1221ac5a404SSelvin Xavier if (!pbl->pg_arr) 1231ac5a404SSelvin Xavier return -ENOMEM; 1241ac5a404SSelvin Xavier 1250c4dcd60SDevesh Sharma pbl->pg_map_arr = vmalloc(pages * sizeof(dma_addr_t)); 1261ac5a404SSelvin Xavier if (!pbl->pg_map_arr) { 1270c4dcd60SDevesh Sharma vfree(pbl->pg_arr); 1281ac5a404SSelvin Xavier pbl->pg_arr = NULL; 1291ac5a404SSelvin Xavier return -ENOMEM; 1301ac5a404SSelvin Xavier } 1311ac5a404SSelvin Xavier pbl->pg_count = 0; 1320c4dcd60SDevesh Sharma pbl->pg_size = sginfo->pgsize; 1331ac5a404SSelvin Xavier 1346ef999f5SJason Gunthorpe if (!sginfo->umem) { 1351ac5a404SSelvin Xavier for (i = 0; i < pages; i++) { 136750afb08SLuis Chamberlain pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev, 1371ac5a404SSelvin Xavier pbl->pg_size, 1381ac5a404SSelvin Xavier &pbl->pg_map_arr[i], 1391ac5a404SSelvin Xavier GFP_KERNEL); 1401ac5a404SSelvin Xavier if (!pbl->pg_arr[i]) 1411ac5a404SSelvin Xavier goto fail; 1421ac5a404SSelvin Xavier pbl->pg_count++; 1431ac5a404SSelvin Xavier } 1441ac5a404SSelvin Xavier } else { 1451ac5a404SSelvin Xavier is_umem = true; 1460c4dcd60SDevesh Sharma bnxt_qplib_fill_user_dma_pages(pbl, sginfo); 1471ac5a404SSelvin Xavier } 1481ac5a404SSelvin Xavier 1491ac5a404SSelvin Xavier return 0; 1501ac5a404SSelvin Xavier fail: 1510c4dcd60SDevesh Sharma __free_pbl(res, pbl, is_umem); 1521ac5a404SSelvin Xavier return -ENOMEM; 1531ac5a404SSelvin Xavier } 1541ac5a404SSelvin Xavier 1551ac5a404SSelvin Xavier /* HWQ */ 1560c4dcd60SDevesh Sharma void bnxt_qplib_free_hwq(struct bnxt_qplib_res *res, 1570c4dcd60SDevesh Sharma struct bnxt_qplib_hwq *hwq) 1581ac5a404SSelvin Xavier { 1591ac5a404SSelvin Xavier int i; 1601ac5a404SSelvin Xavier 1611ac5a404SSelvin Xavier if (!hwq->max_elements) 1621ac5a404SSelvin Xavier return; 1631ac5a404SSelvin Xavier if (hwq->level >= PBL_LVL_MAX) 1641ac5a404SSelvin Xavier return; 1651ac5a404SSelvin Xavier 1661ac5a404SSelvin Xavier for (i = 0; i < hwq->level + 1; i++) { 1671ac5a404SSelvin Xavier if (i == hwq->level) 1680c4dcd60SDevesh Sharma __free_pbl(res, &hwq->pbl[i], hwq->is_user); 1691ac5a404SSelvin Xavier else 1700c4dcd60SDevesh Sharma __free_pbl(res, &hwq->pbl[i], false); 1711ac5a404SSelvin Xavier } 1721ac5a404SSelvin Xavier 1731ac5a404SSelvin Xavier hwq->level = PBL_LVL_MAX; 1741ac5a404SSelvin Xavier hwq->max_elements = 0; 1751ac5a404SSelvin Xavier hwq->element_size = 0; 1761ac5a404SSelvin Xavier hwq->prod = 0; 1771ac5a404SSelvin Xavier hwq->cons = 0; 1781ac5a404SSelvin Xavier hwq->cp_bit = 0; 1791ac5a404SSelvin Xavier } 1801ac5a404SSelvin Xavier 1811ac5a404SSelvin Xavier /* All HWQs are power of 2 in size */ 1820c4dcd60SDevesh Sharma 1830c4dcd60SDevesh Sharma int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, 1840c4dcd60SDevesh Sharma struct bnxt_qplib_hwq_attr *hwq_attr) 1851ac5a404SSelvin Xavier { 1860c4dcd60SDevesh Sharma u32 npages, aux_slots, pg_size, aux_pages = 0, aux_size = 0; 1870c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info sginfo = {}; 1880c4dcd60SDevesh Sharma u32 depth, stride, npbl, npde; 1891ac5a404SSelvin Xavier dma_addr_t *src_phys_ptr, **dst_virt_ptr; 1900c4dcd60SDevesh Sharma struct bnxt_qplib_res *res; 1910c4dcd60SDevesh Sharma struct pci_dev *pdev; 1920c4dcd60SDevesh Sharma int i, rc, lvl; 1931ac5a404SSelvin Xavier 1940c4dcd60SDevesh Sharma res = hwq_attr->res; 1950c4dcd60SDevesh Sharma pdev = res->pdev; 1960c4dcd60SDevesh Sharma pg_size = hwq_attr->sginfo->pgsize; 1971ac5a404SSelvin Xavier hwq->level = PBL_LVL_MAX; 1981ac5a404SSelvin Xavier 1990c4dcd60SDevesh Sharma depth = roundup_pow_of_two(hwq_attr->depth); 2000c4dcd60SDevesh Sharma stride = roundup_pow_of_two(hwq_attr->stride); 2010c4dcd60SDevesh Sharma if (hwq_attr->aux_depth) { 2020c4dcd60SDevesh Sharma aux_slots = hwq_attr->aux_depth; 2030c4dcd60SDevesh Sharma aux_size = roundup_pow_of_two(hwq_attr->aux_stride); 2040c4dcd60SDevesh Sharma aux_pages = (aux_slots * aux_size) / pg_size; 2050c4dcd60SDevesh Sharma if ((aux_slots * aux_size) % pg_size) 2061ac5a404SSelvin Xavier aux_pages++; 2071ac5a404SSelvin Xavier } 2085aa84840SSelvin Xavier 2096ef999f5SJason Gunthorpe if (!hwq_attr->sginfo->umem) { 2101ac5a404SSelvin Xavier hwq->is_user = false; 2110c4dcd60SDevesh Sharma npages = (depth * stride) / pg_size + aux_pages; 2120c4dcd60SDevesh Sharma if ((depth * stride) % pg_size) 2130c4dcd60SDevesh Sharma npages++; 2140c4dcd60SDevesh Sharma if (!npages) 2151ac5a404SSelvin Xavier return -EINVAL; 2160c4dcd60SDevesh Sharma hwq_attr->sginfo->npages = npages; 2171ac5a404SSelvin Xavier } else { 21808c7f093SSelvin Xavier npages = ib_umem_num_dma_blocks(hwq_attr->sginfo->umem, 21908c7f093SSelvin Xavier hwq_attr->sginfo->pgsize); 2201ac5a404SSelvin Xavier hwq->is_user = true; 2211ac5a404SSelvin Xavier } 2221ac5a404SSelvin Xavier 2232b4ccce6SSelvin Xavier if (npages == MAX_PBL_LVL_0_PGS && !hwq_attr->sginfo->nopte) { 2240c4dcd60SDevesh Sharma /* This request is Level 0, map PTE */ 2250c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], hwq_attr->sginfo); 2261ac5a404SSelvin Xavier if (rc) 2271ac5a404SSelvin Xavier goto fail; 2281ac5a404SSelvin Xavier hwq->level = PBL_LVL_0; 2292b4ccce6SSelvin Xavier goto done; 2300c4dcd60SDevesh Sharma } 2311ac5a404SSelvin Xavier 2322b4ccce6SSelvin Xavier if (npages >= MAX_PBL_LVL_0_PGS) { 2330c4dcd60SDevesh Sharma if (npages > MAX_PBL_LVL_1_PGS) { 2340c4dcd60SDevesh Sharma u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ? 2350c4dcd60SDevesh Sharma 0 : PTU_PTE_VALID; 2361ac5a404SSelvin Xavier /* 2 levels of indirection */ 2370c4dcd60SDevesh Sharma npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT; 2380c4dcd60SDevesh Sharma if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT)) 2390c4dcd60SDevesh Sharma npbl++; 2400c4dcd60SDevesh Sharma npde = npbl >> MAX_PDL_LVL_SHIFT; 2410c4dcd60SDevesh Sharma if (npbl % BIT(MAX_PDL_LVL_SHIFT)) 2420c4dcd60SDevesh Sharma npde++; 2430c4dcd60SDevesh Sharma /* Alloc PDE pages */ 2440c4dcd60SDevesh Sharma sginfo.pgsize = npde * pg_size; 2450c4dcd60SDevesh Sharma sginfo.npages = 1; 2460c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo); 2470c4dcd60SDevesh Sharma 2480c4dcd60SDevesh Sharma /* Alloc PBL pages */ 2490c4dcd60SDevesh Sharma sginfo.npages = npbl; 2500c4dcd60SDevesh Sharma sginfo.pgsize = PAGE_SIZE; 2510c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo); 2521ac5a404SSelvin Xavier if (rc) 2531ac5a404SSelvin Xavier goto fail; 2540c4dcd60SDevesh Sharma /* Fill PDL with PBL page pointers */ 2551ac5a404SSelvin Xavier dst_virt_ptr = 2561ac5a404SSelvin Xavier (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr; 2571ac5a404SSelvin Xavier src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr; 2580c4dcd60SDevesh Sharma if (hwq_attr->type == HWQ_TYPE_MR) { 2590c4dcd60SDevesh Sharma /* For MR it is expected that we supply only 1 contigous 2600c4dcd60SDevesh Sharma * page i.e only 1 entry in the PDL that will contain 2610c4dcd60SDevesh Sharma * all the PBLs for the user supplied memory region 2620c4dcd60SDevesh Sharma */ 2630c4dcd60SDevesh Sharma for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; 2640c4dcd60SDevesh Sharma i++) 2650c4dcd60SDevesh Sharma dst_virt_ptr[0][i] = src_phys_ptr[i] | 2660c4dcd60SDevesh Sharma flag; 2670c4dcd60SDevesh Sharma } else { 2680c4dcd60SDevesh Sharma for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; 2690c4dcd60SDevesh Sharma i++) 2701ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = 2710c4dcd60SDevesh Sharma src_phys_ptr[i] | 2720c4dcd60SDevesh Sharma PTU_PDE_VALID; 2730c4dcd60SDevesh Sharma } 2740c4dcd60SDevesh Sharma /* Alloc or init PTEs */ 2750c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_2], 2760c4dcd60SDevesh Sharma hwq_attr->sginfo); 2771ac5a404SSelvin Xavier if (rc) 2781ac5a404SSelvin Xavier goto fail; 2790c4dcd60SDevesh Sharma hwq->level = PBL_LVL_2; 2800c4dcd60SDevesh Sharma if (hwq_attr->sginfo->nopte) 2810c4dcd60SDevesh Sharma goto done; 2820c4dcd60SDevesh Sharma /* Fill PBLs with PTE pointers */ 2831ac5a404SSelvin Xavier dst_virt_ptr = 2841ac5a404SSelvin Xavier (dma_addr_t **)hwq->pbl[PBL_LVL_1].pg_arr; 2851ac5a404SSelvin Xavier src_phys_ptr = hwq->pbl[PBL_LVL_2].pg_map_arr; 2861ac5a404SSelvin Xavier for (i = 0; i < hwq->pbl[PBL_LVL_2].pg_count; i++) { 2871ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = 2881ac5a404SSelvin Xavier src_phys_ptr[i] | PTU_PTE_VALID; 2891ac5a404SSelvin Xavier } 2900c4dcd60SDevesh Sharma if (hwq_attr->type == HWQ_TYPE_QUEUE) { 2911ac5a404SSelvin Xavier /* Find the last pg of the size */ 2921ac5a404SSelvin Xavier i = hwq->pbl[PBL_LVL_2].pg_count; 2931ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |= 2941ac5a404SSelvin Xavier PTU_PTE_LAST; 2951ac5a404SSelvin Xavier if (i > 1) 2961ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i - 2)] 2971ac5a404SSelvin Xavier [PTR_IDX(i - 2)] |= 2981ac5a404SSelvin Xavier PTU_PTE_NEXT_TO_LAST; 2991ac5a404SSelvin Xavier } 3000c4dcd60SDevesh Sharma } else { /* pages < 512 npbl = 1, npde = 0 */ 3010c4dcd60SDevesh Sharma u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ? 3020c4dcd60SDevesh Sharma 0 : PTU_PTE_VALID; 3031ac5a404SSelvin Xavier 3041ac5a404SSelvin Xavier /* 1 level of indirection */ 3050c4dcd60SDevesh Sharma npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT; 3060c4dcd60SDevesh Sharma if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT)) 3070c4dcd60SDevesh Sharma npbl++; 3080c4dcd60SDevesh Sharma sginfo.npages = npbl; 3090c4dcd60SDevesh Sharma sginfo.pgsize = PAGE_SIZE; 3100c4dcd60SDevesh Sharma /* Alloc PBL page */ 3110c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo); 3121ac5a404SSelvin Xavier if (rc) 3131ac5a404SSelvin Xavier goto fail; 3140c4dcd60SDevesh Sharma /* Alloc or init PTEs */ 3150c4dcd60SDevesh Sharma rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], 3160c4dcd60SDevesh Sharma hwq_attr->sginfo); 3170c4dcd60SDevesh Sharma if (rc) 3180c4dcd60SDevesh Sharma goto fail; 3190c4dcd60SDevesh Sharma hwq->level = PBL_LVL_1; 3200c4dcd60SDevesh Sharma if (hwq_attr->sginfo->nopte) 3210c4dcd60SDevesh Sharma goto done; 3220c4dcd60SDevesh Sharma /* Fill PBL with PTE pointers */ 3231ac5a404SSelvin Xavier dst_virt_ptr = 3241ac5a404SSelvin Xavier (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr; 3251ac5a404SSelvin Xavier src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr; 3260c4dcd60SDevesh Sharma for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++) 3271ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = 3281ac5a404SSelvin Xavier src_phys_ptr[i] | flag; 3290c4dcd60SDevesh Sharma if (hwq_attr->type == HWQ_TYPE_QUEUE) { 3301ac5a404SSelvin Xavier /* Find the last pg of the size */ 3311ac5a404SSelvin Xavier i = hwq->pbl[PBL_LVL_1].pg_count; 3321ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |= 3331ac5a404SSelvin Xavier PTU_PTE_LAST; 3341ac5a404SSelvin Xavier if (i > 1) 3351ac5a404SSelvin Xavier dst_virt_ptr[PTR_PG(i - 2)] 3361ac5a404SSelvin Xavier [PTR_IDX(i - 2)] |= 3371ac5a404SSelvin Xavier PTU_PTE_NEXT_TO_LAST; 3381ac5a404SSelvin Xavier } 3391ac5a404SSelvin Xavier } 3401ac5a404SSelvin Xavier } 3410c4dcd60SDevesh Sharma done: 3421ac5a404SSelvin Xavier hwq->prod = 0; 3431ac5a404SSelvin Xavier hwq->cons = 0; 3440c4dcd60SDevesh Sharma hwq->pdev = pdev; 3450c4dcd60SDevesh Sharma hwq->depth = hwq_attr->depth; 3460c4dcd60SDevesh Sharma hwq->max_elements = depth; 3470c4dcd60SDevesh Sharma hwq->element_size = stride; 348fddcbbb0SDevesh Sharma hwq->qe_ppg = pg_size / stride; 3491ac5a404SSelvin Xavier /* For direct access to the elements */ 3500c4dcd60SDevesh Sharma lvl = hwq->level; 3510c4dcd60SDevesh Sharma if (hwq_attr->sginfo->nopte && hwq->level) 3520c4dcd60SDevesh Sharma lvl = hwq->level - 1; 3530c4dcd60SDevesh Sharma hwq->pbl_ptr = hwq->pbl[lvl].pg_arr; 3540c4dcd60SDevesh Sharma hwq->pbl_dma_ptr = hwq->pbl[lvl].pg_map_arr; 3550c4dcd60SDevesh Sharma spin_lock_init(&hwq->lock); 3561ac5a404SSelvin Xavier 3571ac5a404SSelvin Xavier return 0; 3581ac5a404SSelvin Xavier fail: 3590c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, hwq); 3601ac5a404SSelvin Xavier return -ENOMEM; 3611ac5a404SSelvin Xavier } 3621ac5a404SSelvin Xavier 3631ac5a404SSelvin Xavier /* Context Tables */ 3640c4dcd60SDevesh Sharma void bnxt_qplib_free_ctx(struct bnxt_qplib_res *res, 3651ac5a404SSelvin Xavier struct bnxt_qplib_ctx *ctx) 3661ac5a404SSelvin Xavier { 3671ac5a404SSelvin Xavier int i; 3681ac5a404SSelvin Xavier 3690c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->qpc_tbl); 3700c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->mrw_tbl); 3710c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->srqc_tbl); 3720c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->cq_tbl); 3730c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->tim_tbl); 3741ac5a404SSelvin Xavier for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) 3750c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->tqm_ctx.qtbl[i]); 3760c4dcd60SDevesh Sharma /* restore original pde level before destroy */ 3770c4dcd60SDevesh Sharma ctx->tqm_ctx.pde.level = ctx->tqm_ctx.pde_level; 3780c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &ctx->tqm_ctx.pde); 3790c4dcd60SDevesh Sharma bnxt_qplib_free_stats_ctx(res->pdev, &ctx->stats); 3800c4dcd60SDevesh Sharma } 3810c4dcd60SDevesh Sharma 3820c4dcd60SDevesh Sharma static int bnxt_qplib_alloc_tqm_rings(struct bnxt_qplib_res *res, 3830c4dcd60SDevesh Sharma struct bnxt_qplib_ctx *ctx) 3840c4dcd60SDevesh Sharma { 3850c4dcd60SDevesh Sharma struct bnxt_qplib_hwq_attr hwq_attr = {}; 3860c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info sginfo = {}; 3870c4dcd60SDevesh Sharma struct bnxt_qplib_tqm_ctx *tqmctx; 3880c4dcd60SDevesh Sharma int rc = 0; 3890c4dcd60SDevesh Sharma int i; 3900c4dcd60SDevesh Sharma 3910c4dcd60SDevesh Sharma tqmctx = &ctx->tqm_ctx; 3920c4dcd60SDevesh Sharma 3930c4dcd60SDevesh Sharma sginfo.pgsize = PAGE_SIZE; 3940c4dcd60SDevesh Sharma sginfo.pgshft = PAGE_SHIFT; 3950c4dcd60SDevesh Sharma hwq_attr.sginfo = &sginfo; 3960c4dcd60SDevesh Sharma hwq_attr.res = res; 3970c4dcd60SDevesh Sharma hwq_attr.type = HWQ_TYPE_CTX; 3980c4dcd60SDevesh Sharma hwq_attr.depth = 512; 3990c4dcd60SDevesh Sharma hwq_attr.stride = sizeof(u64); 4000c4dcd60SDevesh Sharma /* Alloc pdl buffer */ 4010c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&tqmctx->pde, &hwq_attr); 4020c4dcd60SDevesh Sharma if (rc) 4030c4dcd60SDevesh Sharma goto out; 4040c4dcd60SDevesh Sharma /* Save original pdl level */ 4050c4dcd60SDevesh Sharma tqmctx->pde_level = tqmctx->pde.level; 4060c4dcd60SDevesh Sharma 4070c4dcd60SDevesh Sharma hwq_attr.stride = 1; 4080c4dcd60SDevesh Sharma for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) { 4090c4dcd60SDevesh Sharma if (!tqmctx->qcount[i]) 4100c4dcd60SDevesh Sharma continue; 4110c4dcd60SDevesh Sharma hwq_attr.depth = ctx->qpc_count * tqmctx->qcount[i]; 4120c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&tqmctx->qtbl[i], &hwq_attr); 4130c4dcd60SDevesh Sharma if (rc) 4140c4dcd60SDevesh Sharma goto out; 4150c4dcd60SDevesh Sharma } 4160c4dcd60SDevesh Sharma out: 4170c4dcd60SDevesh Sharma return rc; 4180c4dcd60SDevesh Sharma } 4190c4dcd60SDevesh Sharma 4200c4dcd60SDevesh Sharma static void bnxt_qplib_map_tqm_pgtbl(struct bnxt_qplib_tqm_ctx *ctx) 4210c4dcd60SDevesh Sharma { 4220c4dcd60SDevesh Sharma struct bnxt_qplib_hwq *tbl; 4230c4dcd60SDevesh Sharma dma_addr_t *dma_ptr; 4240c4dcd60SDevesh Sharma __le64 **pbl_ptr, *ptr; 4250c4dcd60SDevesh Sharma int i, j, k; 4260c4dcd60SDevesh Sharma int fnz_idx = -1; 4270c4dcd60SDevesh Sharma int pg_count; 4280c4dcd60SDevesh Sharma 4290c4dcd60SDevesh Sharma pbl_ptr = (__le64 **)ctx->pde.pbl_ptr; 4300c4dcd60SDevesh Sharma 4310c4dcd60SDevesh Sharma for (i = 0, j = 0; i < MAX_TQM_ALLOC_REQ; 4320c4dcd60SDevesh Sharma i++, j += MAX_TQM_ALLOC_BLK_SIZE) { 4330c4dcd60SDevesh Sharma tbl = &ctx->qtbl[i]; 4340c4dcd60SDevesh Sharma if (!tbl->max_elements) 4350c4dcd60SDevesh Sharma continue; 4360c4dcd60SDevesh Sharma if (fnz_idx == -1) 4370c4dcd60SDevesh Sharma fnz_idx = i; /* first non-zero index */ 4380c4dcd60SDevesh Sharma switch (tbl->level) { 4390c4dcd60SDevesh Sharma case PBL_LVL_2: 4400c4dcd60SDevesh Sharma pg_count = tbl->pbl[PBL_LVL_1].pg_count; 4410c4dcd60SDevesh Sharma for (k = 0; k < pg_count; k++) { 4420c4dcd60SDevesh Sharma ptr = &pbl_ptr[PTR_PG(j + k)][PTR_IDX(j + k)]; 4430c4dcd60SDevesh Sharma dma_ptr = &tbl->pbl[PBL_LVL_1].pg_map_arr[k]; 4440c4dcd60SDevesh Sharma *ptr = cpu_to_le64(*dma_ptr | PTU_PTE_VALID); 4450c4dcd60SDevesh Sharma } 4460c4dcd60SDevesh Sharma break; 4470c4dcd60SDevesh Sharma case PBL_LVL_1: 4480c4dcd60SDevesh Sharma case PBL_LVL_0: 4490c4dcd60SDevesh Sharma default: 4500c4dcd60SDevesh Sharma ptr = &pbl_ptr[PTR_PG(j)][PTR_IDX(j)]; 4510c4dcd60SDevesh Sharma *ptr = cpu_to_le64(tbl->pbl[PBL_LVL_0].pg_map_arr[0] | 4520c4dcd60SDevesh Sharma PTU_PTE_VALID); 4530c4dcd60SDevesh Sharma break; 4540c4dcd60SDevesh Sharma } 4550c4dcd60SDevesh Sharma } 4560c4dcd60SDevesh Sharma if (fnz_idx == -1) 4570c4dcd60SDevesh Sharma fnz_idx = 0; 4580c4dcd60SDevesh Sharma /* update pde level as per page table programming */ 4590c4dcd60SDevesh Sharma ctx->pde.level = (ctx->qtbl[fnz_idx].level == PBL_LVL_2) ? PBL_LVL_2 : 4600c4dcd60SDevesh Sharma ctx->qtbl[fnz_idx].level + 1; 4610c4dcd60SDevesh Sharma } 4620c4dcd60SDevesh Sharma 4630c4dcd60SDevesh Sharma static int bnxt_qplib_setup_tqm_rings(struct bnxt_qplib_res *res, 4640c4dcd60SDevesh Sharma struct bnxt_qplib_ctx *ctx) 4650c4dcd60SDevesh Sharma { 4660c4dcd60SDevesh Sharma int rc = 0; 4670c4dcd60SDevesh Sharma 4680c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_tqm_rings(res, ctx); 4690c4dcd60SDevesh Sharma if (rc) 4700c4dcd60SDevesh Sharma goto fail; 4710c4dcd60SDevesh Sharma 4720c4dcd60SDevesh Sharma bnxt_qplib_map_tqm_pgtbl(&ctx->tqm_ctx); 4730c4dcd60SDevesh Sharma fail: 4740c4dcd60SDevesh Sharma return rc; 4751ac5a404SSelvin Xavier } 4761ac5a404SSelvin Xavier 4771ac5a404SSelvin Xavier /* 4781ac5a404SSelvin Xavier * Routine: bnxt_qplib_alloc_ctx 4791ac5a404SSelvin Xavier * Description: 4801ac5a404SSelvin Xavier * Context tables are memories which are used by the chip fw. 4811ac5a404SSelvin Xavier * The 6 tables defined are: 4821ac5a404SSelvin Xavier * QPC ctx - holds QP states 4831ac5a404SSelvin Xavier * MRW ctx - holds memory region and window 4841ac5a404SSelvin Xavier * SRQ ctx - holds shared RQ states 4851ac5a404SSelvin Xavier * CQ ctx - holds completion queue states 4861ac5a404SSelvin Xavier * TQM ctx - holds Tx Queue Manager context 4871ac5a404SSelvin Xavier * TIM ctx - holds timer context 4881ac5a404SSelvin Xavier * Depending on the size of the tbl requested, either a 1 Page Buffer List 4891ac5a404SSelvin Xavier * or a 1-to-2-stage indirection Page Directory List + 1 PBL is used 4901ac5a404SSelvin Xavier * instead. 4911ac5a404SSelvin Xavier * Table might be employed as follows: 4921ac5a404SSelvin Xavier * For 0 < ctx size <= 1 PAGE, 0 level of ind is used 4931ac5a404SSelvin Xavier * For 1 PAGE < ctx size <= 512 entries size, 1 level of ind is used 4941ac5a404SSelvin Xavier * For 512 < ctx size <= MAX, 2 levels of ind is used 4951ac5a404SSelvin Xavier * Returns: 4961ac5a404SSelvin Xavier * 0 if success, else -ERRORS 4971ac5a404SSelvin Xavier */ 4980c4dcd60SDevesh Sharma int bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res, 4991ac5a404SSelvin Xavier struct bnxt_qplib_ctx *ctx, 500e0387e1dSDevesh Sharma bool virt_fn, bool is_p5) 5011ac5a404SSelvin Xavier { 5020c4dcd60SDevesh Sharma struct bnxt_qplib_hwq_attr hwq_attr = {}; 5030c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info sginfo = {}; 5040c4dcd60SDevesh Sharma int rc = 0; 5051ac5a404SSelvin Xavier 506e0387e1dSDevesh Sharma if (virt_fn || is_p5) 5071ac5a404SSelvin Xavier goto stats_alloc; 5081ac5a404SSelvin Xavier 5091ac5a404SSelvin Xavier /* QPC Tables */ 5100c4dcd60SDevesh Sharma sginfo.pgsize = PAGE_SIZE; 5110c4dcd60SDevesh Sharma sginfo.pgshft = PAGE_SHIFT; 5120c4dcd60SDevesh Sharma hwq_attr.sginfo = &sginfo; 5130c4dcd60SDevesh Sharma 5140c4dcd60SDevesh Sharma hwq_attr.res = res; 5150c4dcd60SDevesh Sharma hwq_attr.depth = ctx->qpc_count; 5160c4dcd60SDevesh Sharma hwq_attr.stride = BNXT_QPLIB_MAX_QP_CTX_ENTRY_SIZE; 5170c4dcd60SDevesh Sharma hwq_attr.type = HWQ_TYPE_CTX; 5180c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&ctx->qpc_tbl, &hwq_attr); 5191ac5a404SSelvin Xavier if (rc) 5201ac5a404SSelvin Xavier goto fail; 5211ac5a404SSelvin Xavier 5221ac5a404SSelvin Xavier /* MRW Tables */ 5230c4dcd60SDevesh Sharma hwq_attr.depth = ctx->mrw_count; 5240c4dcd60SDevesh Sharma hwq_attr.stride = BNXT_QPLIB_MAX_MRW_CTX_ENTRY_SIZE; 5250c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&ctx->mrw_tbl, &hwq_attr); 5261ac5a404SSelvin Xavier if (rc) 5271ac5a404SSelvin Xavier goto fail; 5281ac5a404SSelvin Xavier 5291ac5a404SSelvin Xavier /* SRQ Tables */ 5300c4dcd60SDevesh Sharma hwq_attr.depth = ctx->srqc_count; 5310c4dcd60SDevesh Sharma hwq_attr.stride = BNXT_QPLIB_MAX_SRQ_CTX_ENTRY_SIZE; 5320c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&ctx->srqc_tbl, &hwq_attr); 5331ac5a404SSelvin Xavier if (rc) 5341ac5a404SSelvin Xavier goto fail; 5351ac5a404SSelvin Xavier 5361ac5a404SSelvin Xavier /* CQ Tables */ 5370c4dcd60SDevesh Sharma hwq_attr.depth = ctx->cq_count; 5380c4dcd60SDevesh Sharma hwq_attr.stride = BNXT_QPLIB_MAX_CQ_CTX_ENTRY_SIZE; 5390c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&ctx->cq_tbl, &hwq_attr); 5401ac5a404SSelvin Xavier if (rc) 5411ac5a404SSelvin Xavier goto fail; 5421ac5a404SSelvin Xavier 5431ac5a404SSelvin Xavier /* TQM Buffer */ 5440c4dcd60SDevesh Sharma rc = bnxt_qplib_setup_tqm_rings(res, ctx); 5451ac5a404SSelvin Xavier if (rc) 5461ac5a404SSelvin Xavier goto fail; 5471ac5a404SSelvin Xavier /* TIM Buffer */ 5481ac5a404SSelvin Xavier ctx->tim_tbl.max_elements = ctx->qpc_count * 16; 5490c4dcd60SDevesh Sharma hwq_attr.depth = ctx->qpc_count * 16; 5500c4dcd60SDevesh Sharma hwq_attr.stride = 1; 5510c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&ctx->tim_tbl, &hwq_attr); 5521ac5a404SSelvin Xavier if (rc) 5531ac5a404SSelvin Xavier goto fail; 5541ac5a404SSelvin Xavier stats_alloc: 5551ac5a404SSelvin Xavier /* Stats */ 5560c23af52SNaresh Kumar PBS rc = bnxt_qplib_alloc_stats_ctx(res->pdev, res->cctx, &ctx->stats); 5571ac5a404SSelvin Xavier if (rc) 5581ac5a404SSelvin Xavier goto fail; 5591ac5a404SSelvin Xavier 5601ac5a404SSelvin Xavier return 0; 5611ac5a404SSelvin Xavier 5621ac5a404SSelvin Xavier fail: 5630c4dcd60SDevesh Sharma bnxt_qplib_free_ctx(res, ctx); 5641ac5a404SSelvin Xavier return rc; 5651ac5a404SSelvin Xavier } 5661ac5a404SSelvin Xavier 5671ac5a404SSelvin Xavier static void bnxt_qplib_free_sgid_tbl(struct bnxt_qplib_res *res, 5681ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl) 5691ac5a404SSelvin Xavier { 5701ac5a404SSelvin Xavier kfree(sgid_tbl->tbl); 5711ac5a404SSelvin Xavier kfree(sgid_tbl->hw_id); 5721ac5a404SSelvin Xavier kfree(sgid_tbl->ctx); 5735fac5b1bSKalesh AP kfree(sgid_tbl->vlan); 5741ac5a404SSelvin Xavier sgid_tbl->tbl = NULL; 5751ac5a404SSelvin Xavier sgid_tbl->hw_id = NULL; 5761ac5a404SSelvin Xavier sgid_tbl->ctx = NULL; 5775fac5b1bSKalesh AP sgid_tbl->vlan = NULL; 5781ac5a404SSelvin Xavier sgid_tbl->max = 0; 5791ac5a404SSelvin Xavier sgid_tbl->active = 0; 5801ac5a404SSelvin Xavier } 5811ac5a404SSelvin Xavier 5821ac5a404SSelvin Xavier static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res, 5831ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl, 5841ac5a404SSelvin Xavier u16 max) 5851ac5a404SSelvin Xavier { 586c56b593dSSelvin Xavier sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL); 5871ac5a404SSelvin Xavier if (!sgid_tbl->tbl) 5881ac5a404SSelvin Xavier return -ENOMEM; 5891ac5a404SSelvin Xavier 5901ac5a404SSelvin Xavier sgid_tbl->hw_id = kcalloc(max, sizeof(u16), GFP_KERNEL); 5911ac5a404SSelvin Xavier if (!sgid_tbl->hw_id) 5921ac5a404SSelvin Xavier goto out_free1; 5931ac5a404SSelvin Xavier 5941ac5a404SSelvin Xavier sgid_tbl->ctx = kcalloc(max, sizeof(void *), GFP_KERNEL); 5951ac5a404SSelvin Xavier if (!sgid_tbl->ctx) 5961ac5a404SSelvin Xavier goto out_free2; 5971ac5a404SSelvin Xavier 5985fac5b1bSKalesh AP sgid_tbl->vlan = kcalloc(max, sizeof(u8), GFP_KERNEL); 5995fac5b1bSKalesh AP if (!sgid_tbl->vlan) 6005fac5b1bSKalesh AP goto out_free3; 6015fac5b1bSKalesh AP 6021ac5a404SSelvin Xavier sgid_tbl->max = max; 6031ac5a404SSelvin Xavier return 0; 6045fac5b1bSKalesh AP out_free3: 6055fac5b1bSKalesh AP kfree(sgid_tbl->ctx); 6065fac5b1bSKalesh AP sgid_tbl->ctx = NULL; 6071ac5a404SSelvin Xavier out_free2: 6081ac5a404SSelvin Xavier kfree(sgid_tbl->hw_id); 6091ac5a404SSelvin Xavier sgid_tbl->hw_id = NULL; 6101ac5a404SSelvin Xavier out_free1: 6111ac5a404SSelvin Xavier kfree(sgid_tbl->tbl); 6121ac5a404SSelvin Xavier sgid_tbl->tbl = NULL; 6131ac5a404SSelvin Xavier return -ENOMEM; 6141ac5a404SSelvin Xavier }; 6151ac5a404SSelvin Xavier 6161ac5a404SSelvin Xavier static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res, 6171ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl) 6181ac5a404SSelvin Xavier { 6191ac5a404SSelvin Xavier int i; 6201ac5a404SSelvin Xavier 6211ac5a404SSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) { 6221ac5a404SSelvin Xavier if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 6231ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero))) 624c56b593dSSelvin Xavier bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid, 625c56b593dSSelvin Xavier sgid_tbl->tbl[i].vlan_id, true); 6261ac5a404SSelvin Xavier } 627c56b593dSSelvin Xavier memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max); 6281ac5a404SSelvin Xavier memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); 6295fac5b1bSKalesh AP memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max); 6301ac5a404SSelvin Xavier sgid_tbl->active = 0; 6311ac5a404SSelvin Xavier } 6321ac5a404SSelvin Xavier 6331ac5a404SSelvin Xavier static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl, 6341ac5a404SSelvin Xavier struct net_device *netdev) 6351ac5a404SSelvin Xavier { 636c56b593dSSelvin Xavier u32 i; 637c56b593dSSelvin Xavier 638c56b593dSSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) 639c56b593dSSelvin Xavier sgid_tbl->tbl[i].vlan_id = 0xffff; 640c56b593dSSelvin Xavier 6411ac5a404SSelvin Xavier memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); 6421ac5a404SSelvin Xavier } 6431ac5a404SSelvin Xavier 6441ac5a404SSelvin Xavier /* PDs */ 6451ac5a404SSelvin Xavier int bnxt_qplib_alloc_pd(struct bnxt_qplib_pd_tbl *pdt, struct bnxt_qplib_pd *pd) 6461ac5a404SSelvin Xavier { 6471ac5a404SSelvin Xavier u32 bit_num; 6481ac5a404SSelvin Xavier 6491ac5a404SSelvin Xavier bit_num = find_first_bit(pdt->tbl, pdt->max); 6501ac5a404SSelvin Xavier if (bit_num == pdt->max) 6511ac5a404SSelvin Xavier return -ENOMEM; 6521ac5a404SSelvin Xavier 6531ac5a404SSelvin Xavier /* Found unused PD */ 6541ac5a404SSelvin Xavier clear_bit(bit_num, pdt->tbl); 6551ac5a404SSelvin Xavier pd->id = bit_num; 6561ac5a404SSelvin Xavier return 0; 6571ac5a404SSelvin Xavier } 6581ac5a404SSelvin Xavier 6591ac5a404SSelvin Xavier int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res, 6601ac5a404SSelvin Xavier struct bnxt_qplib_pd_tbl *pdt, 6611ac5a404SSelvin Xavier struct bnxt_qplib_pd *pd) 6621ac5a404SSelvin Xavier { 6631ac5a404SSelvin Xavier if (test_and_set_bit(pd->id, pdt->tbl)) { 66408920b8fSJoe Perches dev_warn(&res->pdev->dev, "Freeing an unused PD? pdn = %d\n", 6651ac5a404SSelvin Xavier pd->id); 6661ac5a404SSelvin Xavier return -EINVAL; 6671ac5a404SSelvin Xavier } 6681ac5a404SSelvin Xavier pd->id = 0; 6691ac5a404SSelvin Xavier return 0; 6701ac5a404SSelvin Xavier } 6711ac5a404SSelvin Xavier 6721ac5a404SSelvin Xavier static void bnxt_qplib_free_pd_tbl(struct bnxt_qplib_pd_tbl *pdt) 6731ac5a404SSelvin Xavier { 6741ac5a404SSelvin Xavier kfree(pdt->tbl); 6751ac5a404SSelvin Xavier pdt->tbl = NULL; 6761ac5a404SSelvin Xavier pdt->max = 0; 6771ac5a404SSelvin Xavier } 6781ac5a404SSelvin Xavier 6791ac5a404SSelvin Xavier static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res, 6801ac5a404SSelvin Xavier struct bnxt_qplib_pd_tbl *pdt, 6811ac5a404SSelvin Xavier u32 max) 6821ac5a404SSelvin Xavier { 6831ac5a404SSelvin Xavier u32 bytes; 6841ac5a404SSelvin Xavier 6851ac5a404SSelvin Xavier bytes = max >> 3; 6861ac5a404SSelvin Xavier if (!bytes) 6871ac5a404SSelvin Xavier bytes = 1; 6881ac5a404SSelvin Xavier pdt->tbl = kmalloc(bytes, GFP_KERNEL); 6891ac5a404SSelvin Xavier if (!pdt->tbl) 6901ac5a404SSelvin Xavier return -ENOMEM; 6911ac5a404SSelvin Xavier 6921ac5a404SSelvin Xavier pdt->max = max; 6931ac5a404SSelvin Xavier memset((u8 *)pdt->tbl, 0xFF, bytes); 6941ac5a404SSelvin Xavier 6951ac5a404SSelvin Xavier return 0; 6961ac5a404SSelvin Xavier } 6971ac5a404SSelvin Xavier 6981ac5a404SSelvin Xavier /* DPIs */ 6990ac20fafSSelvin Xavier int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res, 7001ac5a404SSelvin Xavier struct bnxt_qplib_dpi *dpi, 7010ac20fafSSelvin Xavier void *app, u8 type) 7021ac5a404SSelvin Xavier { 7030ac20fafSSelvin Xavier struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; 7040ac20fafSSelvin Xavier struct bnxt_qplib_reg_desc *reg; 7051ac5a404SSelvin Xavier u32 bit_num; 7060ac20fafSSelvin Xavier u64 umaddr; 7070ac20fafSSelvin Xavier 7080ac20fafSSelvin Xavier reg = &dpit->wcreg; 7090ac20fafSSelvin Xavier mutex_lock(&res->dpi_tbl_lock); 7101ac5a404SSelvin Xavier 7111ac5a404SSelvin Xavier bit_num = find_first_bit(dpit->tbl, dpit->max); 7120ac20fafSSelvin Xavier if (bit_num == dpit->max) { 7130ac20fafSSelvin Xavier mutex_unlock(&res->dpi_tbl_lock); 7141ac5a404SSelvin Xavier return -ENOMEM; 7150ac20fafSSelvin Xavier } 7161ac5a404SSelvin Xavier 7171ac5a404SSelvin Xavier /* Found unused DPI */ 7181ac5a404SSelvin Xavier clear_bit(bit_num, dpit->tbl); 7191ac5a404SSelvin Xavier dpit->app_tbl[bit_num] = app; 7201ac5a404SSelvin Xavier 7210ac20fafSSelvin Xavier dpi->bit = bit_num; 7220ac20fafSSelvin Xavier dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE; 7231ac5a404SSelvin Xavier 7240ac20fafSSelvin Xavier umaddr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE; 7250ac20fafSSelvin Xavier dpi->umdbr = umaddr; 7260ac20fafSSelvin Xavier 7270ac20fafSSelvin Xavier switch (type) { 7280ac20fafSSelvin Xavier case BNXT_QPLIB_DPI_TYPE_KERNEL: 729d1d7fc3bSColin Ian King /* privileged dbr was already mapped just initialize it. */ 7300ac20fafSSelvin Xavier dpi->umdbr = dpit->ucreg.bar_base + 7310ac20fafSSelvin Xavier dpit->ucreg.offset + bit_num * PAGE_SIZE; 7320ac20fafSSelvin Xavier dpi->dbr = dpit->priv_db; 7330ac20fafSSelvin Xavier dpi->dpi = dpi->bit; 7340ac20fafSSelvin Xavier break; 735360da60dSSelvin Xavier case BNXT_QPLIB_DPI_TYPE_WC: 736360da60dSSelvin Xavier dpi->dbr = ioremap_wc(umaddr, PAGE_SIZE); 737360da60dSSelvin Xavier break; 7380ac20fafSSelvin Xavier default: 7390ac20fafSSelvin Xavier dpi->dbr = ioremap(umaddr, PAGE_SIZE); 7400ac20fafSSelvin Xavier break; 7410ac20fafSSelvin Xavier } 7420ac20fafSSelvin Xavier 7430ac20fafSSelvin Xavier dpi->type = type; 7440ac20fafSSelvin Xavier mutex_unlock(&res->dpi_tbl_lock); 7451ac5a404SSelvin Xavier return 0; 7460ac20fafSSelvin Xavier 7471ac5a404SSelvin Xavier } 7481ac5a404SSelvin Xavier 7491ac5a404SSelvin Xavier int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res, 7501ac5a404SSelvin Xavier struct bnxt_qplib_dpi *dpi) 7511ac5a404SSelvin Xavier { 7520ac20fafSSelvin Xavier struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; 7530ac20fafSSelvin Xavier 7540ac20fafSSelvin Xavier mutex_lock(&res->dpi_tbl_lock); 7550ac20fafSSelvin Xavier if (dpi->dpi && dpi->type != BNXT_QPLIB_DPI_TYPE_KERNEL) 7560ac20fafSSelvin Xavier pci_iounmap(res->pdev, dpi->dbr); 7570ac20fafSSelvin Xavier 7580ac20fafSSelvin Xavier if (test_and_set_bit(dpi->bit, dpit->tbl)) { 7590ac20fafSSelvin Xavier dev_warn(&res->pdev->dev, 7600ac20fafSSelvin Xavier "Freeing an unused DPI? dpi = %d, bit = %d\n", 7610ac20fafSSelvin Xavier dpi->dpi, dpi->bit); 7620ac20fafSSelvin Xavier mutex_unlock(&res->dpi_tbl_lock); 7631ac5a404SSelvin Xavier return -EINVAL; 7641ac5a404SSelvin Xavier } 7651ac5a404SSelvin Xavier if (dpit->app_tbl) 7660ac20fafSSelvin Xavier dpit->app_tbl[dpi->bit] = NULL; 7671ac5a404SSelvin Xavier memset(dpi, 0, sizeof(*dpi)); 7680ac20fafSSelvin Xavier mutex_unlock(&res->dpi_tbl_lock); 7691ac5a404SSelvin Xavier return 0; 7701ac5a404SSelvin Xavier } 7711ac5a404SSelvin Xavier 7721ac5a404SSelvin Xavier static void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_res *res, 7731ac5a404SSelvin Xavier struct bnxt_qplib_dpi_tbl *dpit) 7741ac5a404SSelvin Xavier { 7751ac5a404SSelvin Xavier kfree(dpit->tbl); 7761ac5a404SSelvin Xavier kfree(dpit->app_tbl); 7770ac20fafSSelvin Xavier dpit->tbl = NULL; 7780ac20fafSSelvin Xavier dpit->app_tbl = NULL; 7790ac20fafSSelvin Xavier dpit->max = 0; 7801ac5a404SSelvin Xavier } 7811ac5a404SSelvin Xavier 7821ac5a404SSelvin Xavier static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, 7830ac20fafSSelvin Xavier struct bnxt_qplib_dev_attr *dev_attr) 7841ac5a404SSelvin Xavier { 7850ac20fafSSelvin Xavier struct bnxt_qplib_dpi_tbl *dpit; 7860ac20fafSSelvin Xavier struct bnxt_qplib_reg_desc *reg; 7870ac20fafSSelvin Xavier unsigned long bar_len; 7880ac20fafSSelvin Xavier u32 dbr_offset; 7890ac20fafSSelvin Xavier u32 bytes; 7901ac5a404SSelvin Xavier 7910ac20fafSSelvin Xavier dpit = &res->dpi_tbl; 7920ac20fafSSelvin Xavier reg = &dpit->wcreg; 7930ac20fafSSelvin Xavier 7940ac20fafSSelvin Xavier if (!bnxt_qplib_is_chip_gen_p5(res->cctx)) { 7950ac20fafSSelvin Xavier /* Offest should come from L2 driver */ 7960ac20fafSSelvin Xavier dbr_offset = dev_attr->l2_db_size; 7970ac20fafSSelvin Xavier dpit->ucreg.offset = dbr_offset; 7980ac20fafSSelvin Xavier dpit->wcreg.offset = dbr_offset; 7991ac5a404SSelvin Xavier } 8001ac5a404SSelvin Xavier 8010ac20fafSSelvin Xavier bar_len = pci_resource_len(res->pdev, reg->bar_id); 8020ac20fafSSelvin Xavier dpit->max = (bar_len - reg->offset) / PAGE_SIZE; 8030ac20fafSSelvin Xavier if (dev_attr->max_dpi) 8040ac20fafSSelvin Xavier dpit->max = min_t(u32, dpit->max, dev_attr->max_dpi); 8051ac5a404SSelvin Xavier 8061ac5a404SSelvin Xavier dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL); 807e5b89843SMarkus Elfring if (!dpit->app_tbl) 8080ac20fafSSelvin Xavier return -ENOMEM; 8091ac5a404SSelvin Xavier 8101ac5a404SSelvin Xavier bytes = dpit->max >> 3; 8111ac5a404SSelvin Xavier if (!bytes) 8121ac5a404SSelvin Xavier bytes = 1; 8131ac5a404SSelvin Xavier 8141ac5a404SSelvin Xavier dpit->tbl = kmalloc(bytes, GFP_KERNEL); 8151ac5a404SSelvin Xavier if (!dpit->tbl) { 8161ac5a404SSelvin Xavier kfree(dpit->app_tbl); 8171ac5a404SSelvin Xavier dpit->app_tbl = NULL; 8180ac20fafSSelvin Xavier return -ENOMEM; 8191ac5a404SSelvin Xavier } 8201ac5a404SSelvin Xavier 8211ac5a404SSelvin Xavier memset((u8 *)dpit->tbl, 0xFF, bytes); 822*64b63265SKashyap Desai mutex_init(&res->dpi_tbl_lock); 8230ac20fafSSelvin Xavier dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; 8241ac5a404SSelvin Xavier 8251ac5a404SSelvin Xavier return 0; 826e5b89843SMarkus Elfring 8271ac5a404SSelvin Xavier } 8281ac5a404SSelvin Xavier 8291ac5a404SSelvin Xavier /* Stats */ 8301ac5a404SSelvin Xavier static void bnxt_qplib_free_stats_ctx(struct pci_dev *pdev, 8311ac5a404SSelvin Xavier struct bnxt_qplib_stats *stats) 8321ac5a404SSelvin Xavier { 8331ac5a404SSelvin Xavier if (stats->dma) { 8341ac5a404SSelvin Xavier dma_free_coherent(&pdev->dev, stats->size, 8351ac5a404SSelvin Xavier stats->dma, stats->dma_map); 8361ac5a404SSelvin Xavier } 8371ac5a404SSelvin Xavier memset(stats, 0, sizeof(*stats)); 8381ac5a404SSelvin Xavier stats->fw_id = -1; 8391ac5a404SSelvin Xavier } 8401ac5a404SSelvin Xavier 8411ac5a404SSelvin Xavier static int bnxt_qplib_alloc_stats_ctx(struct pci_dev *pdev, 8420c23af52SNaresh Kumar PBS struct bnxt_qplib_chip_ctx *cctx, 8431ac5a404SSelvin Xavier struct bnxt_qplib_stats *stats) 8441ac5a404SSelvin Xavier { 8451ac5a404SSelvin Xavier memset(stats, 0, sizeof(*stats)); 8461ac5a404SSelvin Xavier stats->fw_id = -1; 8470c23af52SNaresh Kumar PBS stats->size = cctx->hw_stats_size; 8481ac5a404SSelvin Xavier stats->dma = dma_alloc_coherent(&pdev->dev, stats->size, 8491ac5a404SSelvin Xavier &stats->dma_map, GFP_KERNEL); 8501ac5a404SSelvin Xavier if (!stats->dma) { 85108920b8fSJoe Perches dev_err(&pdev->dev, "Stats DMA allocation failed\n"); 8521ac5a404SSelvin Xavier return -ENOMEM; 8531ac5a404SSelvin Xavier } 8541ac5a404SSelvin Xavier return 0; 8551ac5a404SSelvin Xavier } 8561ac5a404SSelvin Xavier 8571ac5a404SSelvin Xavier void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res) 8581ac5a404SSelvin Xavier { 8591ac5a404SSelvin Xavier bnxt_qplib_cleanup_sgid_tbl(res, &res->sgid_tbl); 8601ac5a404SSelvin Xavier } 8611ac5a404SSelvin Xavier 8621ac5a404SSelvin Xavier int bnxt_qplib_init_res(struct bnxt_qplib_res *res) 8631ac5a404SSelvin Xavier { 8641ac5a404SSelvin Xavier bnxt_qplib_init_sgid_tbl(&res->sgid_tbl, res->netdev); 8651ac5a404SSelvin Xavier 8661ac5a404SSelvin Xavier return 0; 8671ac5a404SSelvin Xavier } 8681ac5a404SSelvin Xavier 8691ac5a404SSelvin Xavier void bnxt_qplib_free_res(struct bnxt_qplib_res *res) 8701ac5a404SSelvin Xavier { 8711ac5a404SSelvin Xavier bnxt_qplib_free_sgid_tbl(res, &res->sgid_tbl); 8721ac5a404SSelvin Xavier bnxt_qplib_free_pd_tbl(&res->pd_tbl); 8731ac5a404SSelvin Xavier bnxt_qplib_free_dpi_tbl(res, &res->dpi_tbl); 8741ac5a404SSelvin Xavier } 8751ac5a404SSelvin Xavier 8761ac5a404SSelvin Xavier int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev, 8771ac5a404SSelvin Xavier struct net_device *netdev, 8781ac5a404SSelvin Xavier struct bnxt_qplib_dev_attr *dev_attr) 8791ac5a404SSelvin Xavier { 8801ac5a404SSelvin Xavier int rc = 0; 8811ac5a404SSelvin Xavier 8821ac5a404SSelvin Xavier res->pdev = pdev; 8831ac5a404SSelvin Xavier res->netdev = netdev; 8841ac5a404SSelvin Xavier 8851ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_sgid_tbl(res, &res->sgid_tbl, dev_attr->max_sgid); 8861ac5a404SSelvin Xavier if (rc) 8871ac5a404SSelvin Xavier goto fail; 8881ac5a404SSelvin Xavier 8891ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_pd_tbl(res, &res->pd_tbl, dev_attr->max_pd); 8901ac5a404SSelvin Xavier if (rc) 8911ac5a404SSelvin Xavier goto fail; 8921ac5a404SSelvin Xavier 8930ac20fafSSelvin Xavier rc = bnxt_qplib_alloc_dpi_tbl(res, dev_attr); 8941ac5a404SSelvin Xavier if (rc) 8951ac5a404SSelvin Xavier goto fail; 8961ac5a404SSelvin Xavier 8971ac5a404SSelvin Xavier return 0; 8981ac5a404SSelvin Xavier fail: 8991ac5a404SSelvin Xavier bnxt_qplib_free_res(res); 9001ac5a404SSelvin Xavier return rc; 9011ac5a404SSelvin Xavier } 90235f5ace5SDevesh Sharma 9030ac20fafSSelvin Xavier void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res) 9040ac20fafSSelvin Xavier { 9050ac20fafSSelvin Xavier struct bnxt_qplib_reg_desc *reg; 9060ac20fafSSelvin Xavier 9070ac20fafSSelvin Xavier reg = &res->dpi_tbl.ucreg; 9080ac20fafSSelvin Xavier if (reg->bar_reg) 9090ac20fafSSelvin Xavier pci_iounmap(res->pdev, reg->bar_reg); 9100ac20fafSSelvin Xavier reg->bar_reg = NULL; 9110ac20fafSSelvin Xavier reg->bar_base = 0; 9120ac20fafSSelvin Xavier reg->len = 0; 9130ac20fafSSelvin Xavier reg->bar_id = 0; 9140ac20fafSSelvin Xavier } 9150ac20fafSSelvin Xavier 9160ac20fafSSelvin Xavier int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res) 9170ac20fafSSelvin Xavier { 9180ac20fafSSelvin Xavier struct bnxt_qplib_reg_desc *ucreg; 9190ac20fafSSelvin Xavier struct bnxt_qplib_reg_desc *wcreg; 9200ac20fafSSelvin Xavier 9210ac20fafSSelvin Xavier wcreg = &res->dpi_tbl.wcreg; 9220ac20fafSSelvin Xavier wcreg->bar_id = RCFW_DBR_PCI_BAR_REGION; 9230ac20fafSSelvin Xavier wcreg->bar_base = pci_resource_start(res->pdev, wcreg->bar_id); 9240ac20fafSSelvin Xavier 9250ac20fafSSelvin Xavier ucreg = &res->dpi_tbl.ucreg; 9260ac20fafSSelvin Xavier ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION; 9270ac20fafSSelvin Xavier ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id); 9280ac20fafSSelvin Xavier ucreg->len = ucreg->offset + PAGE_SIZE; 9290ac20fafSSelvin Xavier if (!ucreg->len || ((ucreg->len & (PAGE_SIZE - 1)) != 0)) { 9300ac20fafSSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: invalid dbr length %d", 9310ac20fafSSelvin Xavier (int)ucreg->len); 9320ac20fafSSelvin Xavier return -EINVAL; 9330ac20fafSSelvin Xavier } 9340ac20fafSSelvin Xavier ucreg->bar_reg = ioremap(ucreg->bar_base, ucreg->len); 9350ac20fafSSelvin Xavier if (!ucreg->bar_reg) { 936d1d7fc3bSColin Ian King dev_err(&res->pdev->dev, "privileged dpi map failed!"); 9370ac20fafSSelvin Xavier return -ENOMEM; 9380ac20fafSSelvin Xavier } 9390ac20fafSSelvin Xavier 9400ac20fafSSelvin Xavier return 0; 9410ac20fafSSelvin Xavier } 9420ac20fafSSelvin Xavier 94335f5ace5SDevesh Sharma int bnxt_qplib_determine_atomics(struct pci_dev *dev) 94435f5ace5SDevesh Sharma { 94535f5ace5SDevesh Sharma int comp; 94635f5ace5SDevesh Sharma u16 ctl2; 94735f5ace5SDevesh Sharma 94835f5ace5SDevesh Sharma comp = pci_enable_atomic_ops_to_root(dev, 94935f5ace5SDevesh Sharma PCI_EXP_DEVCAP2_ATOMIC_COMP32); 95035f5ace5SDevesh Sharma if (comp) 95135f5ace5SDevesh Sharma return -EOPNOTSUPP; 95235f5ace5SDevesh Sharma comp = pci_enable_atomic_ops_to_root(dev, 95335f5ace5SDevesh Sharma PCI_EXP_DEVCAP2_ATOMIC_COMP64); 95435f5ace5SDevesh Sharma if (comp) 95535f5ace5SDevesh Sharma return -EOPNOTSUPP; 95635f5ace5SDevesh Sharma pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctl2); 95735f5ace5SDevesh Sharma return !(ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ); 95835f5ace5SDevesh Sharma } 959