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 */ 121c63e1c4dSSelvin Xavier attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1; 12237f91cffSDevesh Sharma attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx) ? 12337f91cffSDevesh Sharma 6 : sb->max_sge; 1241ac5a404SSelvin Xavier attr->max_cq = le32_to_cpu(sb->max_cq); 1251ac5a404SSelvin Xavier attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 1261ac5a404SSelvin Xavier attr->max_cq_sges = attr->max_qp_sges; 1271ac5a404SSelvin Xavier attr->max_mr = le32_to_cpu(sb->max_mr); 1281ac5a404SSelvin Xavier attr->max_mw = le32_to_cpu(sb->max_mw); 1291ac5a404SSelvin Xavier 1301ac5a404SSelvin Xavier attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 1311ac5a404SSelvin Xavier attr->max_pd = 64 * 1024; 1321ac5a404SSelvin Xavier attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 1331ac5a404SSelvin Xavier attr->max_ah = le32_to_cpu(sb->max_ah); 1341ac5a404SSelvin Xavier 1351ac5a404SSelvin Xavier attr->max_srq = le16_to_cpu(sb->max_srq); 1361ac5a404SSelvin Xavier attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 1371ac5a404SSelvin Xavier attr->max_srq_sges = sb->max_srq_sge; 1381ac5a404SSelvin Xavier attr->max_pkey = le32_to_cpu(sb->max_pkeys); 139854a2020SDevesh Sharma /* 140854a2020SDevesh Sharma * Some versions of FW reports more than 0xFFFF. 141854a2020SDevesh Sharma * Restrict it for now to 0xFFFF to avoid 142854a2020SDevesh Sharma * reporting trucated value 143854a2020SDevesh Sharma */ 144854a2020SDevesh Sharma if (attr->max_pkey > 0xFFFF) { 145854a2020SDevesh Sharma /* ib_port_attr::pkey_tbl_len is u16 */ 146854a2020SDevesh Sharma attr->max_pkey = 0xFFFF; 147854a2020SDevesh Sharma } 1481ac5a404SSelvin Xavier 1491ac5a404SSelvin Xavier attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 150c354dff0SDevesh Sharma attr->l2_db_size = (sb->l2_db_space_size + 1) * 151c354dff0SDevesh Sharma (0x01 << RCFW_DBR_BASE_PAGE_SHIFT); 152847b9788SNaresh Kumar PBS attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED; 1531ac5a404SSelvin Xavier 1542fc68543SSelvin Xavier bnxt_qplib_query_version(rcfw, attr->fw_ver); 1551ac5a404SSelvin Xavier 1561ac5a404SSelvin Xavier for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 1571ac5a404SSelvin Xavier temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 1581ac5a404SSelvin Xavier tqm_alloc = (u8 *)&temp; 1591ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 1601ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 1611ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 1621ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 1631ac5a404SSelvin Xavier } 164cc1ec769SDevesh Sharma 16563231585SGustavo A. R. Silva attr->is_atomic = false; 166cc1ec769SDevesh Sharma bail: 167cc1ec769SDevesh Sharma bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 168cc1ec769SDevesh Sharma return rc; 1691ac5a404SSelvin Xavier } 1701ac5a404SSelvin Xavier 171ccd9d0d3SSelvin Xavier int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res, 172ccd9d0d3SSelvin Xavier struct bnxt_qplib_rcfw *rcfw, 173ccd9d0d3SSelvin Xavier struct bnxt_qplib_ctx *ctx) 174ccd9d0d3SSelvin Xavier { 175ccd9d0d3SSelvin Xavier struct cmdq_set_func_resources req; 176ccd9d0d3SSelvin Xavier struct creq_set_func_resources_resp resp; 177ccd9d0d3SSelvin Xavier u16 cmd_flags = 0; 178ccd9d0d3SSelvin Xavier int rc = 0; 179ccd9d0d3SSelvin Xavier 180ccd9d0d3SSelvin Xavier RCFW_CMD_PREP(req, SET_FUNC_RESOURCES, cmd_flags); 181ccd9d0d3SSelvin Xavier 182ccd9d0d3SSelvin Xavier req.number_of_qp = cpu_to_le32(ctx->qpc_count); 183ccd9d0d3SSelvin Xavier req.number_of_mrw = cpu_to_le32(ctx->mrw_count); 184ccd9d0d3SSelvin Xavier req.number_of_srq = cpu_to_le32(ctx->srqc_count); 185ccd9d0d3SSelvin Xavier req.number_of_cq = cpu_to_le32(ctx->cq_count); 186ccd9d0d3SSelvin Xavier 187ccd9d0d3SSelvin Xavier req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf); 188ccd9d0d3SSelvin Xavier req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf); 189ccd9d0d3SSelvin Xavier req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf); 190ccd9d0d3SSelvin Xavier req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf); 191ccd9d0d3SSelvin Xavier req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf); 192ccd9d0d3SSelvin Xavier 193ccd9d0d3SSelvin Xavier rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 194ccd9d0d3SSelvin Xavier (void *)&resp, 195ccd9d0d3SSelvin Xavier NULL, 0); 196ccd9d0d3SSelvin Xavier if (rc) { 19708920b8fSJoe Perches dev_err(&res->pdev->dev, "Failed to set function resources\n"); 198ccd9d0d3SSelvin Xavier } 199ccd9d0d3SSelvin Xavier return rc; 200ccd9d0d3SSelvin Xavier } 201ccd9d0d3SSelvin Xavier 2021ac5a404SSelvin Xavier /* SGID */ 2031ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 2041ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 2051ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid) 2061ac5a404SSelvin Xavier { 207474e5a86SDan Carpenter if (index >= sgid_tbl->max) { 2081ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 20908920b8fSJoe Perches "Index %d exceeded SGID table max (%d)\n", 2101ac5a404SSelvin Xavier index, sgid_tbl->max); 2111ac5a404SSelvin Xavier return -EINVAL; 2121ac5a404SSelvin Xavier } 213c56b593dSSelvin Xavier memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid)); 2141ac5a404SSelvin Xavier return 0; 2151ac5a404SSelvin Xavier } 2161ac5a404SSelvin Xavier 2171ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 218c56b593dSSelvin Xavier struct bnxt_qplib_gid *gid, u16 vlan_id, bool update) 2191ac5a404SSelvin Xavier { 2201ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2211ac5a404SSelvin Xavier struct bnxt_qplib_res, 2221ac5a404SSelvin Xavier sgid_tbl); 2231ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 2241ac5a404SSelvin Xavier int index; 2251ac5a404SSelvin Xavier 2261ac5a404SSelvin Xavier if (!sgid_tbl) { 22708920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2281ac5a404SSelvin Xavier return -EINVAL; 2291ac5a404SSelvin Xavier } 2301ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 2311ac5a404SSelvin Xavier if (!sgid_tbl->active) { 23208920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table has no active entries\n"); 2331ac5a404SSelvin Xavier return -ENOMEM; 2341ac5a404SSelvin Xavier } 2351ac5a404SSelvin Xavier for (index = 0; index < sgid_tbl->max; index++) { 236c56b593dSSelvin Xavier if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) && 237c56b593dSSelvin Xavier vlan_id == sgid_tbl->tbl[index].vlan_id) 2381ac5a404SSelvin Xavier break; 2391ac5a404SSelvin Xavier } 2401ac5a404SSelvin Xavier if (index == sgid_tbl->max) { 24108920b8fSJoe Perches dev_warn(&res->pdev->dev, "GID not found in the SGID table\n"); 2421ac5a404SSelvin Xavier return 0; 2431ac5a404SSelvin Xavier } 2441ac5a404SSelvin Xavier /* Remove GID from the SGID table */ 2451ac5a404SSelvin Xavier if (update) { 2461ac5a404SSelvin Xavier struct cmdq_delete_gid req; 247cc1ec769SDevesh Sharma struct creq_delete_gid_resp resp; 2481ac5a404SSelvin Xavier u16 cmd_flags = 0; 249cc1ec769SDevesh Sharma int rc; 2501ac5a404SSelvin Xavier 2511ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); 2521ac5a404SSelvin Xavier if (sgid_tbl->hw_id[index] == 0xFFFF) { 2531ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 25408920b8fSJoe Perches "GID entry contains an invalid HW id\n"); 2551ac5a404SSelvin Xavier return -EINVAL; 2561ac5a404SSelvin Xavier } 2571ac5a404SSelvin Xavier req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 258cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 259cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 260cc1ec769SDevesh Sharma if (rc) 261cc1ec769SDevesh Sharma return rc; 2621ac5a404SSelvin Xavier } 263c56b593dSSelvin Xavier memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero, 2641ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)); 265c56b593dSSelvin Xavier sgid_tbl->tbl[index].vlan_id = 0xFFFF; 2665fac5b1bSKalesh AP sgid_tbl->vlan[index] = 0; 2671ac5a404SSelvin Xavier sgid_tbl->active--; 2681ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 26908920b8fSJoe Perches "SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n", 2701ac5a404SSelvin Xavier index, sgid_tbl->hw_id[index], sgid_tbl->active); 2711ac5a404SSelvin Xavier sgid_tbl->hw_id[index] = (u16)-1; 2721ac5a404SSelvin Xavier 2731ac5a404SSelvin Xavier /* unlock */ 2741ac5a404SSelvin Xavier return 0; 2751ac5a404SSelvin Xavier } 2761ac5a404SSelvin Xavier 2771ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 2781ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id, 2791ac5a404SSelvin Xavier bool update, u32 *index) 2801ac5a404SSelvin Xavier { 2811ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 2821ac5a404SSelvin Xavier struct bnxt_qplib_res, 2831ac5a404SSelvin Xavier sgid_tbl); 2841ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 285cc1ec769SDevesh Sharma int i, free_idx; 2861ac5a404SSelvin Xavier 2871ac5a404SSelvin Xavier if (!sgid_tbl) { 28808920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table not allocated\n"); 2891ac5a404SSelvin Xavier return -EINVAL; 2901ac5a404SSelvin Xavier } 2911ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 2921ac5a404SSelvin Xavier if (sgid_tbl->active == sgid_tbl->max) { 29308920b8fSJoe Perches dev_err(&res->pdev->dev, "SGID table is full\n"); 2941ac5a404SSelvin Xavier return -ENOMEM; 2951ac5a404SSelvin Xavier } 2961ac5a404SSelvin Xavier free_idx = sgid_tbl->max; 2971ac5a404SSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) { 298c56b593dSSelvin Xavier if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) && 299c56b593dSSelvin Xavier sgid_tbl->tbl[i].vlan_id == vlan_id) { 3001ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 30108920b8fSJoe Perches "SGID entry already exist in entry %d!\n", i); 3021ac5a404SSelvin Xavier *index = i; 3031ac5a404SSelvin Xavier return -EALREADY; 3041ac5a404SSelvin Xavier } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 3051ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)) && 3061ac5a404SSelvin Xavier free_idx == sgid_tbl->max) { 3071ac5a404SSelvin Xavier free_idx = i; 3081ac5a404SSelvin Xavier } 3091ac5a404SSelvin Xavier } 3101ac5a404SSelvin Xavier if (free_idx == sgid_tbl->max) { 3111ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 31208920b8fSJoe Perches "SGID table is FULL but count is not MAX??\n"); 3131ac5a404SSelvin Xavier return -ENOMEM; 3141ac5a404SSelvin Xavier } 3151ac5a404SSelvin Xavier if (update) { 3161ac5a404SSelvin Xavier struct cmdq_add_gid req; 317cc1ec769SDevesh Sharma struct creq_add_gid_resp resp; 3181ac5a404SSelvin Xavier u16 cmd_flags = 0; 319cc1ec769SDevesh Sharma int rc; 3201ac5a404SSelvin Xavier 3211ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ADD_GID, cmd_flags); 3221ac5a404SSelvin Xavier 3235fac5b1bSKalesh AP req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3245fac5b1bSKalesh AP req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3255fac5b1bSKalesh AP req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3265fac5b1bSKalesh AP req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3275fac5b1bSKalesh AP /* 3285fac5b1bSKalesh AP * driver should ensure that all RoCE traffic is always VLAN 3295fac5b1bSKalesh AP * tagged if RoCE traffic is running on non-zero VLAN ID or 3305fac5b1bSKalesh AP * RoCE traffic is running on non-zero Priority. 3315fac5b1bSKalesh AP */ 3325fac5b1bSKalesh AP if ((vlan_id != 0xFFFF) || res->prio) { 3331ac5a404SSelvin Xavier if (vlan_id != 0xFFFF) 3345fac5b1bSKalesh AP req.vlan = cpu_to_le16 3355fac5b1bSKalesh AP (vlan_id & CMDQ_ADD_GID_VLAN_VLAN_ID_MASK); 3365fac5b1bSKalesh AP req.vlan |= cpu_to_le16 3375fac5b1bSKalesh AP (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3381ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_EN); 3395fac5b1bSKalesh AP } 3401ac5a404SSelvin Xavier 3411ac5a404SSelvin Xavier /* MAC in network format */ 3425fac5b1bSKalesh AP req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3435fac5b1bSKalesh AP req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3445fac5b1bSKalesh AP req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3451ac5a404SSelvin Xavier 346cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 347cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 348cc1ec769SDevesh Sharma if (rc) 349cc1ec769SDevesh Sharma return rc; 350cc1ec769SDevesh Sharma sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); 3511ac5a404SSelvin Xavier } 3521ac5a404SSelvin Xavier /* Add GID to the sgid_tbl */ 3531ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 354c56b593dSSelvin Xavier sgid_tbl->tbl[free_idx].vlan_id = vlan_id; 3551ac5a404SSelvin Xavier sgid_tbl->active++; 3565fac5b1bSKalesh AP if (vlan_id != 0xFFFF) 3575fac5b1bSKalesh AP sgid_tbl->vlan[free_idx] = 1; 3585fac5b1bSKalesh AP 3591ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 36008920b8fSJoe Perches "SGID added hw_id[0x%x] = 0x%x active = 0x%x\n", 3611ac5a404SSelvin Xavier free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 3621ac5a404SSelvin Xavier 3631ac5a404SSelvin Xavier *index = free_idx; 3641ac5a404SSelvin Xavier /* unlock */ 365cc1ec769SDevesh Sharma return 0; 3661ac5a404SSelvin Xavier } 3671ac5a404SSelvin Xavier 3685fac5b1bSKalesh AP int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 3695fac5b1bSKalesh AP struct bnxt_qplib_gid *gid, u16 gid_idx, 3705fac5b1bSKalesh AP u8 *smac) 3715fac5b1bSKalesh AP { 3725fac5b1bSKalesh AP struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 3735fac5b1bSKalesh AP struct bnxt_qplib_res, 3745fac5b1bSKalesh AP sgid_tbl); 3755fac5b1bSKalesh AP struct bnxt_qplib_rcfw *rcfw = res->rcfw; 3765fac5b1bSKalesh AP struct creq_modify_gid_resp resp; 3775fac5b1bSKalesh AP struct cmdq_modify_gid req; 3785fac5b1bSKalesh AP int rc; 3795fac5b1bSKalesh AP u16 cmd_flags = 0; 3805fac5b1bSKalesh AP 3815fac5b1bSKalesh AP RCFW_CMD_PREP(req, MODIFY_GID, cmd_flags); 3825fac5b1bSKalesh AP 3835fac5b1bSKalesh AP req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); 3845fac5b1bSKalesh AP req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); 3855fac5b1bSKalesh AP req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); 3865fac5b1bSKalesh AP req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); 3875fac5b1bSKalesh AP if (res->prio) { 3885fac5b1bSKalesh AP req.vlan |= cpu_to_le16 3895fac5b1bSKalesh AP (CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 3905fac5b1bSKalesh AP CMDQ_ADD_GID_VLAN_VLAN_EN); 3915fac5b1bSKalesh AP } 3925fac5b1bSKalesh AP 3935fac5b1bSKalesh AP /* MAC in network format */ 3945fac5b1bSKalesh AP req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); 3955fac5b1bSKalesh AP req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); 3965fac5b1bSKalesh AP req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); 3975fac5b1bSKalesh AP 3985fac5b1bSKalesh AP req.gid_index = cpu_to_le16(gid_idx); 3995fac5b1bSKalesh AP 4005fac5b1bSKalesh AP rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 4015fac5b1bSKalesh AP (void *)&resp, NULL, 0); 4025fac5b1bSKalesh AP return rc; 4035fac5b1bSKalesh AP } 4045fac5b1bSKalesh AP 4051ac5a404SSelvin Xavier /* pkeys */ 4061ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, 4071ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index, 4081ac5a404SSelvin Xavier u16 *pkey) 4091ac5a404SSelvin Xavier { 4101ac5a404SSelvin Xavier if (index == 0xFFFF) { 4111ac5a404SSelvin Xavier *pkey = 0xFFFF; 4121ac5a404SSelvin Xavier return 0; 4131ac5a404SSelvin Xavier } 414474e5a86SDan Carpenter if (index >= pkey_tbl->max) { 4151ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 41608920b8fSJoe Perches "Index %d exceeded PKEY table max (%d)\n", 4171ac5a404SSelvin Xavier index, pkey_tbl->max); 4181ac5a404SSelvin Xavier return -EINVAL; 4191ac5a404SSelvin Xavier } 4201ac5a404SSelvin Xavier memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey)); 4211ac5a404SSelvin Xavier return 0; 4221ac5a404SSelvin Xavier } 4231ac5a404SSelvin Xavier 4241ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res, 4251ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4261ac5a404SSelvin Xavier bool update) 4271ac5a404SSelvin Xavier { 4281ac5a404SSelvin Xavier int i, rc = 0; 4291ac5a404SSelvin Xavier 4301ac5a404SSelvin Xavier if (!pkey_tbl) { 43108920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4321ac5a404SSelvin Xavier return -EINVAL; 4331ac5a404SSelvin Xavier } 4341ac5a404SSelvin Xavier 4351ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 4361ac5a404SSelvin Xavier if (!pkey_tbl->active) { 43708920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table has no active entries\n"); 4381ac5a404SSelvin Xavier return -ENOMEM; 4391ac5a404SSelvin Xavier } 4401ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 4411ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4421ac5a404SSelvin Xavier break; 4431ac5a404SSelvin Xavier } 4441ac5a404SSelvin Xavier if (i == pkey_tbl->max) { 4451ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 44608920b8fSJoe Perches "PKEY 0x%04x not found in the pkey table\n", *pkey); 4471ac5a404SSelvin Xavier return -ENOMEM; 4481ac5a404SSelvin Xavier } 4491ac5a404SSelvin Xavier memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey)); 4501ac5a404SSelvin Xavier pkey_tbl->active--; 4511ac5a404SSelvin Xavier 4521ac5a404SSelvin Xavier /* unlock */ 4531ac5a404SSelvin Xavier return rc; 4541ac5a404SSelvin Xavier } 4551ac5a404SSelvin Xavier 4561ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, 4571ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 4581ac5a404SSelvin Xavier bool update) 4591ac5a404SSelvin Xavier { 4601ac5a404SSelvin Xavier int i, free_idx, rc = 0; 4611ac5a404SSelvin Xavier 4621ac5a404SSelvin Xavier if (!pkey_tbl) { 46308920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table not allocated\n"); 4641ac5a404SSelvin Xavier return -EINVAL; 4651ac5a404SSelvin Xavier } 4661ac5a404SSelvin Xavier 4671ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 4681ac5a404SSelvin Xavier if (pkey_tbl->active == pkey_tbl->max) { 46908920b8fSJoe Perches dev_err(&res->pdev->dev, "PKEY table is full\n"); 4701ac5a404SSelvin Xavier return -ENOMEM; 4711ac5a404SSelvin Xavier } 4721ac5a404SSelvin Xavier free_idx = pkey_tbl->max; 4731ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 4741ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 4751ac5a404SSelvin Xavier return -EALREADY; 4761ac5a404SSelvin Xavier else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max) 4771ac5a404SSelvin Xavier free_idx = i; 4781ac5a404SSelvin Xavier } 4791ac5a404SSelvin Xavier if (free_idx == pkey_tbl->max) { 4801ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 48108920b8fSJoe Perches "PKEY table is FULL but count is not MAX??\n"); 4821ac5a404SSelvin Xavier return -ENOMEM; 4831ac5a404SSelvin Xavier } 4841ac5a404SSelvin Xavier /* Add PKEY to the pkey_tbl */ 4851ac5a404SSelvin Xavier memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey)); 4861ac5a404SSelvin Xavier pkey_tbl->active++; 4871ac5a404SSelvin Xavier 4881ac5a404SSelvin Xavier /* unlock */ 4891ac5a404SSelvin Xavier return rc; 4901ac5a404SSelvin Xavier } 4911ac5a404SSelvin Xavier 4921ac5a404SSelvin Xavier /* AH */ 49390e3edd8SGal Pressman int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 49490e3edd8SGal Pressman bool block) 4951ac5a404SSelvin Xavier { 4961ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 4971ac5a404SSelvin Xavier struct cmdq_create_ah req; 498cc1ec769SDevesh Sharma struct creq_create_ah_resp resp; 4991ac5a404SSelvin Xavier u16 cmd_flags = 0; 5001ac5a404SSelvin Xavier u32 temp32[4]; 5011ac5a404SSelvin Xavier u16 temp16[3]; 502cc1ec769SDevesh Sharma int rc; 5031ac5a404SSelvin Xavier 5041ac5a404SSelvin Xavier RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); 5051ac5a404SSelvin Xavier 5061ac5a404SSelvin Xavier memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 5071ac5a404SSelvin Xavier req.dgid[0] = cpu_to_le32(temp32[0]); 5081ac5a404SSelvin Xavier req.dgid[1] = cpu_to_le32(temp32[1]); 5091ac5a404SSelvin Xavier req.dgid[2] = cpu_to_le32(temp32[2]); 5101ac5a404SSelvin Xavier req.dgid[3] = cpu_to_le32(temp32[3]); 5111ac5a404SSelvin Xavier 5121ac5a404SSelvin Xavier req.type = ah->nw_type; 5131ac5a404SSelvin Xavier req.hop_limit = ah->hop_limit; 5141ac5a404SSelvin Xavier req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 5151ac5a404SSelvin Xavier req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 5161ac5a404SSelvin Xavier CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 5171ac5a404SSelvin Xavier CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 5181ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(ah->pd->id); 5191ac5a404SSelvin Xavier req.traffic_class = ah->traffic_class; 5201ac5a404SSelvin Xavier 5211ac5a404SSelvin Xavier /* MAC in network format */ 5221ac5a404SSelvin Xavier memcpy(temp16, ah->dmac, 6); 5231ac5a404SSelvin Xavier req.dest_mac[0] = cpu_to_le16(temp16[0]); 5241ac5a404SSelvin Xavier req.dest_mac[1] = cpu_to_le16(temp16[1]); 5251ac5a404SSelvin Xavier req.dest_mac[2] = cpu_to_le16(temp16[2]); 5261ac5a404SSelvin Xavier 527cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 52890e3edd8SGal Pressman NULL, block); 529cc1ec769SDevesh Sharma if (rc) 530cc1ec769SDevesh Sharma return rc; 531cc1ec769SDevesh Sharma 532cc1ec769SDevesh Sharma ah->id = le32_to_cpu(resp.xid); 5331ac5a404SSelvin Xavier return 0; 5341ac5a404SSelvin Xavier } 5351ac5a404SSelvin Xavier 536d3456914SLeon Romanovsky void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, 53750c582deSGal Pressman bool block) 5381ac5a404SSelvin Xavier { 5391ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5401ac5a404SSelvin Xavier struct cmdq_destroy_ah req; 541cc1ec769SDevesh Sharma struct creq_destroy_ah_resp resp; 5421ac5a404SSelvin Xavier u16 cmd_flags = 0; 5431ac5a404SSelvin Xavier 5441ac5a404SSelvin Xavier /* Clean up the AH table in the device */ 5451ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); 5461ac5a404SSelvin Xavier 5471ac5a404SSelvin Xavier req.ah_cid = cpu_to_le32(ah->id); 5481ac5a404SSelvin Xavier 549d3456914SLeon Romanovsky bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 550d3456914SLeon Romanovsky block); 5511ac5a404SSelvin Xavier } 5521ac5a404SSelvin Xavier 5531ac5a404SSelvin Xavier /* MRW */ 5541ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5551ac5a404SSelvin Xavier { 5561ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5571ac5a404SSelvin Xavier struct cmdq_deallocate_key req; 558cc1ec769SDevesh Sharma struct creq_deallocate_key_resp resp; 5591ac5a404SSelvin Xavier u16 cmd_flags = 0; 560cc1ec769SDevesh Sharma int rc; 5611ac5a404SSelvin Xavier 5621ac5a404SSelvin Xavier if (mrw->lkey == 0xFFFFFFFF) { 56308920b8fSJoe Perches dev_info(&res->pdev->dev, "SP: Free a reserved lkey MRW\n"); 5641ac5a404SSelvin Xavier return 0; 5651ac5a404SSelvin Xavier } 5661ac5a404SSelvin Xavier 5671ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags); 5681ac5a404SSelvin Xavier 5691ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 5701ac5a404SSelvin Xavier 5711ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 5721ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 5731ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 5741ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->rkey); 5751ac5a404SSelvin Xavier else 5761ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->lkey); 5771ac5a404SSelvin Xavier 578cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 5791ac5a404SSelvin Xavier NULL, 0); 580cc1ec769SDevesh Sharma if (rc) 581cc1ec769SDevesh Sharma return rc; 582cc1ec769SDevesh Sharma 5831ac5a404SSelvin Xavier /* Free the qplib's MRW memory */ 5841ac5a404SSelvin Xavier if (mrw->hwq.max_elements) 5850c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &mrw->hwq); 5861ac5a404SSelvin Xavier 5871ac5a404SSelvin Xavier return 0; 5881ac5a404SSelvin Xavier } 5891ac5a404SSelvin Xavier 5901ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 5911ac5a404SSelvin Xavier { 5921ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 5931ac5a404SSelvin Xavier struct cmdq_allocate_mrw req; 594cc1ec769SDevesh Sharma struct creq_allocate_mrw_resp resp; 5951ac5a404SSelvin Xavier u16 cmd_flags = 0; 5961ac5a404SSelvin Xavier unsigned long tmp; 597cc1ec769SDevesh Sharma int rc; 5981ac5a404SSelvin Xavier 5991ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); 6001ac5a404SSelvin Xavier 6011ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(mrw->pd->id); 6021ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 6031ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 6041ac5a404SSelvin Xavier mrw->flags & BNXT_QPLIB_FR_PMR) || 6051ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 6061ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 6071ac5a404SSelvin Xavier req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 6081ac5a404SSelvin Xavier tmp = (unsigned long)mrw; 6091ac5a404SSelvin Xavier req.mrw_handle = cpu_to_le64(tmp); 6101ac5a404SSelvin Xavier 611cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 612cc1ec769SDevesh Sharma (void *)&resp, NULL, 0); 613cc1ec769SDevesh Sharma if (rc) 614cc1ec769SDevesh Sharma return rc; 615cc1ec769SDevesh Sharma 6161ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 6171ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 6181ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 619cc1ec769SDevesh Sharma mrw->rkey = le32_to_cpu(resp.xid); 6201ac5a404SSelvin Xavier else 621cc1ec769SDevesh Sharma mrw->lkey = le32_to_cpu(resp.xid); 6221ac5a404SSelvin Xavier return 0; 6231ac5a404SSelvin Xavier } 6241ac5a404SSelvin Xavier 6251ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 6261ac5a404SSelvin Xavier bool block) 6271ac5a404SSelvin Xavier { 6281ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6291ac5a404SSelvin Xavier struct cmdq_deregister_mr req; 630cc1ec769SDevesh Sharma struct creq_deregister_mr_resp resp; 6311ac5a404SSelvin Xavier u16 cmd_flags = 0; 6321ac5a404SSelvin Xavier int rc; 6331ac5a404SSelvin Xavier 6341ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); 6351ac5a404SSelvin Xavier 6361ac5a404SSelvin Xavier req.lkey = cpu_to_le32(mrw->lkey); 637cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 638cc1ec769SDevesh Sharma (void *)&resp, NULL, block); 639cc1ec769SDevesh Sharma if (rc) 640cc1ec769SDevesh Sharma return rc; 6411ac5a404SSelvin Xavier 6421ac5a404SSelvin Xavier /* Free the qplib's MR memory */ 6431ac5a404SSelvin Xavier if (mrw->hwq.max_elements) { 6441ac5a404SSelvin Xavier mrw->va = 0; 6451ac5a404SSelvin Xavier mrw->total_size = 0; 6460c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &mrw->hwq); 6471ac5a404SSelvin Xavier } 6481ac5a404SSelvin Xavier 6491ac5a404SSelvin Xavier return 0; 6501ac5a404SSelvin Xavier } 6511ac5a404SSelvin Xavier 6521ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 653*f6919d56SSelvin Xavier struct ib_umem *umem, int num_pbls, u32 buf_pg_size) 6541ac5a404SSelvin Xavier { 6551ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 6560c4dcd60SDevesh Sharma struct bnxt_qplib_hwq_attr hwq_attr = {}; 6570c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info sginfo = {}; 658cc1ec769SDevesh Sharma struct creq_register_mr_resp resp; 6590c4dcd60SDevesh Sharma struct cmdq_register_mr req; 6600c4dcd60SDevesh Sharma u16 cmd_flags = 0, level; 661*f6919d56SSelvin Xavier int pages, rc, pg_ptrs; 6621ac5a404SSelvin Xavier u32 pg_size; 6631ac5a404SSelvin Xavier 6641ac5a404SSelvin Xavier if (num_pbls) { 665872f3578SSomnath Kotur /* Allocate memory for the non-leaf pages to store buf ptrs. 666872f3578SSomnath Kotur * Non-leaf pages always uses system PAGE_SIZE 667872f3578SSomnath Kotur */ 6681ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(num_pbls); 6691ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 6701ac5a404SSelvin Xavier if (!pages) 6711ac5a404SSelvin Xavier pages++; 6721ac5a404SSelvin Xavier 6731ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) { 6741ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 6750c4dcd60SDevesh Sharma "SP: Reg MR: pages requested (0x%x) exceeded max (0x%x)\n", 6761ac5a404SSelvin Xavier pages, MAX_PBL_LVL_1_PGS); 6771ac5a404SSelvin Xavier return -ENOMEM; 6781ac5a404SSelvin Xavier } 6791ac5a404SSelvin Xavier /* Free the hwq if it already exist, must be a rereg */ 6801ac5a404SSelvin Xavier if (mr->hwq.max_elements) 6810c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &mr->hwq); 682872f3578SSomnath Kotur /* Use system PAGE_SIZE */ 6830c4dcd60SDevesh Sharma hwq_attr.res = res; 6840c4dcd60SDevesh Sharma hwq_attr.depth = pages; 685*f6919d56SSelvin Xavier hwq_attr.stride = buf_pg_size; 6860c4dcd60SDevesh Sharma hwq_attr.type = HWQ_TYPE_MR; 6870c4dcd60SDevesh Sharma hwq_attr.sginfo = &sginfo; 688*f6919d56SSelvin Xavier hwq_attr.sginfo->umem = umem; 6890c4dcd60SDevesh Sharma hwq_attr.sginfo->npages = pages; 6900c4dcd60SDevesh Sharma hwq_attr.sginfo->pgsize = PAGE_SIZE; 6910c4dcd60SDevesh Sharma hwq_attr.sginfo->pgshft = PAGE_SHIFT; 6920c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr); 6931ac5a404SSelvin Xavier if (rc) { 6941ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 69508920b8fSJoe Perches "SP: Reg MR memory allocation failed\n"); 6961ac5a404SSelvin Xavier return -ENOMEM; 6971ac5a404SSelvin Xavier } 6981ac5a404SSelvin Xavier } 6991ac5a404SSelvin Xavier 7001ac5a404SSelvin Xavier RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); 7011ac5a404SSelvin Xavier 7021ac5a404SSelvin Xavier /* Configure the request */ 7031ac5a404SSelvin Xavier if (mr->hwq.level == PBL_LVL_MAX) { 704872f3578SSomnath Kotur /* No PBL provided, just use system PAGE_SIZE */ 7051ac5a404SSelvin Xavier level = 0; 7061ac5a404SSelvin Xavier req.pbl = 0; 7071ac5a404SSelvin Xavier pg_size = PAGE_SIZE; 7081ac5a404SSelvin Xavier } else { 709*f6919d56SSelvin Xavier level = mr->hwq.level; 7101ac5a404SSelvin Xavier req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 7111ac5a404SSelvin Xavier } 712872f3578SSomnath Kotur pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE; 7131ac5a404SSelvin Xavier req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 7141ac5a404SSelvin Xavier ((ilog2(pg_size) << 7151ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 7161ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 717872f3578SSomnath Kotur req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) << 718872f3578SSomnath Kotur CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) & 719872f3578SSomnath Kotur CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK)); 7201ac5a404SSelvin Xavier req.access = (mr->flags & 0xFFFF); 7211ac5a404SSelvin Xavier req.va = cpu_to_le64(mr->va); 7221ac5a404SSelvin Xavier req.key = cpu_to_le32(mr->lkey); 7231ac5a404SSelvin Xavier req.mr_size = cpu_to_le64(mr->total_size); 7241ac5a404SSelvin Xavier 725cc1ec769SDevesh Sharma rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 726*f6919d56SSelvin Xavier (void *)&resp, NULL, false); 727cc1ec769SDevesh Sharma if (rc) 7281ac5a404SSelvin Xavier goto fail; 729cc1ec769SDevesh Sharma 7301ac5a404SSelvin Xavier return 0; 7311ac5a404SSelvin Xavier 7321ac5a404SSelvin Xavier fail: 7331ac5a404SSelvin Xavier if (mr->hwq.max_elements) 7340c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &mr->hwq); 7351ac5a404SSelvin Xavier return rc; 7361ac5a404SSelvin Xavier } 7371ac5a404SSelvin Xavier 7381ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 7391ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl, 7401ac5a404SSelvin Xavier int max_pg_ptrs) 7411ac5a404SSelvin Xavier { 7420c4dcd60SDevesh Sharma struct bnxt_qplib_hwq_attr hwq_attr = {}; 7430c4dcd60SDevesh Sharma struct bnxt_qplib_sg_info sginfo = {}; 7441ac5a404SSelvin Xavier int pg_ptrs, pages, rc; 7451ac5a404SSelvin Xavier 7461ac5a404SSelvin Xavier /* Re-calculate the max to fit the HWQ allocation model */ 7471ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 7481ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 7491ac5a404SSelvin Xavier if (!pages) 7501ac5a404SSelvin Xavier pages++; 7511ac5a404SSelvin Xavier 7521ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) 7531ac5a404SSelvin Xavier return -ENOMEM; 7541ac5a404SSelvin Xavier 7550c4dcd60SDevesh Sharma sginfo.pgsize = PAGE_SIZE; 7560c4dcd60SDevesh Sharma sginfo.nopte = true; 7570c4dcd60SDevesh Sharma 7580c4dcd60SDevesh Sharma hwq_attr.res = res; 7590c4dcd60SDevesh Sharma hwq_attr.depth = pg_ptrs; 7600c4dcd60SDevesh Sharma hwq_attr.stride = PAGE_SIZE; 7610c4dcd60SDevesh Sharma hwq_attr.sginfo = &sginfo; 7620c4dcd60SDevesh Sharma hwq_attr.type = HWQ_TYPE_CTX; 7630c4dcd60SDevesh Sharma rc = bnxt_qplib_alloc_init_hwq(&frpl->hwq, &hwq_attr); 7641ac5a404SSelvin Xavier if (!rc) 7651ac5a404SSelvin Xavier frpl->max_pg_ptrs = pg_ptrs; 7661ac5a404SSelvin Xavier 7671ac5a404SSelvin Xavier return rc; 7681ac5a404SSelvin Xavier } 7691ac5a404SSelvin Xavier 7701ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 7711ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl) 7721ac5a404SSelvin Xavier { 7730c4dcd60SDevesh Sharma bnxt_qplib_free_hwq(res, &frpl->hwq); 7741ac5a404SSelvin Xavier return 0; 7751ac5a404SSelvin Xavier } 7761ac5a404SSelvin Xavier 7771ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) 7781ac5a404SSelvin Xavier { 7791ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 7801ac5a404SSelvin Xavier struct cmdq_map_tc_to_cos req; 781cc1ec769SDevesh Sharma struct creq_map_tc_to_cos_resp resp; 7821ac5a404SSelvin Xavier u16 cmd_flags = 0; 7831ac5a404SSelvin Xavier 7841ac5a404SSelvin Xavier RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); 7851ac5a404SSelvin Xavier req.cos0 = cpu_to_le16(cids[0]); 7861ac5a404SSelvin Xavier req.cos1 = cpu_to_le16(cids[1]); 7871ac5a404SSelvin Xavier 78894edd87aSAditya Pakki return bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 78994edd87aSAditya Pakki NULL, 0); 7901ac5a404SSelvin Xavier } 79189f81008SSelvin Xavier 79289f81008SSelvin Xavier int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw, 79389f81008SSelvin Xavier struct bnxt_qplib_roce_stats *stats) 79489f81008SSelvin Xavier { 79589f81008SSelvin Xavier struct cmdq_query_roce_stats req; 79689f81008SSelvin Xavier struct creq_query_roce_stats_resp resp; 79789f81008SSelvin Xavier struct bnxt_qplib_rcfw_sbuf *sbuf; 79889f81008SSelvin Xavier struct creq_query_roce_stats_resp_sb *sb; 79989f81008SSelvin Xavier u16 cmd_flags = 0; 80089f81008SSelvin Xavier int rc = 0; 80189f81008SSelvin Xavier 80289f81008SSelvin Xavier RCFW_CMD_PREP(req, QUERY_ROCE_STATS, cmd_flags); 80389f81008SSelvin Xavier 80489f81008SSelvin Xavier sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); 80589f81008SSelvin Xavier if (!sbuf) { 80689f81008SSelvin Xavier dev_err(&rcfw->pdev->dev, 80708920b8fSJoe Perches "SP: QUERY_ROCE_STATS alloc side buffer failed\n"); 80889f81008SSelvin Xavier return -ENOMEM; 80989f81008SSelvin Xavier } 81089f81008SSelvin Xavier 81189f81008SSelvin Xavier sb = sbuf->sb; 81289f81008SSelvin Xavier req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 81389f81008SSelvin Xavier rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, 81489f81008SSelvin Xavier (void *)sbuf, 0); 81589f81008SSelvin Xavier if (rc) 81689f81008SSelvin Xavier goto bail; 81789f81008SSelvin Xavier /* Extract the context from the side buffer */ 81889f81008SSelvin Xavier stats->to_retransmits = le64_to_cpu(sb->to_retransmits); 81989f81008SSelvin Xavier stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); 82089f81008SSelvin Xavier stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded); 82189f81008SSelvin Xavier stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); 82289f81008SSelvin Xavier stats->missing_resp = le64_to_cpu(sb->missing_resp); 82389f81008SSelvin Xavier stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err); 82489f81008SSelvin Xavier stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err); 82589f81008SSelvin Xavier stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err); 82689f81008SSelvin Xavier stats->local_protection_err = le64_to_cpu(sb->local_protection_err); 82789f81008SSelvin Xavier stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err); 82889f81008SSelvin Xavier stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err); 82989f81008SSelvin Xavier stats->remote_access_err = le64_to_cpu(sb->remote_access_err); 83089f81008SSelvin Xavier stats->remote_op_err = le64_to_cpu(sb->remote_op_err); 83189f81008SSelvin Xavier stats->dup_req = le64_to_cpu(sb->dup_req); 83289f81008SSelvin Xavier stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max); 83389f81008SSelvin Xavier stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch); 83489f81008SSelvin Xavier stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe); 83589f81008SSelvin Xavier stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err); 83689f81008SSelvin Xavier stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey); 83789f81008SSelvin Xavier stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err); 83889f81008SSelvin Xavier stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm); 83989f81008SSelvin Xavier stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err); 84089f81008SSelvin Xavier stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey); 84189f81008SSelvin Xavier stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err); 84289f81008SSelvin Xavier stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm); 84389f81008SSelvin Xavier stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err); 84489f81008SSelvin Xavier stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow); 84589f81008SSelvin Xavier stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode); 84689f81008SSelvin Xavier stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic); 84789f81008SSelvin Xavier stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err); 84889f81008SSelvin Xavier stats->res_mem_error = le64_to_cpu(sb->res_mem_error); 84989f81008SSelvin Xavier stats->res_srq_err = le64_to_cpu(sb->res_srq_err); 85089f81008SSelvin Xavier stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err); 85189f81008SSelvin Xavier stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey); 85289f81008SSelvin Xavier stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err); 85389f81008SSelvin Xavier stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err); 85489f81008SSelvin Xavier stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err); 85589f81008SSelvin Xavier stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err); 85689f81008SSelvin Xavier stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err); 857316dd282SSelvin Xavier if (!rcfw->init_oos_stats) { 858316dd282SSelvin Xavier rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 859316dd282SSelvin Xavier rcfw->init_oos_stats = 1; 860316dd282SSelvin Xavier } else { 861316dd282SSelvin Xavier stats->res_oos_drop_count += 862316dd282SSelvin Xavier (le64_to_cpu(sb->res_oos_drop_count) - 863316dd282SSelvin Xavier rcfw->oos_prev) & BNXT_QPLIB_OOS_COUNT_MASK; 864316dd282SSelvin Xavier rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); 865316dd282SSelvin Xavier } 866316dd282SSelvin Xavier 86789f81008SSelvin Xavier bail: 86889f81008SSelvin Xavier bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 86989f81008SSelvin Xavier return rc; 87089f81008SSelvin Xavier } 871