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: Slow Path Operators 371ac5a404SSelvin Xavier */ 381ac5a404SSelvin Xavier 391ac5a404SSelvin Xavier #include <linux/interrupt.h> 401ac5a404SSelvin Xavier #include <linux/spinlock.h> 411ac5a404SSelvin Xavier #include <linux/sched.h> 421ac5a404SSelvin Xavier #include <linux/pci.h> 431ac5a404SSelvin Xavier 441ac5a404SSelvin Xavier #include "roce_hsi.h" 451ac5a404SSelvin Xavier 461ac5a404SSelvin Xavier #include "qplib_res.h" 471ac5a404SSelvin Xavier #include "qplib_rcfw.h" 481ac5a404SSelvin Xavier #include "qplib_sp.h" 491ac5a404SSelvin Xavier 501ac5a404SSelvin Xavier const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 511ac5a404SSelvin Xavier 0, 0, 0, 0, 0, 0, 0, 0 } }; 521ac5a404SSelvin Xavier 531ac5a404SSelvin Xavier /* Device */ 541ac5a404SSelvin Xavier int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, 551ac5a404SSelvin Xavier struct bnxt_qplib_dev_attr *attr) 561ac5a404SSelvin Xavier { 571ac5a404SSelvin Xavier struct cmdq_query_func req; 58cc1ec769SDevesh Sharma struct creq_query_func_resp resp; 59cc1ec769SDevesh Sharma struct bnxt_qplib_rcfw_sbuf *sbuf; 601ac5a404SSelvin Xavier struct creq_query_func_resp_sb *sb; 611ac5a404SSelvin Xavier u16 cmd_flags = 0; 621ac5a404SSelvin Xavier u32 temp; 631ac5a404SSelvin Xavier u8 *tqm_alloc; 64cc1ec769SDevesh Sharma int i, rc = 0; 651ac5a404SSelvin Xavier 661ac5a404SSelvin Xavier RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags); 671ac5a404SSelvin Xavier 68cc1ec769SDevesh Sharma sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 69cc1ec769SDevesh Sharma if (!sbuf) { 701ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 71cc1ec769SDevesh Sharma "QPLIB: SP: QUERY_FUNC alloc side buffer failed"); 72cc1ec769SDevesh Sharma return -ENOMEM; 731ac5a404SSelvin Xavier } 74cc1ec769SDevesh Sharma 75cc1ec769SDevesh Sharma sb = sbuf->sb; 76cc1ec769SDevesh Sharma req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 77cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 78cc1ec769SDevesh Sharma (void *)sbuf, 0); 79cc1ec769SDevesh Sharma if (rc) 80cc1ec769SDevesh Sharma goto bail; 81cc1ec769SDevesh Sharma 821ac5a404SSelvin Xavier /* Extract the context from the side buffer */ 831ac5a404SSelvin Xavier attr->max_qp = le32_to_cpu(sb->max_qp); 84*58d4a671SSelvin Xavier /* max_qp value reported by FW for PF doesn't include the QP1 for PF */ 85*58d4a671SSelvin Xavier attr->max_qp += 1; 861ac5a404SSelvin Xavier attr->max_qp_rd_atom = 871ac5a404SSelvin Xavier sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 881ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; 891ac5a404SSelvin Xavier attr->max_qp_init_rd_atom = 901ac5a404SSelvin Xavier sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 911ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; 921ac5a404SSelvin Xavier attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); 939152e0b7SEddie Wai /* 949152e0b7SEddie Wai * 128 WQEs needs to be reserved for the HW (8916). Prevent 959152e0b7SEddie Wai * reporting the max number 969152e0b7SEddie Wai */ 979152e0b7SEddie Wai attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS; 981ac5a404SSelvin Xavier attr->max_qp_sges = sb->max_sge; 991ac5a404SSelvin Xavier attr->max_cq = le32_to_cpu(sb->max_cq); 1001ac5a404SSelvin Xavier attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 1011ac5a404SSelvin Xavier attr->max_cq_sges = attr->max_qp_sges; 1021ac5a404SSelvin Xavier attr->max_mr = le32_to_cpu(sb->max_mr); 1031ac5a404SSelvin Xavier attr->max_mw = le32_to_cpu(sb->max_mw); 1041ac5a404SSelvin Xavier 1051ac5a404SSelvin Xavier attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 1061ac5a404SSelvin Xavier attr->max_pd = 64 * 1024; 1071ac5a404SSelvin Xavier attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 1081ac5a404SSelvin Xavier attr->max_ah = le32_to_cpu(sb->max_ah); 1091ac5a404SSelvin Xavier 1101ac5a404SSelvin Xavier attr->max_fmr = le32_to_cpu(sb->max_fmr); 1111ac5a404SSelvin Xavier attr->max_map_per_fmr = sb->max_map_per_fmr; 1121ac5a404SSelvin Xavier 1131ac5a404SSelvin Xavier attr->max_srq = le16_to_cpu(sb->max_srq); 1141ac5a404SSelvin Xavier attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 1151ac5a404SSelvin Xavier attr->max_srq_sges = sb->max_srq_sge; 1161ac5a404SSelvin Xavier /* Bono only reports 1 PKEY for now, but it can support > 1 */ 1171ac5a404SSelvin Xavier attr->max_pkey = le32_to_cpu(sb->max_pkeys); 1181ac5a404SSelvin Xavier 1191ac5a404SSelvin Xavier attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 1201ac5a404SSelvin Xavier attr->l2_db_size = (sb->l2_db_space_size + 1) * PAGE_SIZE; 1211ac5a404SSelvin Xavier attr->max_sgid = le32_to_cpu(sb->max_gid); 1221ac5a404SSelvin Xavier 1231ac5a404SSelvin Xavier strlcpy(attr->fw_ver, "20.6.28.0", sizeof(attr->fw_ver)); 1241ac5a404SSelvin Xavier 1251ac5a404SSelvin Xavier for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 1261ac5a404SSelvin Xavier temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 1271ac5a404SSelvin Xavier tqm_alloc = (u8 *)&temp; 1281ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 1291ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 1301ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 1311ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 1321ac5a404SSelvin Xavier } 133cc1ec769SDevesh Sharma 134cc1ec769SDevesh Sharma bail: 135cc1ec769SDevesh Sharma bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 136cc1ec769SDevesh Sharma return rc; 1371ac5a404SSelvin Xavier } 1381ac5a404SSelvin Xavier 1391ac5a404SSelvin Xavier /* SGID */ 1401ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 1411ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 1421ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid) 1431ac5a404SSelvin Xavier { 1441ac5a404SSelvin Xavier if (index > sgid_tbl->max) { 1451ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 1461ac5a404SSelvin Xavier "QPLIB: Index %d exceeded SGID table max (%d)", 1471ac5a404SSelvin Xavier index, sgid_tbl->max); 1481ac5a404SSelvin Xavier return -EINVAL; 1491ac5a404SSelvin Xavier } 1501ac5a404SSelvin Xavier memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid)); 1511ac5a404SSelvin Xavier return 0; 1521ac5a404SSelvin Xavier } 1531ac5a404SSelvin Xavier 1541ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 1551ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, bool update) 1561ac5a404SSelvin Xavier { 1571ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 1581ac5a404SSelvin Xavier struct bnxt_qplib_res, 1591ac5a404SSelvin Xavier sgid_tbl); 1601ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 1611ac5a404SSelvin Xavier int index; 1621ac5a404SSelvin Xavier 1631ac5a404SSelvin Xavier if (!sgid_tbl) { 1641ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated"); 1651ac5a404SSelvin Xavier return -EINVAL; 1661ac5a404SSelvin Xavier } 1671ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 1681ac5a404SSelvin Xavier if (!sgid_tbl->active) { 1691ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 1701ac5a404SSelvin Xavier "QPLIB: SGID table has no active entries"); 1711ac5a404SSelvin Xavier return -ENOMEM; 1721ac5a404SSelvin Xavier } 1731ac5a404SSelvin Xavier for (index = 0; index < sgid_tbl->max; index++) { 1741ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid))) 1751ac5a404SSelvin Xavier break; 1761ac5a404SSelvin Xavier } 1771ac5a404SSelvin Xavier if (index == sgid_tbl->max) { 1781ac5a404SSelvin Xavier dev_warn(&res->pdev->dev, "GID not found in the SGID table"); 1791ac5a404SSelvin Xavier return 0; 1801ac5a404SSelvin Xavier } 1811ac5a404SSelvin Xavier /* Remove GID from the SGID table */ 1821ac5a404SSelvin Xavier if (update) { 1831ac5a404SSelvin Xavier struct cmdq_delete_gid req; 184cc1ec769SDevesh Sharma struct creq_delete_gid_resp resp; 1851ac5a404SSelvin Xavier u16 cmd_flags = 0; 186cc1ec769SDevesh Sharma int rc; 1871ac5a404SSelvin Xavier 1881ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); 1891ac5a404SSelvin Xavier if (sgid_tbl->hw_id[index] == 0xFFFF) { 1901ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 1911ac5a404SSelvin Xavier "QPLIB: GID entry contains an invalid HW id"); 1921ac5a404SSelvin Xavier return -EINVAL; 1931ac5a404SSelvin Xavier } 1941ac5a404SSelvin Xavier req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 195cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 196cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 197cc1ec769SDevesh Sharma if (rc) 198cc1ec769SDevesh Sharma return rc; 1991ac5a404SSelvin Xavier } 2001ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, 2011ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)); 2021ac5a404SSelvin Xavier sgid_tbl->active--; 2031ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 2041ac5a404SSelvin Xavier "QPLIB: SGID deleted hw_id[0x%x] = 0x%x active = 0x%x", 2051ac5a404SSelvin Xavier index, sgid_tbl->hw_id[index], sgid_tbl->active); 2061ac5a404SSelvin Xavier sgid_tbl->hw_id[index] = (u16)-1; 2071ac5a404SSelvin Xavier 2081ac5a404SSelvin Xavier /* unlock */ 2091ac5a404SSelvin Xavier return 0; 2101ac5a404SSelvin Xavier } 2111ac5a404SSelvin Xavier 2121ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2131ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id, 2141ac5a404SSelvin Xavier bool update, u32 *index) 2151ac5a404SSelvin Xavier { 2161ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2171ac5a404SSelvin Xavier struct bnxt_qplib_res, 2181ac5a404SSelvin Xavier sgid_tbl); 2191ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 220cc1ec769SDevesh Sharma int i, free_idx; 2211ac5a404SSelvin Xavier 2221ac5a404SSelvin Xavier if (!sgid_tbl) { 2231ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated"); 2241ac5a404SSelvin Xavier return -EINVAL; 2251ac5a404SSelvin Xavier } 2261ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 2271ac5a404SSelvin Xavier if (sgid_tbl->active == sgid_tbl->max) { 2281ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table is full"); 2291ac5a404SSelvin Xavier return -ENOMEM; 2301ac5a404SSelvin Xavier } 2311ac5a404SSelvin Xavier free_idx = sgid_tbl->max; 2321ac5a404SSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) { 2331ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) { 2341ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 2351ac5a404SSelvin Xavier "QPLIB: SGID entry already exist in entry %d!", 2361ac5a404SSelvin Xavier i); 2371ac5a404SSelvin Xavier *index = i; 2381ac5a404SSelvin Xavier return -EALREADY; 2391ac5a404SSelvin Xavier } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 2401ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)) && 2411ac5a404SSelvin Xavier free_idx == sgid_tbl->max) { 2421ac5a404SSelvin Xavier free_idx = i; 2431ac5a404SSelvin Xavier } 2441ac5a404SSelvin Xavier } 2451ac5a404SSelvin Xavier if (free_idx == sgid_tbl->max) { 2461ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 2471ac5a404SSelvin Xavier "QPLIB: SGID table is FULL but count is not MAX??"); 2481ac5a404SSelvin Xavier return -ENOMEM; 2491ac5a404SSelvin Xavier } 2501ac5a404SSelvin Xavier if (update) { 2511ac5a404SSelvin Xavier struct cmdq_add_gid req; 252cc1ec769SDevesh Sharma struct creq_add_gid_resp resp; 2531ac5a404SSelvin Xavier u16 cmd_flags = 0; 2541ac5a404SSelvin Xavier u32 temp32[4]; 2551ac5a404SSelvin Xavier u16 temp16[3]; 256cc1ec769SDevesh Sharma int rc; 2571ac5a404SSelvin Xavier 2581ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ADD_GID, cmd_flags); 2591ac5a404SSelvin Xavier 2601ac5a404SSelvin Xavier memcpy(temp32, gid->data, sizeof(struct bnxt_qplib_gid)); 2611ac5a404SSelvin Xavier req.gid[0] = cpu_to_be32(temp32[3]); 2621ac5a404SSelvin Xavier req.gid[1] = cpu_to_be32(temp32[2]); 2631ac5a404SSelvin Xavier req.gid[2] = cpu_to_be32(temp32[1]); 2641ac5a404SSelvin Xavier req.gid[3] = cpu_to_be32(temp32[0]); 2651ac5a404SSelvin Xavier if (vlan_id != 0xFFFF) 2661ac5a404SSelvin Xavier req.vlan = cpu_to_le16((vlan_id & 2671ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_ID_MASK) | 2681ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 2691ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_EN); 2701ac5a404SSelvin Xavier 2711ac5a404SSelvin Xavier /* MAC in network format */ 2721ac5a404SSelvin Xavier memcpy(temp16, smac, 6); 2731ac5a404SSelvin Xavier req.src_mac[0] = cpu_to_be16(temp16[0]); 2741ac5a404SSelvin Xavier req.src_mac[1] = cpu_to_be16(temp16[1]); 2751ac5a404SSelvin Xavier req.src_mac[2] = cpu_to_be16(temp16[2]); 2761ac5a404SSelvin Xavier 277cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 278cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 279cc1ec769SDevesh Sharma if (rc) 280cc1ec769SDevesh Sharma return rc; 281cc1ec769SDevesh Sharma sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); 2821ac5a404SSelvin Xavier } 2831ac5a404SSelvin Xavier /* Add GID to the sgid_tbl */ 2841ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 2851ac5a404SSelvin Xavier sgid_tbl->active++; 2861ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 2871ac5a404SSelvin Xavier "QPLIB: SGID added hw_id[0x%x] = 0x%x active = 0x%x", 2881ac5a404SSelvin Xavier free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 2891ac5a404SSelvin Xavier 2901ac5a404SSelvin Xavier *index = free_idx; 2911ac5a404SSelvin Xavier /* unlock */ 292cc1ec769SDevesh Sharma return 0; 2931ac5a404SSelvin Xavier } 2941ac5a404SSelvin Xavier 2951ac5a404SSelvin Xavier /* pkeys */ 2961ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, 2971ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index, 2981ac5a404SSelvin Xavier u16 *pkey) 2991ac5a404SSelvin Xavier { 3001ac5a404SSelvin Xavier if (index == 0xFFFF) { 3011ac5a404SSelvin Xavier *pkey = 0xFFFF; 3021ac5a404SSelvin Xavier return 0; 3031ac5a404SSelvin Xavier } 3041ac5a404SSelvin Xavier if (index > pkey_tbl->max) { 3051ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 3061ac5a404SSelvin Xavier "QPLIB: Index %d exceeded PKEY table max (%d)", 3071ac5a404SSelvin Xavier index, pkey_tbl->max); 3081ac5a404SSelvin Xavier return -EINVAL; 3091ac5a404SSelvin Xavier } 3101ac5a404SSelvin Xavier memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey)); 3111ac5a404SSelvin Xavier return 0; 3121ac5a404SSelvin Xavier } 3131ac5a404SSelvin Xavier 3141ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res, 3151ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 3161ac5a404SSelvin Xavier bool update) 3171ac5a404SSelvin Xavier { 3181ac5a404SSelvin Xavier int i, rc = 0; 3191ac5a404SSelvin Xavier 3201ac5a404SSelvin Xavier if (!pkey_tbl) { 3211ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated"); 3221ac5a404SSelvin Xavier return -EINVAL; 3231ac5a404SSelvin Xavier } 3241ac5a404SSelvin Xavier 3251ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 3261ac5a404SSelvin Xavier if (!pkey_tbl->active) { 3271ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 3281ac5a404SSelvin Xavier "QPLIB: PKEY table has no active entries"); 3291ac5a404SSelvin Xavier return -ENOMEM; 3301ac5a404SSelvin Xavier } 3311ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 3321ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 3331ac5a404SSelvin Xavier break; 3341ac5a404SSelvin Xavier } 3351ac5a404SSelvin Xavier if (i == pkey_tbl->max) { 3361ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 3371ac5a404SSelvin Xavier "QPLIB: PKEY 0x%04x not found in the pkey table", 3381ac5a404SSelvin Xavier *pkey); 3391ac5a404SSelvin Xavier return -ENOMEM; 3401ac5a404SSelvin Xavier } 3411ac5a404SSelvin Xavier memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey)); 3421ac5a404SSelvin Xavier pkey_tbl->active--; 3431ac5a404SSelvin Xavier 3441ac5a404SSelvin Xavier /* unlock */ 3451ac5a404SSelvin Xavier return rc; 3461ac5a404SSelvin Xavier } 3471ac5a404SSelvin Xavier 3481ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, 3491ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 3501ac5a404SSelvin Xavier bool update) 3511ac5a404SSelvin Xavier { 3521ac5a404SSelvin Xavier int i, free_idx, rc = 0; 3531ac5a404SSelvin Xavier 3541ac5a404SSelvin Xavier if (!pkey_tbl) { 3551ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated"); 3561ac5a404SSelvin Xavier return -EINVAL; 3571ac5a404SSelvin Xavier } 3581ac5a404SSelvin Xavier 3591ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 3601ac5a404SSelvin Xavier if (pkey_tbl->active == pkey_tbl->max) { 3611ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table is full"); 3621ac5a404SSelvin Xavier return -ENOMEM; 3631ac5a404SSelvin Xavier } 3641ac5a404SSelvin Xavier free_idx = pkey_tbl->max; 3651ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 3661ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 3671ac5a404SSelvin Xavier return -EALREADY; 3681ac5a404SSelvin Xavier else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max) 3691ac5a404SSelvin Xavier free_idx = i; 3701ac5a404SSelvin Xavier } 3711ac5a404SSelvin Xavier if (free_idx == pkey_tbl->max) { 3721ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 3731ac5a404SSelvin Xavier "QPLIB: PKEY table is FULL but count is not MAX??"); 3741ac5a404SSelvin Xavier return -ENOMEM; 3751ac5a404SSelvin Xavier } 3761ac5a404SSelvin Xavier /* Add PKEY to the pkey_tbl */ 3771ac5a404SSelvin Xavier memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey)); 3781ac5a404SSelvin Xavier pkey_tbl->active++; 3791ac5a404SSelvin Xavier 3801ac5a404SSelvin Xavier /* unlock */ 3811ac5a404SSelvin Xavier return rc; 3821ac5a404SSelvin Xavier } 3831ac5a404SSelvin Xavier 3841ac5a404SSelvin Xavier /* AH */ 3851ac5a404SSelvin Xavier int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 3861ac5a404SSelvin Xavier { 3871ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 3881ac5a404SSelvin Xavier struct cmdq_create_ah req; 389cc1ec769SDevesh Sharma struct creq_create_ah_resp resp; 3901ac5a404SSelvin Xavier u16 cmd_flags = 0; 3911ac5a404SSelvin Xavier u32 temp32[4]; 3921ac5a404SSelvin Xavier u16 temp16[3]; 393cc1ec769SDevesh Sharma int rc; 3941ac5a404SSelvin Xavier 3951ac5a404SSelvin Xavier RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); 3961ac5a404SSelvin Xavier 3971ac5a404SSelvin Xavier memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 3981ac5a404SSelvin Xavier req.dgid[0] = cpu_to_le32(temp32[0]); 3991ac5a404SSelvin Xavier req.dgid[1] = cpu_to_le32(temp32[1]); 4001ac5a404SSelvin Xavier req.dgid[2] = cpu_to_le32(temp32[2]); 4011ac5a404SSelvin Xavier req.dgid[3] = cpu_to_le32(temp32[3]); 4021ac5a404SSelvin Xavier 4031ac5a404SSelvin Xavier req.type = ah->nw_type; 4041ac5a404SSelvin Xavier req.hop_limit = ah->hop_limit; 4051ac5a404SSelvin Xavier req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 4061ac5a404SSelvin Xavier req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 4071ac5a404SSelvin Xavier CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 4081ac5a404SSelvin Xavier CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 4091ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(ah->pd->id); 4101ac5a404SSelvin Xavier req.traffic_class = ah->traffic_class; 4111ac5a404SSelvin Xavier 4121ac5a404SSelvin Xavier /* MAC in network format */ 4131ac5a404SSelvin Xavier memcpy(temp16, ah->dmac, 6); 4141ac5a404SSelvin Xavier req.dest_mac[0] = cpu_to_le16(temp16[0]); 4151ac5a404SSelvin Xavier req.dest_mac[1] = cpu_to_le16(temp16[1]); 4161ac5a404SSelvin Xavier req.dest_mac[2] = cpu_to_le16(temp16[2]); 4171ac5a404SSelvin Xavier 418cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 4191ac5a404SSelvin Xavier NULL, 1); 420cc1ec769SDevesh Sharma if (rc) 421cc1ec769SDevesh Sharma return rc; 422cc1ec769SDevesh Sharma 423cc1ec769SDevesh Sharma ah->id = le32_to_cpu(resp.xid); 4241ac5a404SSelvin Xavier return 0; 4251ac5a404SSelvin Xavier } 4261ac5a404SSelvin Xavier 4271ac5a404SSelvin Xavier int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 4281ac5a404SSelvin Xavier { 4291ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4301ac5a404SSelvin Xavier struct cmdq_destroy_ah req; 431cc1ec769SDevesh Sharma struct creq_destroy_ah_resp resp; 4321ac5a404SSelvin Xavier u16 cmd_flags = 0; 433cc1ec769SDevesh Sharma int rc; 4341ac5a404SSelvin Xavier 4351ac5a404SSelvin Xavier /* Clean up the AH table in the device */ 4361ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); 4371ac5a404SSelvin Xavier 4381ac5a404SSelvin Xavier req.ah_cid = cpu_to_le32(ah->id); 4391ac5a404SSelvin Xavier 440cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 4411ac5a404SSelvin Xavier NULL, 1); 442cc1ec769SDevesh Sharma if (rc) 443cc1ec769SDevesh Sharma return rc; 4441ac5a404SSelvin Xavier return 0; 4451ac5a404SSelvin Xavier } 4461ac5a404SSelvin Xavier 4471ac5a404SSelvin Xavier /* MRW */ 4481ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 4491ac5a404SSelvin Xavier { 4501ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4511ac5a404SSelvin Xavier struct cmdq_deallocate_key req; 452cc1ec769SDevesh Sharma struct creq_deallocate_key_resp resp; 4531ac5a404SSelvin Xavier u16 cmd_flags = 0; 454cc1ec769SDevesh Sharma int rc; 4551ac5a404SSelvin Xavier 4561ac5a404SSelvin Xavier if (mrw->lkey == 0xFFFFFFFF) { 4571ac5a404SSelvin Xavier dev_info(&res->pdev->dev, 4581ac5a404SSelvin Xavier "QPLIB: SP: Free a reserved lkey MRW"); 4591ac5a404SSelvin Xavier return 0; 4601ac5a404SSelvin Xavier } 4611ac5a404SSelvin Xavier 4621ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags); 4631ac5a404SSelvin Xavier 4641ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 4651ac5a404SSelvin Xavier 4661ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 4671ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 4681ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 4691ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->rkey); 4701ac5a404SSelvin Xavier else 4711ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->lkey); 4721ac5a404SSelvin Xavier 473cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 4741ac5a404SSelvin Xavier NULL, 0); 475cc1ec769SDevesh Sharma if (rc) 476cc1ec769SDevesh Sharma return rc; 477cc1ec769SDevesh Sharma 4781ac5a404SSelvin Xavier /* Free the qplib's MRW memory */ 4791ac5a404SSelvin Xavier if (mrw->hwq.max_elements) 4801ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 4811ac5a404SSelvin Xavier 4821ac5a404SSelvin Xavier return 0; 4831ac5a404SSelvin Xavier } 4841ac5a404SSelvin Xavier 4851ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 4861ac5a404SSelvin Xavier { 4871ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4881ac5a404SSelvin Xavier struct cmdq_allocate_mrw req; 489cc1ec769SDevesh Sharma struct creq_allocate_mrw_resp resp; 4901ac5a404SSelvin Xavier u16 cmd_flags = 0; 4911ac5a404SSelvin Xavier unsigned long tmp; 492cc1ec769SDevesh Sharma int rc; 4931ac5a404SSelvin Xavier 4941ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); 4951ac5a404SSelvin Xavier 4961ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(mrw->pd->id); 4971ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 4981ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 4991ac5a404SSelvin Xavier mrw->flags & BNXT_QPLIB_FR_PMR) || 5001ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 5011ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 5021ac5a404SSelvin Xavier req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 5031ac5a404SSelvin Xavier tmp = (unsigned long)mrw; 5041ac5a404SSelvin Xavier req.mrw_handle = cpu_to_le64(tmp); 5051ac5a404SSelvin Xavier 506cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 507cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 508cc1ec769SDevesh Sharma if (rc) 509cc1ec769SDevesh Sharma return rc; 510cc1ec769SDevesh Sharma 5111ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 5121ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 5131ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 514cc1ec769SDevesh Sharma mrw->rkey = le32_to_cpu(resp.xid); 5151ac5a404SSelvin Xavier else 516cc1ec769SDevesh Sharma mrw->lkey = le32_to_cpu(resp.xid); 5171ac5a404SSelvin Xavier return 0; 5181ac5a404SSelvin Xavier } 5191ac5a404SSelvin Xavier 5201ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 5211ac5a404SSelvin Xavier bool block) 5221ac5a404SSelvin Xavier { 5231ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5241ac5a404SSelvin Xavier struct cmdq_deregister_mr req; 525cc1ec769SDevesh Sharma struct creq_deregister_mr_resp resp; 5261ac5a404SSelvin Xavier u16 cmd_flags = 0; 5271ac5a404SSelvin Xavier int rc; 5281ac5a404SSelvin Xavier 5291ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); 5301ac5a404SSelvin Xavier 5311ac5a404SSelvin Xavier req.lkey = cpu_to_le32(mrw->lkey); 532cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 533cc1ec769SDevesh Sharma (void *)&resp, NULL, block); 534cc1ec769SDevesh Sharma if (rc) 535cc1ec769SDevesh Sharma return rc; 5361ac5a404SSelvin Xavier 5371ac5a404SSelvin Xavier /* Free the qplib's MR memory */ 5381ac5a404SSelvin Xavier if (mrw->hwq.max_elements) { 5391ac5a404SSelvin Xavier mrw->va = 0; 5401ac5a404SSelvin Xavier mrw->total_size = 0; 5411ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 5421ac5a404SSelvin Xavier } 5431ac5a404SSelvin Xavier 5441ac5a404SSelvin Xavier return 0; 5451ac5a404SSelvin Xavier } 5461ac5a404SSelvin Xavier 5471ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 5481ac5a404SSelvin Xavier u64 *pbl_tbl, int num_pbls, bool block) 5491ac5a404SSelvin Xavier { 5501ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5511ac5a404SSelvin Xavier struct cmdq_register_mr req; 552cc1ec769SDevesh Sharma struct creq_register_mr_resp resp; 5531ac5a404SSelvin Xavier u16 cmd_flags = 0, level; 5541ac5a404SSelvin Xavier int pg_ptrs, pages, i, rc; 5551ac5a404SSelvin Xavier dma_addr_t **pbl_ptr; 5561ac5a404SSelvin Xavier u32 pg_size; 5571ac5a404SSelvin Xavier 5581ac5a404SSelvin Xavier if (num_pbls) { 5591ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(num_pbls); 5601ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 5611ac5a404SSelvin Xavier if (!pages) 5621ac5a404SSelvin Xavier pages++; 5631ac5a404SSelvin Xavier 5641ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) { 5651ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: Reg MR pages "); 5661ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 5671ac5a404SSelvin Xavier "requested (0x%x) exceeded max (0x%x)", 5681ac5a404SSelvin Xavier pages, MAX_PBL_LVL_1_PGS); 5691ac5a404SSelvin Xavier return -ENOMEM; 5701ac5a404SSelvin Xavier } 5711ac5a404SSelvin Xavier /* Free the hwq if it already exist, must be a rereg */ 5721ac5a404SSelvin Xavier if (mr->hwq.max_elements) 5731ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 5741ac5a404SSelvin Xavier 5751ac5a404SSelvin Xavier mr->hwq.max_elements = pages; 5761ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0, 5771ac5a404SSelvin Xavier &mr->hwq.max_elements, 5781ac5a404SSelvin Xavier PAGE_SIZE, 0, PAGE_SIZE, 5791ac5a404SSelvin Xavier HWQ_TYPE_CTX); 5801ac5a404SSelvin Xavier if (rc) { 5811ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 5821ac5a404SSelvin Xavier "SP: Reg MR memory allocation failed"); 5831ac5a404SSelvin Xavier return -ENOMEM; 5841ac5a404SSelvin Xavier } 5851ac5a404SSelvin Xavier /* Write to the hwq */ 5861ac5a404SSelvin Xavier pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr; 5871ac5a404SSelvin Xavier for (i = 0; i < num_pbls; i++) 5881ac5a404SSelvin Xavier pbl_ptr[PTR_PG(i)][PTR_IDX(i)] = 5891ac5a404SSelvin Xavier (pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID; 5901ac5a404SSelvin Xavier } 5911ac5a404SSelvin Xavier 5921ac5a404SSelvin Xavier RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); 5931ac5a404SSelvin Xavier 5941ac5a404SSelvin Xavier /* Configure the request */ 5951ac5a404SSelvin Xavier if (mr->hwq.level == PBL_LVL_MAX) { 5961ac5a404SSelvin Xavier level = 0; 5971ac5a404SSelvin Xavier req.pbl = 0; 5981ac5a404SSelvin Xavier pg_size = PAGE_SIZE; 5991ac5a404SSelvin Xavier } else { 6001ac5a404SSelvin Xavier level = mr->hwq.level + 1; 6011ac5a404SSelvin Xavier req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 6021ac5a404SSelvin Xavier pg_size = mr->hwq.pbl[PBL_LVL_0].pg_size; 6031ac5a404SSelvin Xavier } 6041ac5a404SSelvin Xavier req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 6051ac5a404SSelvin Xavier ((ilog2(pg_size) << 6061ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 6071ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 6081ac5a404SSelvin Xavier req.access = (mr->flags & 0xFFFF); 6091ac5a404SSelvin Xavier req.va = cpu_to_le64(mr->va); 6101ac5a404SSelvin Xavier req.key = cpu_to_le32(mr->lkey); 6111ac5a404SSelvin Xavier req.mr_size = cpu_to_le64(mr->total_size); 6121ac5a404SSelvin Xavier 613cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 614cc1ec769SDevesh Sharma (void *)&resp, NULL, block); 615cc1ec769SDevesh Sharma if (rc) 6161ac5a404SSelvin Xavier goto fail; 617cc1ec769SDevesh Sharma 6181ac5a404SSelvin Xavier return 0; 6191ac5a404SSelvin Xavier 6201ac5a404SSelvin Xavier fail: 6211ac5a404SSelvin Xavier if (mr->hwq.max_elements) 6221ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 6231ac5a404SSelvin Xavier return rc; 6241ac5a404SSelvin Xavier } 6251ac5a404SSelvin Xavier 6261ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 6271ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl, 6281ac5a404SSelvin Xavier int max_pg_ptrs) 6291ac5a404SSelvin Xavier { 6301ac5a404SSelvin Xavier int pg_ptrs, pages, rc; 6311ac5a404SSelvin Xavier 6321ac5a404SSelvin Xavier /* Re-calculate the max to fit the HWQ allocation model */ 6331ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 6341ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 6351ac5a404SSelvin Xavier if (!pages) 6361ac5a404SSelvin Xavier pages++; 6371ac5a404SSelvin Xavier 6381ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) 6391ac5a404SSelvin Xavier return -ENOMEM; 6401ac5a404SSelvin Xavier 6411ac5a404SSelvin Xavier frpl->hwq.max_elements = pages; 6421ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0, 6431ac5a404SSelvin Xavier &frpl->hwq.max_elements, PAGE_SIZE, 0, 6441ac5a404SSelvin Xavier PAGE_SIZE, HWQ_TYPE_CTX); 6451ac5a404SSelvin Xavier if (!rc) 6461ac5a404SSelvin Xavier frpl->max_pg_ptrs = pg_ptrs; 6471ac5a404SSelvin Xavier 6481ac5a404SSelvin Xavier return rc; 6491ac5a404SSelvin Xavier } 6501ac5a404SSelvin Xavier 6511ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 6521ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl) 6531ac5a404SSelvin Xavier { 6541ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &frpl->hwq); 6551ac5a404SSelvin Xavier return 0; 6561ac5a404SSelvin Xavier } 6571ac5a404SSelvin Xavier 6581ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) 6591ac5a404SSelvin Xavier { 6601ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6611ac5a404SSelvin Xavier struct cmdq_map_tc_to_cos req; 662cc1ec769SDevesh Sharma struct creq_map_tc_to_cos_resp resp; 6631ac5a404SSelvin Xavier u16 cmd_flags = 0; 664cc1ec769SDevesh Sharma int rc = 0; 6651ac5a404SSelvin Xavier 6661ac5a404SSelvin Xavier RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); 6671ac5a404SSelvin Xavier req.cos0 = cpu_to_le16(cids[0]); 6681ac5a404SSelvin Xavier req.cos1 = cpu_to_le16(cids[1]); 6691ac5a404SSelvin Xavier 670cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 671cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 6721ac5a404SSelvin Xavier return 0; 6731ac5a404SSelvin Xavier } 674