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 3908920b8fSJoe Perches #define dev_fmt(fmt) "QPLIB: " fmt 4008920b8fSJoe Perches 411ac5a404SSelvin Xavier #include <linux/interrupt.h> 421ac5a404SSelvin Xavier #include <linux/spinlock.h> 431ac5a404SSelvin Xavier #include <linux/sched.h> 441ac5a404SSelvin Xavier #include <linux/pci.h> 451ac5a404SSelvin Xavier 461ac5a404SSelvin Xavier #include "roce_hsi.h" 471ac5a404SSelvin Xavier 481ac5a404SSelvin Xavier #include "qplib_res.h" 491ac5a404SSelvin Xavier #include "qplib_rcfw.h" 501ac5a404SSelvin Xavier #include "qplib_sp.h" 511ac5a404SSelvin Xavier 521ac5a404SSelvin Xavier const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 531ac5a404SSelvin Xavier 0, 0, 0, 0, 0, 0, 0, 0 } }; 541ac5a404SSelvin Xavier 551ac5a404SSelvin Xavier /* Device */ 56254cd259SDevesh Sharma 572fc68543SSelvin Xavier static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, 582fc68543SSelvin Xavier char *fw_ver) 592fc68543SSelvin Xavier { 602fc68543SSelvin Xavier struct cmdq_query_version req; 612fc68543SSelvin Xavier struct creq_query_version_resp resp; 622fc68543SSelvin Xavier u16 cmd_flags = 0; 632fc68543SSelvin Xavier int rc = 0; 642fc68543SSelvin Xavier 652fc68543SSelvin Xavier RCFW_CMD_PREP(req, QUERY_VERSION, cmd_flags); 662fc68543SSelvin Xavier 672fc68543SSelvin Xavier rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 682fc68543SSelvin Xavier (void *)&resp, NULL, 0); 692fc68543SSelvin Xavier if (rc) 702fc68543SSelvin Xavier return; 712fc68543SSelvin Xavier fw_ver[0] = resp.fw_maj; 722fc68543SSelvin Xavier fw_ver[1] = resp.fw_minor; 732fc68543SSelvin Xavier fw_ver[2] = resp.fw_bld; 742fc68543SSelvin Xavier fw_ver[3] = resp.fw_rsvd; 752fc68543SSelvin Xavier } 762fc68543SSelvin Xavier 771ac5a404SSelvin Xavier int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, 78ccd9d0d3SSelvin Xavier struct bnxt_qplib_dev_attr *attr, bool vf) 791ac5a404SSelvin Xavier { 801ac5a404SSelvin Xavier struct cmdq_query_func req; 81cc1ec769SDevesh Sharma struct creq_query_func_resp resp; 82cc1ec769SDevesh Sharma struct bnxt_qplib_rcfw_sbuf *sbuf; 831ac5a404SSelvin Xavier struct creq_query_func_resp_sb *sb; 841ac5a404SSelvin Xavier u16 cmd_flags = 0; 851ac5a404SSelvin Xavier u32 temp; 861ac5a404SSelvin Xavier u8 *tqm_alloc; 87cc1ec769SDevesh Sharma int i, rc = 0; 881ac5a404SSelvin Xavier 891ac5a404SSelvin Xavier RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags); 901ac5a404SSelvin Xavier 91cc1ec769SDevesh Sharma sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 92cc1ec769SDevesh Sharma if (!sbuf) { 931ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 9408920b8fSJoe Perches "SP: QUERY_FUNC alloc side buffer failed\n"); 95cc1ec769SDevesh Sharma return -ENOMEM; 961ac5a404SSelvin Xavier } 97cc1ec769SDevesh Sharma 98cc1ec769SDevesh Sharma sb = sbuf->sb; 99cc1ec769SDevesh Sharma req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 100cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 101cc1ec769SDevesh Sharma (void *)sbuf, 0); 102cc1ec769SDevesh Sharma if (rc) 103cc1ec769SDevesh Sharma goto bail; 104cc1ec769SDevesh Sharma 1051ac5a404SSelvin Xavier /* Extract the context from the side buffer */ 1061ac5a404SSelvin Xavier attr->max_qp = le32_to_cpu(sb->max_qp); 10758d4a671SSelvin Xavier /* max_qp value reported by FW for PF doesn't include the QP1 for PF */ 108ccd9d0d3SSelvin Xavier if (!vf) 10958d4a671SSelvin Xavier attr->max_qp += 1; 1101ac5a404SSelvin Xavier attr->max_qp_rd_atom = 1111ac5a404SSelvin Xavier sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 1121ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; 1131ac5a404SSelvin Xavier attr->max_qp_init_rd_atom = 1141ac5a404SSelvin Xavier sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 1151ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; 1161ac5a404SSelvin Xavier attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); 1179152e0b7SEddie Wai /* 1189152e0b7SEddie Wai * 128 WQEs needs to be reserved for the HW (8916). Prevent 1199152e0b7SEddie Wai * reporting the max number 1209152e0b7SEddie Wai */ 1219152e0b7SEddie Wai attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS; 1221ac5a404SSelvin Xavier attr->max_qp_sges = sb->max_sge; 1231ac5a404SSelvin Xavier attr->max_cq = le32_to_cpu(sb->max_cq); 1241ac5a404SSelvin Xavier attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 1251ac5a404SSelvin Xavier attr->max_cq_sges = attr->max_qp_sges; 1261ac5a404SSelvin Xavier attr->max_mr = le32_to_cpu(sb->max_mr); 1271ac5a404SSelvin Xavier attr->max_mw = le32_to_cpu(sb->max_mw); 1281ac5a404SSelvin Xavier 1291ac5a404SSelvin Xavier attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 1301ac5a404SSelvin Xavier attr->max_pd = 64 * 1024; 1311ac5a404SSelvin Xavier attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 1321ac5a404SSelvin Xavier attr->max_ah = le32_to_cpu(sb->max_ah); 1331ac5a404SSelvin Xavier 1341ac5a404SSelvin Xavier attr->max_fmr = le32_to_cpu(sb->max_fmr); 1351ac5a404SSelvin Xavier attr->max_map_per_fmr = sb->max_map_per_fmr; 1361ac5a404SSelvin Xavier 1371ac5a404SSelvin Xavier attr->max_srq = le16_to_cpu(sb->max_srq); 1381ac5a404SSelvin Xavier attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 1391ac5a404SSelvin Xavier attr->max_srq_sges = sb->max_srq_sge; 1401ac5a404SSelvin Xavier /* Bono only reports 1 PKEY for now, but it can support > 1 */ 1411ac5a404SSelvin Xavier attr->max_pkey = le32_to_cpu(sb->max_pkeys); 1421ac5a404SSelvin Xavier 1431ac5a404SSelvin Xavier attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 144c354dff0SDevesh Sharma attr->l2_db_size = (sb->l2_db_space_size + 1) * 145c354dff0SDevesh Sharma (0x01 << RCFW_DBR_BASE_PAGE_SHIFT); 1461ac5a404SSelvin Xavier attr->max_sgid = le32_to_cpu(sb->max_gid); 1471ac5a404SSelvin Xavier 1482fc68543SSelvin Xavier bnxt_qplib_query_version(rcfw, attr->fw_ver); 1491ac5a404SSelvin Xavier 1501ac5a404SSelvin Xavier for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 1511ac5a404SSelvin Xavier temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 1521ac5a404SSelvin Xavier tqm_alloc = (u8 *)&temp; 1531ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 1541ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 1551ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 1561ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 1571ac5a404SSelvin Xavier } 158cc1ec769SDevesh Sharma 15963231585SGustavo A. R. Silva attr->is_atomic = false; 160cc1ec769SDevesh Sharma bail: 161cc1ec769SDevesh Sharma bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 162cc1ec769SDevesh Sharma return rc; 1631ac5a404SSelvin Xavier } 1641ac5a404SSelvin Xavier 165ccd9d0d3SSelvin Xavier int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res, 166ccd9d0d3SSelvin Xavier struct bnxt_qplib_rcfw *rcfw, 167ccd9d0d3SSelvin Xavier struct bnxt_qplib_ctx *ctx) 168ccd9d0d3SSelvin Xavier { 169ccd9d0d3SSelvin Xavier struct cmdq_set_func_resources req; 170ccd9d0d3SSelvin Xavier struct creq_set_func_resources_resp resp; 171ccd9d0d3SSelvin Xavier u16 cmd_flags = 0; 172ccd9d0d3SSelvin Xavier int rc = 0; 173ccd9d0d3SSelvin Xavier 174ccd9d0d3SSelvin Xavier RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags); 175ccd9d0d3SSelvin Xavier 176ccd9d0d3SSelvin Xavier req.number_of_qp = cpu_to_le32(ctx->qpc_count); 177ccd9d0d3SSelvin Xavier req.number_of_mrw = cpu_to_le32(ctx->mrw_count); 178ccd9d0d3SSelvin Xavier req.number_of_srq = cpu_to_le32(ctx->srqc_count); 179ccd9d0d3SSelvin Xavier req.number_of_cq = cpu_to_le32(ctx->cq_count); 180ccd9d0d3SSelvin Xavier 181ccd9d0d3SSelvin Xavier req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf); 182ccd9d0d3SSelvin Xavier req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf); 183ccd9d0d3SSelvin Xavier req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf); 184ccd9d0d3SSelvin Xavier req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf); 185ccd9d0d3SSelvin Xavier req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf); 186ccd9d0d3SSelvin Xavier 187ccd9d0d3SSelvin Xavier rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 188ccd9d0d3SSelvin Xavier (void *)&resp, 189ccd9d0d3SSelvin Xavier NULL, 0); 190ccd9d0d3SSelvin Xavier if (rc) { 19108920b8fSJoe Perches dev_err(&res->pdev->dev, "Failed to set function resources\n"); 192ccd9d0d3SSelvin Xavier } 193ccd9d0d3SSelvin Xavier return rc; 194ccd9d0d3SSelvin Xavier } 195ccd9d0d3SSelvin Xavier 1961ac5a404SSelvin Xavier /* SGID */ 1971ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 1981ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 1991ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid) 2001ac5a404SSelvin Xavier { 201474e5a86SDan Carpenter if (index >= sgid_tbl->max) { 2021ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 20308920b8fSJoe Perches "Index %d exceeded SGID table max (%d)\n", 2041ac5a404SSelvin Xavier index, sgid_tbl->max); 2051ac5a404SSelvin Xavier return -EINVAL; 2061ac5a404SSelvin Xavier } 2071ac5a404SSelvin Xavier memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid)); 2081ac5a404SSelvin Xavier return 0; 2091ac5a404SSelvin Xavier } 2101ac5a404SSelvin Xavier 2111ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2121ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, bool update) 2131ac5a404SSelvin Xavier { 2141ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2151ac5a404SSelvin Xavier struct bnxt_qplib_res, 2161ac5a404SSelvin Xavier sgid_tbl); 2171ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 2181ac5a404SSelvin Xavier int index; 2191ac5a404SSelvin Xavier 2201ac5a404SSelvin Xavier if (!sgid_tbl) { 22108920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2221ac5a404SSelvin Xavier return -EINVAL; 2231ac5a404SSelvin Xavier } 2241ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 2251ac5a404SSelvin Xavier if (!sgid_tbl->active) { 22608920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table has no active entries\n"); 2271ac5a404SSelvin Xavier return -ENOMEM; 2281ac5a404SSelvin Xavier } 2291ac5a404SSelvin Xavier for (index = 0; index < sgid_tbl->max; index++) { 2301ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid))) 2311ac5a404SSelvin Xavier break; 2321ac5a404SSelvin Xavier } 2331ac5a404SSelvin Xavier if (index == sgid_tbl->max) { 23408920b8fSJoe Perches dev_warn(&res->pdev->dev, "GID not found in the SGID table\n"); 2351ac5a404SSelvin Xavier return 0; 2361ac5a404SSelvin Xavier } 2371ac5a404SSelvin Xavier /* Remove GID from the SGID table */ 2381ac5a404SSelvin Xavier if (update) { 2391ac5a404SSelvin Xavier struct cmdq_delete_gid req; 240cc1ec769SDevesh Sharma struct creq_delete_gid_resp resp; 2411ac5a404SSelvin Xavier u16 cmd_flags = 0; 242cc1ec769SDevesh Sharma int rc; 2431ac5a404SSelvin Xavier 2441ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); 2451ac5a404SSelvin Xavier if (sgid_tbl->hw_id[index] == 0xFFFF) { 2461ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 24708920b8fSJoe Perches "GID entry contains an invalid HW id\n"); 2481ac5a404SSelvin Xavier return -EINVAL; 2491ac5a404SSelvin Xavier } 2501ac5a404SSelvin Xavier req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 251cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 252cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 253cc1ec769SDevesh Sharma if (rc) 254cc1ec769SDevesh Sharma return rc; 2551ac5a404SSelvin Xavier } 2561ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, 2571ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)); 2585fac5b1bSKalesh AP sgid_tbl->vlan[index] = 0; 2591ac5a404SSelvin Xavier sgid_tbl->active--; 2601ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 26108920b8fSJoe Perches "SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n", 2621ac5a404SSelvin Xavier index, sgid_tbl->hw_id[index], sgid_tbl->active); 2631ac5a404SSelvin Xavier sgid_tbl->hw_id[index] = (u16)-1; 2641ac5a404SSelvin Xavier 2651ac5a404SSelvin Xavier /* unlock */ 2661ac5a404SSelvin Xavier return 0; 2671ac5a404SSelvin Xavier } 2681ac5a404SSelvin Xavier 2691ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2701ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id, 2711ac5a404SSelvin Xavier bool update, u32 *index) 2721ac5a404SSelvin Xavier { 2731ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2741ac5a404SSelvin Xavier struct bnxt_qplib_res, 2751ac5a404SSelvin Xavier sgid_tbl); 2761ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 277cc1ec769SDevesh Sharma int i, free_idx; 2781ac5a404SSelvin Xavier 2791ac5a404SSelvin Xavier if (!sgid_tbl) { 28008920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2811ac5a404SSelvin Xavier return -EINVAL; 2821ac5a404SSelvin Xavier } 2831ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 2841ac5a404SSelvin Xavier if (sgid_tbl->active == sgid_tbl->max) { 28508920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table is full\n"); 2861ac5a404SSelvin Xavier return -ENOMEM; 2871ac5a404SSelvin Xavier } 2881ac5a404SSelvin Xavier free_idx = sgid_tbl->max; 2891ac5a404SSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) { 2901ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) { 2911ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 29208920b8fSJoe Perches "SGID entry already exist in entry %d!\n", i); 2931ac5a404SSelvin Xavier *index = i; 2941ac5a404SSelvin Xavier return -EALREADY; 2951ac5a404SSelvin Xavier } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 2961ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)) && 2971ac5a404SSelvin Xavier free_idx == sgid_tbl->max) { 2981ac5a404SSelvin Xavier free_idx = i; 2991ac5a404SSelvin Xavier } 3001ac5a404SSelvin Xavier } 3011ac5a404SSelvin Xavier if (free_idx == sgid_tbl->max) { 3021ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 30308920b8fSJoe Perches "SGID table is FULL but count is not MAX??\n"); 3041ac5a404SSelvin Xavier return -ENOMEM; 3051ac5a404SSelvin Xavier } 3061ac5a404SSelvin Xavier if (update) { 3071ac5a404SSelvin Xavier struct cmdq_add_gid req; 308cc1ec769SDevesh Sharma struct creq_add_gid_resp resp; 3091ac5a404SSelvin Xavier u16 cmd_flags = 0; 310cc1ec769SDevesh Sharma int rc; 3111ac5a404SSelvin Xavier 3121ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ADD_GID, cmd_flags); 3131ac5a404SSelvin Xavier 3145fac5b1bSKalesh AP req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3155fac5b1bSKalesh AP req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3165fac5b1bSKalesh AP req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3175fac5b1bSKalesh AP req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3185fac5b1bSKalesh AP /* 3195fac5b1bSKalesh AP * driver should ensure that all RoCE traffic is always VLAN 3205fac5b1bSKalesh AP * tagged if RoCE traffic is running on non-zero VLAN ID or 3215fac5b1bSKalesh AP * RoCE traffic is running on non-zero Priority. 3225fac5b1bSKalesh AP */ 3235fac5b1bSKalesh AP if ((vlan_id != 0xFFFF) || res->prio) { 3241ac5a404SSelvin Xavier if (vlan_id != 0xFFFF) 3255fac5b1bSKalesh AP req.vlan = cpu_to_le16 3265fac5b1bSKalesh AP (vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK); 3275fac5b1bSKalesh AP req.vlan |= cpu_to_le16 3285fac5b1bSKalesh AP (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3291ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_EN); 3305fac5b1bSKalesh AP } 3311ac5a404SSelvin Xavier 3321ac5a404SSelvin Xavier /* MAC in network format */ 3335fac5b1bSKalesh AP req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3345fac5b1bSKalesh AP req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3355fac5b1bSKalesh AP req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3361ac5a404SSelvin Xavier 337cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 338cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 339cc1ec769SDevesh Sharma if (rc) 340cc1ec769SDevesh Sharma return rc; 341cc1ec769SDevesh Sharma sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); 3421ac5a404SSelvin Xavier } 3431ac5a404SSelvin Xavier /* Add GID to the sgid_tbl */ 3441ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 3451ac5a404SSelvin Xavier sgid_tbl->active++; 3465fac5b1bSKalesh AP if (vlan_id != 0xFFFF) 3475fac5b1bSKalesh AP sgid_tbl->vlan[free_idx] = 1; 3485fac5b1bSKalesh AP 3491ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 35008920b8fSJoe Perches "SGID added hw_id[0x%x] = 0x%x active = 0x%x\n", 3511ac5a404SSelvin Xavier free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 3521ac5a404SSelvin Xavier 3531ac5a404SSelvin Xavier *index = free_idx; 3541ac5a404SSelvin Xavier /* unlock */ 355cc1ec769SDevesh Sharma return 0; 3561ac5a404SSelvin Xavier } 3571ac5a404SSelvin Xavier 3585fac5b1bSKalesh AP int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 3595fac5b1bSKalesh AP struct bnxt_qplib_gid *gid, u16 gid_idx, 3605fac5b1bSKalesh AP u8 *smac) 3615fac5b1bSKalesh AP { 3625fac5b1bSKalesh AP struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 3635fac5b1bSKalesh AP struct bnxt_qplib_res, 3645fac5b1bSKalesh AP sgid_tbl); 3655fac5b1bSKalesh AP struct bnxt_qplib_rcfw *rcfw = res->rcfw; 3665fac5b1bSKalesh AP struct creq_modify_gid_resp resp; 3675fac5b1bSKalesh AP struct cmdq_modify_gid req; 3685fac5b1bSKalesh AP int rc; 3695fac5b1bSKalesh AP u16 cmd_flags = 0; 3705fac5b1bSKalesh AP 3715fac5b1bSKalesh AP RCFW_CMD_PREP(req, MODIFY_GID, cmd_flags); 3725fac5b1bSKalesh AP 3735fac5b1bSKalesh AP req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3745fac5b1bSKalesh AP req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3755fac5b1bSKalesh AP req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3765fac5b1bSKalesh AP req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3775fac5b1bSKalesh AP if (res->prio) { 3785fac5b1bSKalesh AP req.vlan |= cpu_to_le16 3795fac5b1bSKalesh AP (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3805fac5b1bSKalesh AP CMDQ_ADD_GID_VLAN_VLAN_EN); 3815fac5b1bSKalesh AP } 3825fac5b1bSKalesh AP 3835fac5b1bSKalesh AP /* MAC in network format */ 3845fac5b1bSKalesh AP req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3855fac5b1bSKalesh AP req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3865fac5b1bSKalesh AP req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3875fac5b1bSKalesh AP 3885fac5b1bSKalesh AP req.gid_index = cpu_to_le16(gid_idx); 3895fac5b1bSKalesh AP 3905fac5b1bSKalesh AP rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 3915fac5b1bSKalesh AP (void *)&resp, NULL, 0); 3925fac5b1bSKalesh AP return rc; 3935fac5b1bSKalesh AP } 3945fac5b1bSKalesh AP 3951ac5a404SSelvin Xavier /* pkeys */ 3961ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, 3971ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index, 3981ac5a404SSelvin Xavier u16 *pkey) 3991ac5a404SSelvin Xavier { 4001ac5a404SSelvin Xavier if (index == 0xFFFF) { 4011ac5a404SSelvin Xavier *pkey = 0xFFFF; 4021ac5a404SSelvin Xavier return 0; 4031ac5a404SSelvin Xavier } 404474e5a86SDan Carpenter if (index >= pkey_tbl->max) { 4051ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 40608920b8fSJoe Perches "Index %d exceeded PKEY table max (%d)\n", 4071ac5a404SSelvin Xavier index, pkey_tbl->max); 4081ac5a404SSelvin Xavier return -EINVAL; 4091ac5a404SSelvin Xavier } 4101ac5a404SSelvin Xavier memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey)); 4111ac5a404SSelvin Xavier return 0; 4121ac5a404SSelvin Xavier } 4131ac5a404SSelvin Xavier 4141ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res, 4151ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4161ac5a404SSelvin Xavier bool update) 4171ac5a404SSelvin Xavier { 4181ac5a404SSelvin Xavier int i, rc = 0; 4191ac5a404SSelvin Xavier 4201ac5a404SSelvin Xavier if (!pkey_tbl) { 42108920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4221ac5a404SSelvin Xavier return -EINVAL; 4231ac5a404SSelvin Xavier } 4241ac5a404SSelvin Xavier 4251ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 4261ac5a404SSelvin Xavier if (!pkey_tbl->active) { 42708920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table has no active entries\n"); 4281ac5a404SSelvin Xavier return -ENOMEM; 4291ac5a404SSelvin Xavier } 4301ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 4311ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4321ac5a404SSelvin Xavier break; 4331ac5a404SSelvin Xavier } 4341ac5a404SSelvin Xavier if (i == pkey_tbl->max) { 4351ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 43608920b8fSJoe Perches "PKEY 0x%04x not found in the pkey table\n", *pkey); 4371ac5a404SSelvin Xavier return -ENOMEM; 4381ac5a404SSelvin Xavier } 4391ac5a404SSelvin Xavier memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey)); 4401ac5a404SSelvin Xavier pkey_tbl->active--; 4411ac5a404SSelvin Xavier 4421ac5a404SSelvin Xavier /* unlock */ 4431ac5a404SSelvin Xavier return rc; 4441ac5a404SSelvin Xavier } 4451ac5a404SSelvin Xavier 4461ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, 4471ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4481ac5a404SSelvin Xavier bool update) 4491ac5a404SSelvin Xavier { 4501ac5a404SSelvin Xavier int i, free_idx, rc = 0; 4511ac5a404SSelvin Xavier 4521ac5a404SSelvin Xavier if (!pkey_tbl) { 45308920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4541ac5a404SSelvin Xavier return -EINVAL; 4551ac5a404SSelvin Xavier } 4561ac5a404SSelvin Xavier 4571ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 4581ac5a404SSelvin Xavier if (pkey_tbl->active == pkey_tbl->max) { 45908920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table is full\n"); 4601ac5a404SSelvin Xavier return -ENOMEM; 4611ac5a404SSelvin Xavier } 4621ac5a404SSelvin Xavier free_idx = pkey_tbl->max; 4631ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 4641ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4651ac5a404SSelvin Xavier return -EALREADY; 4661ac5a404SSelvin Xavier else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max) 4671ac5a404SSelvin Xavier free_idx = i; 4681ac5a404SSelvin Xavier } 4691ac5a404SSelvin Xavier if (free_idx == pkey_tbl->max) { 4701ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 47108920b8fSJoe Perches "PKEY table is FULL but count is not MAX??\n"); 4721ac5a404SSelvin Xavier return -ENOMEM; 4731ac5a404SSelvin Xavier } 4741ac5a404SSelvin Xavier /* Add PKEY to the pkey_tbl */ 4751ac5a404SSelvin Xavier memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey)); 4761ac5a404SSelvin Xavier pkey_tbl->active++; 4771ac5a404SSelvin Xavier 4781ac5a404SSelvin Xavier /* unlock */ 4791ac5a404SSelvin Xavier return rc; 4801ac5a404SSelvin Xavier } 4811ac5a404SSelvin Xavier 4821ac5a404SSelvin Xavier /* AH */ 4831ac5a404SSelvin Xavier int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 4841ac5a404SSelvin Xavier { 4851ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4861ac5a404SSelvin Xavier struct cmdq_create_ah req; 487cc1ec769SDevesh Sharma struct creq_create_ah_resp resp; 4881ac5a404SSelvin Xavier u16 cmd_flags = 0; 4891ac5a404SSelvin Xavier u32 temp32[4]; 4901ac5a404SSelvin Xavier u16 temp16[3]; 491cc1ec769SDevesh Sharma int rc; 4921ac5a404SSelvin Xavier 4931ac5a404SSelvin Xavier RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); 4941ac5a404SSelvin Xavier 4951ac5a404SSelvin Xavier memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 4961ac5a404SSelvin Xavier req.dgid[0] = cpu_to_le32(temp32[0]); 4971ac5a404SSelvin Xavier req.dgid[1] = cpu_to_le32(temp32[1]); 4981ac5a404SSelvin Xavier req.dgid[2] = cpu_to_le32(temp32[2]); 4991ac5a404SSelvin Xavier req.dgid[3] = cpu_to_le32(temp32[3]); 5001ac5a404SSelvin Xavier 5011ac5a404SSelvin Xavier req.type = ah->nw_type; 5021ac5a404SSelvin Xavier req.hop_limit = ah->hop_limit; 5031ac5a404SSelvin Xavier req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 5041ac5a404SSelvin Xavier req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 5051ac5a404SSelvin Xavier CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 5061ac5a404SSelvin Xavier CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 5071ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(ah->pd->id); 5081ac5a404SSelvin Xavier req.traffic_class = ah->traffic_class; 5091ac5a404SSelvin Xavier 5101ac5a404SSelvin Xavier /* MAC in network format */ 5111ac5a404SSelvin Xavier memcpy(temp16, ah->dmac, 6); 5121ac5a404SSelvin Xavier req.dest_mac[0] = cpu_to_le16(temp16[0]); 5131ac5a404SSelvin Xavier req.dest_mac[1] = cpu_to_le16(temp16[1]); 5141ac5a404SSelvin Xavier req.dest_mac[2] = cpu_to_le16(temp16[2]); 5151ac5a404SSelvin Xavier 516cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5171ac5a404SSelvin Xavier NULL, 1); 518cc1ec769SDevesh Sharma if (rc) 519cc1ec769SDevesh Sharma return rc; 520cc1ec769SDevesh Sharma 521cc1ec769SDevesh Sharma ah->id = le32_to_cpu(resp.xid); 5221ac5a404SSelvin Xavier return 0; 5231ac5a404SSelvin Xavier } 5241ac5a404SSelvin Xavier 5251ac5a404SSelvin Xavier int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 5261ac5a404SSelvin Xavier { 5271ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5281ac5a404SSelvin Xavier struct cmdq_destroy_ah req; 529cc1ec769SDevesh Sharma struct creq_destroy_ah_resp resp; 5301ac5a404SSelvin Xavier u16 cmd_flags = 0; 531cc1ec769SDevesh Sharma int rc; 5321ac5a404SSelvin Xavier 5331ac5a404SSelvin Xavier /* Clean up the AH table in the device */ 5341ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); 5351ac5a404SSelvin Xavier 5361ac5a404SSelvin Xavier req.ah_cid = cpu_to_le32(ah->id); 5371ac5a404SSelvin Xavier 538cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5391ac5a404SSelvin Xavier NULL, 1); 540cc1ec769SDevesh Sharma if (rc) 541cc1ec769SDevesh Sharma return rc; 5421ac5a404SSelvin Xavier return 0; 5431ac5a404SSelvin Xavier } 5441ac5a404SSelvin Xavier 5451ac5a404SSelvin Xavier /* MRW */ 5461ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5471ac5a404SSelvin Xavier { 5481ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5491ac5a404SSelvin Xavier struct cmdq_deallocate_key req; 550cc1ec769SDevesh Sharma struct creq_deallocate_key_resp resp; 5511ac5a404SSelvin Xavier u16 cmd_flags = 0; 552cc1ec769SDevesh Sharma int rc; 5531ac5a404SSelvin Xavier 5541ac5a404SSelvin Xavier if (mrw->lkey == 0xFFFFFFFF) { 55508920b8fSJoe Perches dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n"); 5561ac5a404SSelvin Xavier return 0; 5571ac5a404SSelvin Xavier } 5581ac5a404SSelvin Xavier 5591ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags); 5601ac5a404SSelvin Xavier 5611ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 5621ac5a404SSelvin Xavier 5631ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 5641ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 5651ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 5661ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->rkey); 5671ac5a404SSelvin Xavier else 5681ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->lkey); 5691ac5a404SSelvin Xavier 570cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5711ac5a404SSelvin Xavier NULL, 0); 572cc1ec769SDevesh Sharma if (rc) 573cc1ec769SDevesh Sharma return rc; 574cc1ec769SDevesh Sharma 5751ac5a404SSelvin Xavier /* Free the qplib's MRW memory */ 5761ac5a404SSelvin Xavier if (mrw->hwq.max_elements) 5771ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 5781ac5a404SSelvin Xavier 5791ac5a404SSelvin Xavier return 0; 5801ac5a404SSelvin Xavier } 5811ac5a404SSelvin Xavier 5821ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5831ac5a404SSelvin Xavier { 5841ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5851ac5a404SSelvin Xavier struct cmdq_allocate_mrw req; 586cc1ec769SDevesh Sharma struct creq_allocate_mrw_resp resp; 5871ac5a404SSelvin Xavier u16 cmd_flags = 0; 5881ac5a404SSelvin Xavier unsigned long tmp; 589cc1ec769SDevesh Sharma int rc; 5901ac5a404SSelvin Xavier 5911ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); 5921ac5a404SSelvin Xavier 5931ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(mrw->pd->id); 5941ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 5951ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 5961ac5a404SSelvin Xavier mrw->flags & BNXT_QPLIB_FR_PMR) || 5971ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 5981ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 5991ac5a404SSelvin Xavier req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 6001ac5a404SSelvin Xavier tmp = (unsigned long)mrw; 6011ac5a404SSelvin Xavier req.mrw_handle = cpu_to_le64(tmp); 6021ac5a404SSelvin Xavier 603cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 604cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 605cc1ec769SDevesh Sharma if (rc) 606cc1ec769SDevesh Sharma return rc; 607cc1ec769SDevesh Sharma 6081ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 6091ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 6101ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 611cc1ec769SDevesh Sharma mrw->rkey = le32_to_cpu(resp.xid); 6121ac5a404SSelvin Xavier else 613cc1ec769SDevesh Sharma mrw->lkey = le32_to_cpu(resp.xid); 6141ac5a404SSelvin Xavier return 0; 6151ac5a404SSelvin Xavier } 6161ac5a404SSelvin Xavier 6171ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 6181ac5a404SSelvin Xavier bool block) 6191ac5a404SSelvin Xavier { 6201ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6211ac5a404SSelvin Xavier struct cmdq_deregister_mr req; 622cc1ec769SDevesh Sharma struct creq_deregister_mr_resp resp; 6231ac5a404SSelvin Xavier u16 cmd_flags = 0; 6241ac5a404SSelvin Xavier int rc; 6251ac5a404SSelvin Xavier 6261ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); 6271ac5a404SSelvin Xavier 6281ac5a404SSelvin Xavier req.lkey = cpu_to_le32(mrw->lkey); 629cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 630cc1ec769SDevesh Sharma (void *)&resp, NULL, block); 631cc1ec769SDevesh Sharma if (rc) 632cc1ec769SDevesh Sharma return rc; 6331ac5a404SSelvin Xavier 6341ac5a404SSelvin Xavier /* Free the qplib's MR memory */ 6351ac5a404SSelvin Xavier if (mrw->hwq.max_elements) { 6361ac5a404SSelvin Xavier mrw->va = 0; 6371ac5a404SSelvin Xavier mrw->total_size = 0; 6381ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 6391ac5a404SSelvin Xavier } 6401ac5a404SSelvin Xavier 6411ac5a404SSelvin Xavier return 0; 6421ac5a404SSelvin Xavier } 6431ac5a404SSelvin Xavier 6441ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 645872f3578SSomnath Kotur u64 *pbl_tbl, int num_pbls, bool block, u32 buf_pg_size) 6461ac5a404SSelvin Xavier { 6471ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6481ac5a404SSelvin Xavier struct cmdq_register_mr req; 649cc1ec769SDevesh Sharma struct creq_register_mr_resp resp; 6501ac5a404SSelvin Xavier u16 cmd_flags = 0, level; 6511ac5a404SSelvin Xavier int pg_ptrs, pages, i, rc; 6521ac5a404SSelvin Xavier dma_addr_t **pbl_ptr; 6531ac5a404SSelvin Xavier u32 pg_size; 6541ac5a404SSelvin Xavier 6551ac5a404SSelvin Xavier if (num_pbls) { 656872f3578SSomnath Kotur /* Allocate memory for the non-leaf pages to store buf ptrs. 657872f3578SSomnath Kotur * Non-leaf pages always uses system PAGE_SIZE 658872f3578SSomnath Kotur */ 6591ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(num_pbls); 6601ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 6611ac5a404SSelvin Xavier if (!pages) 6621ac5a404SSelvin Xavier pages++; 6631ac5a404SSelvin Xavier 6641ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) { 6651ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 66608920b8fSJoe Perches "SP: Reg MR pages requested (0x%x) exceeded max (0x%x)\n", 6671ac5a404SSelvin Xavier pages, MAX_PBL_LVL_1_PGS); 6681ac5a404SSelvin Xavier return -ENOMEM; 6691ac5a404SSelvin Xavier } 6701ac5a404SSelvin Xavier /* Free the hwq if it already exist, must be a rereg */ 6711ac5a404SSelvin Xavier if (mr->hwq.max_elements) 6721ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 6731ac5a404SSelvin Xavier 6741ac5a404SSelvin Xavier mr->hwq.max_elements = pages; 675872f3578SSomnath Kotur /* Use system PAGE_SIZE */ 6761ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0, 6771ac5a404SSelvin Xavier &mr->hwq.max_elements, 6781ac5a404SSelvin Xavier PAGE_SIZE, 0, PAGE_SIZE, 6791ac5a404SSelvin Xavier HWQ_TYPE_CTX); 6801ac5a404SSelvin Xavier if (rc) { 6811ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 68208920b8fSJoe Perches "SP: Reg MR memory allocation failed\n"); 6831ac5a404SSelvin Xavier return -ENOMEM; 6841ac5a404SSelvin Xavier } 6851ac5a404SSelvin Xavier /* Write to the hwq */ 6861ac5a404SSelvin Xavier pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr; 6871ac5a404SSelvin Xavier for (i = 0; i < num_pbls; i++) 6881ac5a404SSelvin Xavier pbl_ptr[PTR_PG(i)][PTR_IDX(i)] = 6891ac5a404SSelvin Xavier (pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID; 6901ac5a404SSelvin Xavier } 6911ac5a404SSelvin Xavier 6921ac5a404SSelvin Xavier RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); 6931ac5a404SSelvin Xavier 6941ac5a404SSelvin Xavier /* Configure the request */ 6951ac5a404SSelvin Xavier if (mr->hwq.level == PBL_LVL_MAX) { 696872f3578SSomnath Kotur /* No PBL provided, just use system PAGE_SIZE */ 6971ac5a404SSelvin Xavier level = 0; 6981ac5a404SSelvin Xavier req.pbl = 0; 6991ac5a404SSelvin Xavier pg_size = PAGE_SIZE; 7001ac5a404SSelvin Xavier } else { 7011ac5a404SSelvin Xavier level = mr->hwq.level + 1; 7021ac5a404SSelvin Xavier req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 7031ac5a404SSelvin Xavier } 704872f3578SSomnath Kotur pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE; 7051ac5a404SSelvin Xavier req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 7061ac5a404SSelvin Xavier ((ilog2(pg_size) << 7071ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 7081ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 709872f3578SSomnath Kotur req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) << 710872f3578SSomnath Kotur CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) & 711872f3578SSomnath Kotur CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK)); 7121ac5a404SSelvin Xavier req.access = (mr->flags & 0xFFFF); 7131ac5a404SSelvin Xavier req.va = cpu_to_le64(mr->va); 7141ac5a404SSelvin Xavier req.key = cpu_to_le32(mr->lkey); 7151ac5a404SSelvin Xavier req.mr_size = cpu_to_le64(mr->total_size); 7161ac5a404SSelvin Xavier 717cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 718cc1ec769SDevesh Sharma (void *)&resp, NULL, block); 719cc1ec769SDevesh Sharma if (rc) 7201ac5a404SSelvin Xavier goto fail; 721cc1ec769SDevesh Sharma 7221ac5a404SSelvin Xavier return 0; 7231ac5a404SSelvin Xavier 7241ac5a404SSelvin Xavier fail: 7251ac5a404SSelvin Xavier if (mr->hwq.max_elements) 7261ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 7271ac5a404SSelvin Xavier return rc; 7281ac5a404SSelvin Xavier } 7291ac5a404SSelvin Xavier 7301ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 7311ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl, 7321ac5a404SSelvin Xavier int max_pg_ptrs) 7331ac5a404SSelvin Xavier { 7341ac5a404SSelvin Xavier int pg_ptrs, pages, rc; 7351ac5a404SSelvin Xavier 7361ac5a404SSelvin Xavier /* Re-calculate the max to fit the HWQ allocation model */ 7371ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 7381ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 7391ac5a404SSelvin Xavier if (!pages) 7401ac5a404SSelvin Xavier pages++; 7411ac5a404SSelvin Xavier 7421ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) 7431ac5a404SSelvin Xavier return -ENOMEM; 7441ac5a404SSelvin Xavier 7451ac5a404SSelvin Xavier frpl->hwq.max_elements = pages; 7461ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0, 7471ac5a404SSelvin Xavier &frpl->hwq.max_elements, PAGE_SIZE, 0, 7481ac5a404SSelvin Xavier PAGE_SIZE, HWQ_TYPE_CTX); 7491ac5a404SSelvin Xavier if (!rc) 7501ac5a404SSelvin Xavier frpl->max_pg_ptrs = pg_ptrs; 7511ac5a404SSelvin Xavier 7521ac5a404SSelvin Xavier return rc; 7531ac5a404SSelvin Xavier } 7541ac5a404SSelvin Xavier 7551ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 7561ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl) 7571ac5a404SSelvin Xavier { 7581ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &frpl->hwq); 7591ac5a404SSelvin Xavier return 0; 7601ac5a404SSelvin Xavier } 7611ac5a404SSelvin Xavier 7621ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) 7631ac5a404SSelvin Xavier { 7641ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 7651ac5a404SSelvin Xavier struct cmdq_map_tc_to_cos req; 766cc1ec769SDevesh Sharma struct creq_map_tc_to_cos_resp resp; 7671ac5a404SSelvin Xavier u16 cmd_flags = 0; 7681ac5a404SSelvin Xavier 7691ac5a404SSelvin Xavier RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); 7701ac5a404SSelvin Xavier req.cos0 = cpu_to_le16(cids[0]); 7711ac5a404SSelvin Xavier req.cos1 = cpu_to_le16(cids[1]); 7721ac5a404SSelvin Xavier 7736dfa8ae6SBart Van Assche bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 7746dfa8ae6SBart Van Assche 0); 7751ac5a404SSelvin Xavier return 0; 7761ac5a404SSelvin Xavier } 77789f81008SSelvin Xavier 77889f81008SSelvin Xavier int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw, 77989f81008SSelvin Xavier struct bnxt_qplib_roce_stats *stats) 78089f81008SSelvin Xavier { 78189f81008SSelvin Xavier struct cmdq_query_roce_stats req; 78289f81008SSelvin Xavier struct creq_query_roce_stats_resp resp; 78389f81008SSelvin Xavier struct bnxt_qplib_rcfw_sbuf *sbuf; 78489f81008SSelvin Xavier struct creq_query_roce_stats_resp_sb *sb; 78589f81008SSelvin Xavier u16 cmd_flags = 0; 78689f81008SSelvin Xavier int rc = 0; 78789f81008SSelvin Xavier 78889f81008SSelvin Xavier RCFW_CMD_PREP(req, QUERY_ROCE_STATS, cmd_flags); 78989f81008SSelvin Xavier 79089f81008SSelvin Xavier sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 79189f81008SSelvin Xavier if (!sbuf) { 79289f81008SSelvin Xavier dev_err(&rcfw->pdev->dev, 79308920b8fSJoe Perches "SP: QUERY_ROCE_STATS alloc side buffer failed\n"); 79489f81008SSelvin Xavier return -ENOMEM; 79589f81008SSelvin Xavier } 79689f81008SSelvin Xavier 79789f81008SSelvin Xavier sb = sbuf->sb; 79889f81008SSelvin Xavier req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 79989f81008SSelvin Xavier rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 80089f81008SSelvin Xavier (void *)sbuf, 0); 80189f81008SSelvin Xavier if (rc) 80289f81008SSelvin Xavier goto bail; 80389f81008SSelvin Xavier /* Extract the context from the side buffer */ 80489f81008SSelvin Xavier stats->to_retransmits = le64_to_cpu(sb->to_retransmits); 80589f81008SSelvin Xavier stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); 80689f81008SSelvin Xavier stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded); 80789f81008SSelvin Xavier stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); 80889f81008SSelvin Xavier stats->missing_resp = le64_to_cpu(sb->missing_resp); 80989f81008SSelvin Xavier stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err); 81089f81008SSelvin Xavier stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err); 81189f81008SSelvin Xavier stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err); 81289f81008SSelvin Xavier stats->local_protection_err = le64_to_cpu(sb->local_protection_err); 81389f81008SSelvin Xavier stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err); 81489f81008SSelvin Xavier stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err); 81589f81008SSelvin Xavier stats->remote_access_err = le64_to_cpu(sb->remote_access_err); 81689f81008SSelvin Xavier stats->remote_op_err = le64_to_cpu(sb->remote_op_err); 81789f81008SSelvin Xavier stats->dup_req = le64_to_cpu(sb->dup_req); 81889f81008SSelvin Xavier stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max); 81989f81008SSelvin Xavier stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch); 82089f81008SSelvin Xavier stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe); 82189f81008SSelvin Xavier stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err); 82289f81008SSelvin Xavier stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey); 82389f81008SSelvin Xavier stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err); 82489f81008SSelvin Xavier stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm); 82589f81008SSelvin Xavier stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err); 82689f81008SSelvin Xavier stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey); 82789f81008SSelvin Xavier stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err); 82889f81008SSelvin Xavier stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm); 82989f81008SSelvin Xavier stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err); 83089f81008SSelvin Xavier stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow); 83189f81008SSelvin Xavier stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode); 83289f81008SSelvin Xavier stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic); 83389f81008SSelvin Xavier stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err); 83489f81008SSelvin Xavier stats->res_mem_error = le64_to_cpu(sb->res_mem_error); 83589f81008SSelvin Xavier stats->res_srq_err = le64_to_cpu(sb->res_srq_err); 83689f81008SSelvin Xavier stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err); 83789f81008SSelvin Xavier stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey); 83889f81008SSelvin Xavier stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err); 83989f81008SSelvin Xavier stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err); 84089f81008SSelvin Xavier stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err); 84189f81008SSelvin Xavier stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err); 84289f81008SSelvin Xavier stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err); 843*316dd282SSelvin Xavier if (!rcfw->init_oos_stats) { 844*316dd282SSelvin Xavier rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 845*316dd282SSelvin Xavier rcfw->init_oos_stats = 1; 846*316dd282SSelvin Xavier } else { 847*316dd282SSelvin Xavier stats->res_oos_drop_count += 848*316dd282SSelvin Xavier (le64_to_cpu(sb->res_oos_drop_count) - 849*316dd282SSelvin Xavier rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK; 850*316dd282SSelvin Xavier rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 851*316dd282SSelvin Xavier } 852*316dd282SSelvin Xavier 85389f81008SSelvin Xavier bail: 85489f81008SSelvin Xavier bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 85589f81008SSelvin Xavier return rc; 85689f81008SSelvin Xavier } 857