1*1ac5a404SSelvin Xavier /* 2*1ac5a404SSelvin Xavier * Broadcom NetXtreme-E RoCE driver. 3*1ac5a404SSelvin Xavier * 4*1ac5a404SSelvin Xavier * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term 5*1ac5a404SSelvin Xavier * Broadcom refers to Broadcom Limited and/or its subsidiaries. 6*1ac5a404SSelvin Xavier * 7*1ac5a404SSelvin Xavier * This software is available to you under a choice of one of two 8*1ac5a404SSelvin Xavier * licenses. You may choose to be licensed under the terms of the GNU 9*1ac5a404SSelvin Xavier * General Public License (GPL) Version 2, available from the file 10*1ac5a404SSelvin Xavier * COPYING in the main directory of this source tree, or the 11*1ac5a404SSelvin Xavier * BSD license below: 12*1ac5a404SSelvin Xavier * 13*1ac5a404SSelvin Xavier * Redistribution and use in source and binary forms, with or without 14*1ac5a404SSelvin Xavier * modification, are permitted provided that the following conditions 15*1ac5a404SSelvin Xavier * are met: 16*1ac5a404SSelvin Xavier * 17*1ac5a404SSelvin Xavier * 1. Redistributions of source code must retain the above copyright 18*1ac5a404SSelvin Xavier * notice, this list of conditions and the following disclaimer. 19*1ac5a404SSelvin Xavier * 2. Redistributions in binary form must reproduce the above copyright 20*1ac5a404SSelvin Xavier * notice, this list of conditions and the following disclaimer in 21*1ac5a404SSelvin Xavier * the documentation and/or other materials provided with the 22*1ac5a404SSelvin Xavier * distribution. 23*1ac5a404SSelvin Xavier * 24*1ac5a404SSelvin Xavier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 25*1ac5a404SSelvin Xavier * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 26*1ac5a404SSelvin Xavier * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27*1ac5a404SSelvin Xavier * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 28*1ac5a404SSelvin Xavier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29*1ac5a404SSelvin Xavier * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30*1ac5a404SSelvin Xavier * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31*1ac5a404SSelvin Xavier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32*1ac5a404SSelvin Xavier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33*1ac5a404SSelvin Xavier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34*1ac5a404SSelvin Xavier * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35*1ac5a404SSelvin Xavier * 36*1ac5a404SSelvin Xavier * Description: Slow Path Operators 37*1ac5a404SSelvin Xavier */ 38*1ac5a404SSelvin Xavier 39*1ac5a404SSelvin Xavier #include <linux/interrupt.h> 40*1ac5a404SSelvin Xavier #include <linux/spinlock.h> 41*1ac5a404SSelvin Xavier #include <linux/sched.h> 42*1ac5a404SSelvin Xavier #include <linux/pci.h> 43*1ac5a404SSelvin Xavier 44*1ac5a404SSelvin Xavier #include "roce_hsi.h" 45*1ac5a404SSelvin Xavier 46*1ac5a404SSelvin Xavier #include "qplib_res.h" 47*1ac5a404SSelvin Xavier #include "qplib_rcfw.h" 48*1ac5a404SSelvin Xavier #include "qplib_sp.h" 49*1ac5a404SSelvin Xavier 50*1ac5a404SSelvin Xavier const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 51*1ac5a404SSelvin Xavier 0, 0, 0, 0, 0, 0, 0, 0 } }; 52*1ac5a404SSelvin Xavier 53*1ac5a404SSelvin Xavier /* Device */ 54*1ac5a404SSelvin Xavier int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, 55*1ac5a404SSelvin Xavier struct bnxt_qplib_dev_attr *attr) 56*1ac5a404SSelvin Xavier { 57*1ac5a404SSelvin Xavier struct cmdq_query_func req; 58*1ac5a404SSelvin Xavier struct creq_query_func_resp *resp; 59*1ac5a404SSelvin Xavier struct creq_query_func_resp_sb *sb; 60*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 61*1ac5a404SSelvin Xavier u32 temp; 62*1ac5a404SSelvin Xavier u8 *tqm_alloc; 63*1ac5a404SSelvin Xavier int i; 64*1ac5a404SSelvin Xavier 65*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags); 66*1ac5a404SSelvin Xavier 67*1ac5a404SSelvin Xavier req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; 68*1ac5a404SSelvin Xavier resp = (struct creq_query_func_resp *) 69*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void **)&sb, 70*1ac5a404SSelvin Xavier 0); 71*1ac5a404SSelvin Xavier if (!resp) { 72*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC send failed"); 73*1ac5a404SSelvin Xavier return -EINVAL; 74*1ac5a404SSelvin Xavier } 75*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { 76*1ac5a404SSelvin Xavier /* Cmd timed out */ 77*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC timed out"); 78*1ac5a404SSelvin Xavier return -ETIMEDOUT; 79*1ac5a404SSelvin Xavier } 80*1ac5a404SSelvin Xavier if (resp->status || 81*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 82*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC failed "); 83*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 84*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 85*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 86*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 87*1ac5a404SSelvin Xavier return -EINVAL; 88*1ac5a404SSelvin Xavier } 89*1ac5a404SSelvin Xavier /* Extract the context from the side buffer */ 90*1ac5a404SSelvin Xavier attr->max_qp = le32_to_cpu(sb->max_qp); 91*1ac5a404SSelvin Xavier attr->max_qp_rd_atom = 92*1ac5a404SSelvin Xavier sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 93*1ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; 94*1ac5a404SSelvin Xavier attr->max_qp_init_rd_atom = 95*1ac5a404SSelvin Xavier sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? 96*1ac5a404SSelvin Xavier BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; 97*1ac5a404SSelvin Xavier attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); 98*1ac5a404SSelvin Xavier attr->max_qp_sges = sb->max_sge; 99*1ac5a404SSelvin Xavier attr->max_cq = le32_to_cpu(sb->max_cq); 100*1ac5a404SSelvin Xavier attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); 101*1ac5a404SSelvin Xavier attr->max_cq_sges = attr->max_qp_sges; 102*1ac5a404SSelvin Xavier attr->max_mr = le32_to_cpu(sb->max_mr); 103*1ac5a404SSelvin Xavier attr->max_mw = le32_to_cpu(sb->max_mw); 104*1ac5a404SSelvin Xavier 105*1ac5a404SSelvin Xavier attr->max_mr_size = le64_to_cpu(sb->max_mr_size); 106*1ac5a404SSelvin Xavier attr->max_pd = 64 * 1024; 107*1ac5a404SSelvin Xavier attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); 108*1ac5a404SSelvin Xavier attr->max_ah = le32_to_cpu(sb->max_ah); 109*1ac5a404SSelvin Xavier 110*1ac5a404SSelvin Xavier attr->max_fmr = le32_to_cpu(sb->max_fmr); 111*1ac5a404SSelvin Xavier attr->max_map_per_fmr = sb->max_map_per_fmr; 112*1ac5a404SSelvin Xavier 113*1ac5a404SSelvin Xavier attr->max_srq = le16_to_cpu(sb->max_srq); 114*1ac5a404SSelvin Xavier attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; 115*1ac5a404SSelvin Xavier attr->max_srq_sges = sb->max_srq_sge; 116*1ac5a404SSelvin Xavier /* Bono only reports 1 PKEY for now, but it can support > 1 */ 117*1ac5a404SSelvin Xavier attr->max_pkey = le32_to_cpu(sb->max_pkeys); 118*1ac5a404SSelvin Xavier 119*1ac5a404SSelvin Xavier attr->max_inline_data = le32_to_cpu(sb->max_inline_data); 120*1ac5a404SSelvin Xavier attr->l2_db_size = (sb->l2_db_space_size + 1) * PAGE_SIZE; 121*1ac5a404SSelvin Xavier attr->max_sgid = le32_to_cpu(sb->max_gid); 122*1ac5a404SSelvin Xavier 123*1ac5a404SSelvin Xavier strlcpy(attr->fw_ver, "20.6.28.0", sizeof(attr->fw_ver)); 124*1ac5a404SSelvin Xavier 125*1ac5a404SSelvin Xavier for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { 126*1ac5a404SSelvin Xavier temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); 127*1ac5a404SSelvin Xavier tqm_alloc = (u8 *)&temp; 128*1ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; 129*1ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); 130*1ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); 131*1ac5a404SSelvin Xavier attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 132*1ac5a404SSelvin Xavier } 133*1ac5a404SSelvin Xavier return 0; 134*1ac5a404SSelvin Xavier } 135*1ac5a404SSelvin Xavier 136*1ac5a404SSelvin Xavier /* SGID */ 137*1ac5a404SSelvin Xavier int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, 138*1ac5a404SSelvin Xavier struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, 139*1ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid) 140*1ac5a404SSelvin Xavier { 141*1ac5a404SSelvin Xavier if (index > sgid_tbl->max) { 142*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 143*1ac5a404SSelvin Xavier "QPLIB: Index %d exceeded SGID table max (%d)", 144*1ac5a404SSelvin Xavier index, sgid_tbl->max); 145*1ac5a404SSelvin Xavier return -EINVAL; 146*1ac5a404SSelvin Xavier } 147*1ac5a404SSelvin Xavier memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid)); 148*1ac5a404SSelvin Xavier return 0; 149*1ac5a404SSelvin Xavier } 150*1ac5a404SSelvin Xavier 151*1ac5a404SSelvin Xavier int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 152*1ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, bool update) 153*1ac5a404SSelvin Xavier { 154*1ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 155*1ac5a404SSelvin Xavier struct bnxt_qplib_res, 156*1ac5a404SSelvin Xavier sgid_tbl); 157*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 158*1ac5a404SSelvin Xavier int index; 159*1ac5a404SSelvin Xavier 160*1ac5a404SSelvin Xavier if (!sgid_tbl) { 161*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated"); 162*1ac5a404SSelvin Xavier return -EINVAL; 163*1ac5a404SSelvin Xavier } 164*1ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 165*1ac5a404SSelvin Xavier if (!sgid_tbl->active) { 166*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 167*1ac5a404SSelvin Xavier "QPLIB: SGID table has no active entries"); 168*1ac5a404SSelvin Xavier return -ENOMEM; 169*1ac5a404SSelvin Xavier } 170*1ac5a404SSelvin Xavier for (index = 0; index < sgid_tbl->max; index++) { 171*1ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid))) 172*1ac5a404SSelvin Xavier break; 173*1ac5a404SSelvin Xavier } 174*1ac5a404SSelvin Xavier if (index == sgid_tbl->max) { 175*1ac5a404SSelvin Xavier dev_warn(&res->pdev->dev, "GID not found in the SGID table"); 176*1ac5a404SSelvin Xavier return 0; 177*1ac5a404SSelvin Xavier } 178*1ac5a404SSelvin Xavier /* Remove GID from the SGID table */ 179*1ac5a404SSelvin Xavier if (update) { 180*1ac5a404SSelvin Xavier struct cmdq_delete_gid req; 181*1ac5a404SSelvin Xavier struct creq_delete_gid_resp *resp; 182*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 183*1ac5a404SSelvin Xavier 184*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); 185*1ac5a404SSelvin Xavier if (sgid_tbl->hw_id[index] == 0xFFFF) { 186*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 187*1ac5a404SSelvin Xavier "QPLIB: GID entry contains an invalid HW id"); 188*1ac5a404SSelvin Xavier return -EINVAL; 189*1ac5a404SSelvin Xavier } 190*1ac5a404SSelvin Xavier req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); 191*1ac5a404SSelvin Xavier resp = (struct creq_delete_gid_resp *) 192*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 193*1ac5a404SSelvin Xavier 0); 194*1ac5a404SSelvin Xavier if (!resp) { 195*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 196*1ac5a404SSelvin Xavier "QPLIB: SP: DELETE_GID send failed"); 197*1ac5a404SSelvin Xavier return -EINVAL; 198*1ac5a404SSelvin Xavier } 199*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, 200*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie))) { 201*1ac5a404SSelvin Xavier /* Cmd timed out */ 202*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 203*1ac5a404SSelvin Xavier "QPLIB: SP: DELETE_GID timed out"); 204*1ac5a404SSelvin Xavier return -ETIMEDOUT; 205*1ac5a404SSelvin Xavier } 206*1ac5a404SSelvin Xavier if (resp->status || 207*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 208*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 209*1ac5a404SSelvin Xavier "QPLIB: SP: DELETE_GID failed "); 210*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 211*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 212*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 213*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 214*1ac5a404SSelvin Xavier return -EINVAL; 215*1ac5a404SSelvin Xavier } 216*1ac5a404SSelvin Xavier } 217*1ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, 218*1ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)); 219*1ac5a404SSelvin Xavier sgid_tbl->active--; 220*1ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 221*1ac5a404SSelvin Xavier "QPLIB: SGID deleted hw_id[0x%x] = 0x%x active = 0x%x", 222*1ac5a404SSelvin Xavier index, sgid_tbl->hw_id[index], sgid_tbl->active); 223*1ac5a404SSelvin Xavier sgid_tbl->hw_id[index] = (u16)-1; 224*1ac5a404SSelvin Xavier 225*1ac5a404SSelvin Xavier /* unlock */ 226*1ac5a404SSelvin Xavier return 0; 227*1ac5a404SSelvin Xavier } 228*1ac5a404SSelvin Xavier 229*1ac5a404SSelvin Xavier int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, 230*1ac5a404SSelvin Xavier struct bnxt_qplib_gid *gid, u8 *smac, u16 vlan_id, 231*1ac5a404SSelvin Xavier bool update, u32 *index) 232*1ac5a404SSelvin Xavier { 233*1ac5a404SSelvin Xavier struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, 234*1ac5a404SSelvin Xavier struct bnxt_qplib_res, 235*1ac5a404SSelvin Xavier sgid_tbl); 236*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 237*1ac5a404SSelvin Xavier int i, free_idx, rc = 0; 238*1ac5a404SSelvin Xavier 239*1ac5a404SSelvin Xavier if (!sgid_tbl) { 240*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated"); 241*1ac5a404SSelvin Xavier return -EINVAL; 242*1ac5a404SSelvin Xavier } 243*1ac5a404SSelvin Xavier /* Do we need a sgid_lock here? */ 244*1ac5a404SSelvin Xavier if (sgid_tbl->active == sgid_tbl->max) { 245*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SGID table is full"); 246*1ac5a404SSelvin Xavier return -ENOMEM; 247*1ac5a404SSelvin Xavier } 248*1ac5a404SSelvin Xavier free_idx = sgid_tbl->max; 249*1ac5a404SSelvin Xavier for (i = 0; i < sgid_tbl->max; i++) { 250*1ac5a404SSelvin Xavier if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) { 251*1ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 252*1ac5a404SSelvin Xavier "QPLIB: SGID entry already exist in entry %d!", 253*1ac5a404SSelvin Xavier i); 254*1ac5a404SSelvin Xavier *index = i; 255*1ac5a404SSelvin Xavier return -EALREADY; 256*1ac5a404SSelvin Xavier } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, 257*1ac5a404SSelvin Xavier sizeof(bnxt_qplib_gid_zero)) && 258*1ac5a404SSelvin Xavier free_idx == sgid_tbl->max) { 259*1ac5a404SSelvin Xavier free_idx = i; 260*1ac5a404SSelvin Xavier } 261*1ac5a404SSelvin Xavier } 262*1ac5a404SSelvin Xavier if (free_idx == sgid_tbl->max) { 263*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 264*1ac5a404SSelvin Xavier "QPLIB: SGID table is FULL but count is not MAX??"); 265*1ac5a404SSelvin Xavier return -ENOMEM; 266*1ac5a404SSelvin Xavier } 267*1ac5a404SSelvin Xavier if (update) { 268*1ac5a404SSelvin Xavier struct cmdq_add_gid req; 269*1ac5a404SSelvin Xavier struct creq_add_gid_resp *resp; 270*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 271*1ac5a404SSelvin Xavier u32 temp32[4]; 272*1ac5a404SSelvin Xavier u16 temp16[3]; 273*1ac5a404SSelvin Xavier 274*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ADD_GID, cmd_flags); 275*1ac5a404SSelvin Xavier 276*1ac5a404SSelvin Xavier memcpy(temp32, gid->data, sizeof(struct bnxt_qplib_gid)); 277*1ac5a404SSelvin Xavier req.gid[0] = cpu_to_be32(temp32[3]); 278*1ac5a404SSelvin Xavier req.gid[1] = cpu_to_be32(temp32[2]); 279*1ac5a404SSelvin Xavier req.gid[2] = cpu_to_be32(temp32[1]); 280*1ac5a404SSelvin Xavier req.gid[3] = cpu_to_be32(temp32[0]); 281*1ac5a404SSelvin Xavier if (vlan_id != 0xFFFF) 282*1ac5a404SSelvin Xavier req.vlan = cpu_to_le16((vlan_id & 283*1ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_ID_MASK) | 284*1ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | 285*1ac5a404SSelvin Xavier CMDQ_ADD_GID_VLAN_VLAN_EN); 286*1ac5a404SSelvin Xavier 287*1ac5a404SSelvin Xavier /* MAC in network format */ 288*1ac5a404SSelvin Xavier memcpy(temp16, smac, 6); 289*1ac5a404SSelvin Xavier req.src_mac[0] = cpu_to_be16(temp16[0]); 290*1ac5a404SSelvin Xavier req.src_mac[1] = cpu_to_be16(temp16[1]); 291*1ac5a404SSelvin Xavier req.src_mac[2] = cpu_to_be16(temp16[2]); 292*1ac5a404SSelvin Xavier 293*1ac5a404SSelvin Xavier resp = (struct creq_add_gid_resp *) 294*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 295*1ac5a404SSelvin Xavier NULL, 0); 296*1ac5a404SSelvin Xavier if (!resp) { 297*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 298*1ac5a404SSelvin Xavier "QPLIB: SP: ADD_GID send failed"); 299*1ac5a404SSelvin Xavier return -EINVAL; 300*1ac5a404SSelvin Xavier } 301*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, 302*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie))) { 303*1ac5a404SSelvin Xavier /* Cmd timed out */ 304*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 305*1ac5a404SSelvin Xavier "QPIB: SP: ADD_GID timed out"); 306*1ac5a404SSelvin Xavier return -ETIMEDOUT; 307*1ac5a404SSelvin Xavier } 308*1ac5a404SSelvin Xavier if (resp->status || 309*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 310*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: ADD_GID failed "); 311*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 312*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 313*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 314*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 315*1ac5a404SSelvin Xavier return -EINVAL; 316*1ac5a404SSelvin Xavier } 317*1ac5a404SSelvin Xavier sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp->xid); 318*1ac5a404SSelvin Xavier } 319*1ac5a404SSelvin Xavier /* Add GID to the sgid_tbl */ 320*1ac5a404SSelvin Xavier memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); 321*1ac5a404SSelvin Xavier sgid_tbl->active++; 322*1ac5a404SSelvin Xavier dev_dbg(&res->pdev->dev, 323*1ac5a404SSelvin Xavier "QPLIB: SGID added hw_id[0x%x] = 0x%x active = 0x%x", 324*1ac5a404SSelvin Xavier free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); 325*1ac5a404SSelvin Xavier 326*1ac5a404SSelvin Xavier *index = free_idx; 327*1ac5a404SSelvin Xavier /* unlock */ 328*1ac5a404SSelvin Xavier return rc; 329*1ac5a404SSelvin Xavier } 330*1ac5a404SSelvin Xavier 331*1ac5a404SSelvin Xavier /* pkeys */ 332*1ac5a404SSelvin Xavier int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, 333*1ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 index, 334*1ac5a404SSelvin Xavier u16 *pkey) 335*1ac5a404SSelvin Xavier { 336*1ac5a404SSelvin Xavier if (index == 0xFFFF) { 337*1ac5a404SSelvin Xavier *pkey = 0xFFFF; 338*1ac5a404SSelvin Xavier return 0; 339*1ac5a404SSelvin Xavier } 340*1ac5a404SSelvin Xavier if (index > pkey_tbl->max) { 341*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 342*1ac5a404SSelvin Xavier "QPLIB: Index %d exceeded PKEY table max (%d)", 343*1ac5a404SSelvin Xavier index, pkey_tbl->max); 344*1ac5a404SSelvin Xavier return -EINVAL; 345*1ac5a404SSelvin Xavier } 346*1ac5a404SSelvin Xavier memcpy(pkey, &pkey_tbl->tbl[index], sizeof(*pkey)); 347*1ac5a404SSelvin Xavier return 0; 348*1ac5a404SSelvin Xavier } 349*1ac5a404SSelvin Xavier 350*1ac5a404SSelvin Xavier int bnxt_qplib_del_pkey(struct bnxt_qplib_res *res, 351*1ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 352*1ac5a404SSelvin Xavier bool update) 353*1ac5a404SSelvin Xavier { 354*1ac5a404SSelvin Xavier int i, rc = 0; 355*1ac5a404SSelvin Xavier 356*1ac5a404SSelvin Xavier if (!pkey_tbl) { 357*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated"); 358*1ac5a404SSelvin Xavier return -EINVAL; 359*1ac5a404SSelvin Xavier } 360*1ac5a404SSelvin Xavier 361*1ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 362*1ac5a404SSelvin Xavier if (!pkey_tbl->active) { 363*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 364*1ac5a404SSelvin Xavier "QPLIB: PKEY table has no active entries"); 365*1ac5a404SSelvin Xavier return -ENOMEM; 366*1ac5a404SSelvin Xavier } 367*1ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 368*1ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 369*1ac5a404SSelvin Xavier break; 370*1ac5a404SSelvin Xavier } 371*1ac5a404SSelvin Xavier if (i == pkey_tbl->max) { 372*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 373*1ac5a404SSelvin Xavier "QPLIB: PKEY 0x%04x not found in the pkey table", 374*1ac5a404SSelvin Xavier *pkey); 375*1ac5a404SSelvin Xavier return -ENOMEM; 376*1ac5a404SSelvin Xavier } 377*1ac5a404SSelvin Xavier memset(&pkey_tbl->tbl[i], 0, sizeof(*pkey)); 378*1ac5a404SSelvin Xavier pkey_tbl->active--; 379*1ac5a404SSelvin Xavier 380*1ac5a404SSelvin Xavier /* unlock */ 381*1ac5a404SSelvin Xavier return rc; 382*1ac5a404SSelvin Xavier } 383*1ac5a404SSelvin Xavier 384*1ac5a404SSelvin Xavier int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, 385*1ac5a404SSelvin Xavier struct bnxt_qplib_pkey_tbl *pkey_tbl, u16 *pkey, 386*1ac5a404SSelvin Xavier bool update) 387*1ac5a404SSelvin Xavier { 388*1ac5a404SSelvin Xavier int i, free_idx, rc = 0; 389*1ac5a404SSelvin Xavier 390*1ac5a404SSelvin Xavier if (!pkey_tbl) { 391*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table not allocated"); 392*1ac5a404SSelvin Xavier return -EINVAL; 393*1ac5a404SSelvin Xavier } 394*1ac5a404SSelvin Xavier 395*1ac5a404SSelvin Xavier /* Do we need a pkey_lock here? */ 396*1ac5a404SSelvin Xavier if (pkey_tbl->active == pkey_tbl->max) { 397*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: PKEY table is full"); 398*1ac5a404SSelvin Xavier return -ENOMEM; 399*1ac5a404SSelvin Xavier } 400*1ac5a404SSelvin Xavier free_idx = pkey_tbl->max; 401*1ac5a404SSelvin Xavier for (i = 0; i < pkey_tbl->max; i++) { 402*1ac5a404SSelvin Xavier if (!memcmp(&pkey_tbl->tbl[i], pkey, sizeof(*pkey))) 403*1ac5a404SSelvin Xavier return -EALREADY; 404*1ac5a404SSelvin Xavier else if (!pkey_tbl->tbl[i] && free_idx == pkey_tbl->max) 405*1ac5a404SSelvin Xavier free_idx = i; 406*1ac5a404SSelvin Xavier } 407*1ac5a404SSelvin Xavier if (free_idx == pkey_tbl->max) { 408*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 409*1ac5a404SSelvin Xavier "QPLIB: PKEY table is FULL but count is not MAX??"); 410*1ac5a404SSelvin Xavier return -ENOMEM; 411*1ac5a404SSelvin Xavier } 412*1ac5a404SSelvin Xavier /* Add PKEY to the pkey_tbl */ 413*1ac5a404SSelvin Xavier memcpy(&pkey_tbl->tbl[free_idx], pkey, sizeof(*pkey)); 414*1ac5a404SSelvin Xavier pkey_tbl->active++; 415*1ac5a404SSelvin Xavier 416*1ac5a404SSelvin Xavier /* unlock */ 417*1ac5a404SSelvin Xavier return rc; 418*1ac5a404SSelvin Xavier } 419*1ac5a404SSelvin Xavier 420*1ac5a404SSelvin Xavier /* AH */ 421*1ac5a404SSelvin Xavier int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 422*1ac5a404SSelvin Xavier { 423*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 424*1ac5a404SSelvin Xavier struct cmdq_create_ah req; 425*1ac5a404SSelvin Xavier struct creq_create_ah_resp *resp; 426*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 427*1ac5a404SSelvin Xavier u32 temp32[4]; 428*1ac5a404SSelvin Xavier u16 temp16[3]; 429*1ac5a404SSelvin Xavier 430*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); 431*1ac5a404SSelvin Xavier 432*1ac5a404SSelvin Xavier memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); 433*1ac5a404SSelvin Xavier req.dgid[0] = cpu_to_le32(temp32[0]); 434*1ac5a404SSelvin Xavier req.dgid[1] = cpu_to_le32(temp32[1]); 435*1ac5a404SSelvin Xavier req.dgid[2] = cpu_to_le32(temp32[2]); 436*1ac5a404SSelvin Xavier req.dgid[3] = cpu_to_le32(temp32[3]); 437*1ac5a404SSelvin Xavier 438*1ac5a404SSelvin Xavier req.type = ah->nw_type; 439*1ac5a404SSelvin Xavier req.hop_limit = ah->hop_limit; 440*1ac5a404SSelvin Xavier req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); 441*1ac5a404SSelvin Xavier req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & 442*1ac5a404SSelvin Xavier CMDQ_CREATE_AH_FLOW_LABEL_MASK) | 443*1ac5a404SSelvin Xavier CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); 444*1ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(ah->pd->id); 445*1ac5a404SSelvin Xavier req.traffic_class = ah->traffic_class; 446*1ac5a404SSelvin Xavier 447*1ac5a404SSelvin Xavier /* MAC in network format */ 448*1ac5a404SSelvin Xavier memcpy(temp16, ah->dmac, 6); 449*1ac5a404SSelvin Xavier req.dest_mac[0] = cpu_to_le16(temp16[0]); 450*1ac5a404SSelvin Xavier req.dest_mac[1] = cpu_to_le16(temp16[1]); 451*1ac5a404SSelvin Xavier req.dest_mac[2] = cpu_to_le16(temp16[2]); 452*1ac5a404SSelvin Xavier 453*1ac5a404SSelvin Xavier resp = (struct creq_create_ah_resp *) 454*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 455*1ac5a404SSelvin Xavier NULL, 1); 456*1ac5a404SSelvin Xavier if (!resp) { 457*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed"); 458*1ac5a404SSelvin Xavier return -EINVAL; 459*1ac5a404SSelvin Xavier } 460*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) { 461*1ac5a404SSelvin Xavier /* Cmd timed out */ 462*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out"); 463*1ac5a404SSelvin Xavier return -ETIMEDOUT; 464*1ac5a404SSelvin Xavier } 465*1ac5a404SSelvin Xavier if (resp->status || 466*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 467*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed "); 468*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 469*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 470*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 471*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 472*1ac5a404SSelvin Xavier return -EINVAL; 473*1ac5a404SSelvin Xavier } 474*1ac5a404SSelvin Xavier ah->id = le32_to_cpu(resp->xid); 475*1ac5a404SSelvin Xavier return 0; 476*1ac5a404SSelvin Xavier } 477*1ac5a404SSelvin Xavier 478*1ac5a404SSelvin Xavier int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) 479*1ac5a404SSelvin Xavier { 480*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 481*1ac5a404SSelvin Xavier struct cmdq_destroy_ah req; 482*1ac5a404SSelvin Xavier struct creq_destroy_ah_resp *resp; 483*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 484*1ac5a404SSelvin Xavier 485*1ac5a404SSelvin Xavier /* Clean up the AH table in the device */ 486*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); 487*1ac5a404SSelvin Xavier 488*1ac5a404SSelvin Xavier req.ah_cid = cpu_to_le32(ah->id); 489*1ac5a404SSelvin Xavier 490*1ac5a404SSelvin Xavier resp = (struct creq_destroy_ah_resp *) 491*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 492*1ac5a404SSelvin Xavier NULL, 1); 493*1ac5a404SSelvin Xavier if (!resp) { 494*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed"); 495*1ac5a404SSelvin Xavier return -EINVAL; 496*1ac5a404SSelvin Xavier } 497*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) { 498*1ac5a404SSelvin Xavier /* Cmd timed out */ 499*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out"); 500*1ac5a404SSelvin Xavier return -ETIMEDOUT; 501*1ac5a404SSelvin Xavier } 502*1ac5a404SSelvin Xavier if (resp->status || 503*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 504*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed "); 505*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 506*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 507*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 508*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 509*1ac5a404SSelvin Xavier return -EINVAL; 510*1ac5a404SSelvin Xavier } 511*1ac5a404SSelvin Xavier return 0; 512*1ac5a404SSelvin Xavier } 513*1ac5a404SSelvin Xavier 514*1ac5a404SSelvin Xavier /* MRW */ 515*1ac5a404SSelvin Xavier int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 516*1ac5a404SSelvin Xavier { 517*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 518*1ac5a404SSelvin Xavier struct cmdq_deallocate_key req; 519*1ac5a404SSelvin Xavier struct creq_deallocate_key_resp *resp; 520*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 521*1ac5a404SSelvin Xavier 522*1ac5a404SSelvin Xavier if (mrw->lkey == 0xFFFFFFFF) { 523*1ac5a404SSelvin Xavier dev_info(&res->pdev->dev, 524*1ac5a404SSelvin Xavier "QPLIB: SP: Free a reserved lkey MRW"); 525*1ac5a404SSelvin Xavier return 0; 526*1ac5a404SSelvin Xavier } 527*1ac5a404SSelvin Xavier 528*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEALLOCATE_KEY, cmd_flags); 529*1ac5a404SSelvin Xavier 530*1ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 531*1ac5a404SSelvin Xavier 532*1ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 533*1ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 534*1ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 535*1ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->rkey); 536*1ac5a404SSelvin Xavier else 537*1ac5a404SSelvin Xavier req.key = cpu_to_le32(mrw->lkey); 538*1ac5a404SSelvin Xavier 539*1ac5a404SSelvin Xavier resp = (struct creq_deallocate_key_resp *) 540*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 541*1ac5a404SSelvin Xavier NULL, 0); 542*1ac5a404SSelvin Xavier if (!resp) { 543*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR send failed"); 544*1ac5a404SSelvin Xavier return -EINVAL; 545*1ac5a404SSelvin Xavier } 546*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { 547*1ac5a404SSelvin Xavier /* Cmd timed out */ 548*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR timed out"); 549*1ac5a404SSelvin Xavier return -ETIMEDOUT; 550*1ac5a404SSelvin Xavier } 551*1ac5a404SSelvin Xavier if (resp->status || 552*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 553*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR failed "); 554*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 555*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 556*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 557*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 558*1ac5a404SSelvin Xavier return -EINVAL; 559*1ac5a404SSelvin Xavier } 560*1ac5a404SSelvin Xavier /* Free the qplib's MRW memory */ 561*1ac5a404SSelvin Xavier if (mrw->hwq.max_elements) 562*1ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 563*1ac5a404SSelvin Xavier 564*1ac5a404SSelvin Xavier return 0; 565*1ac5a404SSelvin Xavier } 566*1ac5a404SSelvin Xavier 567*1ac5a404SSelvin Xavier int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) 568*1ac5a404SSelvin Xavier { 569*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 570*1ac5a404SSelvin Xavier struct cmdq_allocate_mrw req; 571*1ac5a404SSelvin Xavier struct creq_allocate_mrw_resp *resp; 572*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 573*1ac5a404SSelvin Xavier unsigned long tmp; 574*1ac5a404SSelvin Xavier 575*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); 576*1ac5a404SSelvin Xavier 577*1ac5a404SSelvin Xavier req.pd_id = cpu_to_le32(mrw->pd->id); 578*1ac5a404SSelvin Xavier req.mrw_flags = mrw->type; 579*1ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && 580*1ac5a404SSelvin Xavier mrw->flags & BNXT_QPLIB_FR_PMR) || 581*1ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || 582*1ac5a404SSelvin Xavier mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) 583*1ac5a404SSelvin Xavier req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; 584*1ac5a404SSelvin Xavier tmp = (unsigned long)mrw; 585*1ac5a404SSelvin Xavier req.mrw_handle = cpu_to_le64(tmp); 586*1ac5a404SSelvin Xavier 587*1ac5a404SSelvin Xavier resp = (struct creq_allocate_mrw_resp *) 588*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 589*1ac5a404SSelvin Xavier NULL, 0); 590*1ac5a404SSelvin Xavier if (!resp) { 591*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW send failed"); 592*1ac5a404SSelvin Xavier return -EINVAL; 593*1ac5a404SSelvin Xavier } 594*1ac5a404SSelvin Xavier if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { 595*1ac5a404SSelvin Xavier /* Cmd timed out */ 596*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW timed out"); 597*1ac5a404SSelvin Xavier return -ETIMEDOUT; 598*1ac5a404SSelvin Xavier } 599*1ac5a404SSelvin Xavier if (resp->status || 600*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 601*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW failed "); 602*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 603*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 604*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 605*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 606*1ac5a404SSelvin Xavier return -EINVAL; 607*1ac5a404SSelvin Xavier } 608*1ac5a404SSelvin Xavier if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || 609*1ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || 610*1ac5a404SSelvin Xavier (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) 611*1ac5a404SSelvin Xavier mrw->rkey = le32_to_cpu(resp->xid); 612*1ac5a404SSelvin Xavier else 613*1ac5a404SSelvin Xavier mrw->lkey = le32_to_cpu(resp->xid); 614*1ac5a404SSelvin Xavier return 0; 615*1ac5a404SSelvin Xavier } 616*1ac5a404SSelvin Xavier 617*1ac5a404SSelvin Xavier int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, 618*1ac5a404SSelvin Xavier bool block) 619*1ac5a404SSelvin Xavier { 620*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 621*1ac5a404SSelvin Xavier struct cmdq_deregister_mr req; 622*1ac5a404SSelvin Xavier struct creq_deregister_mr_resp *resp; 623*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 624*1ac5a404SSelvin Xavier int rc; 625*1ac5a404SSelvin Xavier 626*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); 627*1ac5a404SSelvin Xavier 628*1ac5a404SSelvin Xavier req.lkey = cpu_to_le32(mrw->lkey); 629*1ac5a404SSelvin Xavier resp = (struct creq_deregister_mr_resp *) 630*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 631*1ac5a404SSelvin Xavier NULL, block); 632*1ac5a404SSelvin Xavier if (!resp) { 633*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR send failed"); 634*1ac5a404SSelvin Xavier return -EINVAL; 635*1ac5a404SSelvin Xavier } 636*1ac5a404SSelvin Xavier if (block) 637*1ac5a404SSelvin Xavier rc = bnxt_qplib_rcfw_block_for_resp(rcfw, 638*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie)); 639*1ac5a404SSelvin Xavier else 640*1ac5a404SSelvin Xavier rc = bnxt_qplib_rcfw_wait_for_resp(rcfw, 641*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie)); 642*1ac5a404SSelvin Xavier if (!rc) { 643*1ac5a404SSelvin Xavier /* Cmd timed out */ 644*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: DEREG_MR timed out"); 645*1ac5a404SSelvin Xavier return -ETIMEDOUT; 646*1ac5a404SSelvin Xavier } 647*1ac5a404SSelvin Xavier if (resp->status || 648*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 649*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR failed "); 650*1ac5a404SSelvin Xavier dev_err(&rcfw->pdev->dev, 651*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 652*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 653*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 654*1ac5a404SSelvin Xavier return -EINVAL; 655*1ac5a404SSelvin Xavier } 656*1ac5a404SSelvin Xavier 657*1ac5a404SSelvin Xavier /* Free the qplib's MR memory */ 658*1ac5a404SSelvin Xavier if (mrw->hwq.max_elements) { 659*1ac5a404SSelvin Xavier mrw->va = 0; 660*1ac5a404SSelvin Xavier mrw->total_size = 0; 661*1ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); 662*1ac5a404SSelvin Xavier } 663*1ac5a404SSelvin Xavier 664*1ac5a404SSelvin Xavier return 0; 665*1ac5a404SSelvin Xavier } 666*1ac5a404SSelvin Xavier 667*1ac5a404SSelvin Xavier int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, 668*1ac5a404SSelvin Xavier u64 *pbl_tbl, int num_pbls, bool block) 669*1ac5a404SSelvin Xavier { 670*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 671*1ac5a404SSelvin Xavier struct cmdq_register_mr req; 672*1ac5a404SSelvin Xavier struct creq_register_mr_resp *resp; 673*1ac5a404SSelvin Xavier u16 cmd_flags = 0, level; 674*1ac5a404SSelvin Xavier int pg_ptrs, pages, i, rc; 675*1ac5a404SSelvin Xavier dma_addr_t **pbl_ptr; 676*1ac5a404SSelvin Xavier u32 pg_size; 677*1ac5a404SSelvin Xavier 678*1ac5a404SSelvin Xavier if (num_pbls) { 679*1ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(num_pbls); 680*1ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 681*1ac5a404SSelvin Xavier if (!pages) 682*1ac5a404SSelvin Xavier pages++; 683*1ac5a404SSelvin Xavier 684*1ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) { 685*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: Reg MR pages "); 686*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 687*1ac5a404SSelvin Xavier "requested (0x%x) exceeded max (0x%x)", 688*1ac5a404SSelvin Xavier pages, MAX_PBL_LVL_1_PGS); 689*1ac5a404SSelvin Xavier return -ENOMEM; 690*1ac5a404SSelvin Xavier } 691*1ac5a404SSelvin Xavier /* Free the hwq if it already exist, must be a rereg */ 692*1ac5a404SSelvin Xavier if (mr->hwq.max_elements) 693*1ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 694*1ac5a404SSelvin Xavier 695*1ac5a404SSelvin Xavier mr->hwq.max_elements = pages; 696*1ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0, 697*1ac5a404SSelvin Xavier &mr->hwq.max_elements, 698*1ac5a404SSelvin Xavier PAGE_SIZE, 0, PAGE_SIZE, 699*1ac5a404SSelvin Xavier HWQ_TYPE_CTX); 700*1ac5a404SSelvin Xavier if (rc) { 701*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 702*1ac5a404SSelvin Xavier "SP: Reg MR memory allocation failed"); 703*1ac5a404SSelvin Xavier return -ENOMEM; 704*1ac5a404SSelvin Xavier } 705*1ac5a404SSelvin Xavier /* Write to the hwq */ 706*1ac5a404SSelvin Xavier pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr; 707*1ac5a404SSelvin Xavier for (i = 0; i < num_pbls; i++) 708*1ac5a404SSelvin Xavier pbl_ptr[PTR_PG(i)][PTR_IDX(i)] = 709*1ac5a404SSelvin Xavier (pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID; 710*1ac5a404SSelvin Xavier } 711*1ac5a404SSelvin Xavier 712*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); 713*1ac5a404SSelvin Xavier 714*1ac5a404SSelvin Xavier /* Configure the request */ 715*1ac5a404SSelvin Xavier if (mr->hwq.level == PBL_LVL_MAX) { 716*1ac5a404SSelvin Xavier level = 0; 717*1ac5a404SSelvin Xavier req.pbl = 0; 718*1ac5a404SSelvin Xavier pg_size = PAGE_SIZE; 719*1ac5a404SSelvin Xavier } else { 720*1ac5a404SSelvin Xavier level = mr->hwq.level + 1; 721*1ac5a404SSelvin Xavier req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); 722*1ac5a404SSelvin Xavier pg_size = mr->hwq.pbl[PBL_LVL_0].pg_size; 723*1ac5a404SSelvin Xavier } 724*1ac5a404SSelvin Xavier req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | 725*1ac5a404SSelvin Xavier ((ilog2(pg_size) << 726*1ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & 727*1ac5a404SSelvin Xavier CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); 728*1ac5a404SSelvin Xavier req.access = (mr->flags & 0xFFFF); 729*1ac5a404SSelvin Xavier req.va = cpu_to_le64(mr->va); 730*1ac5a404SSelvin Xavier req.key = cpu_to_le32(mr->lkey); 731*1ac5a404SSelvin Xavier req.mr_size = cpu_to_le64(mr->total_size); 732*1ac5a404SSelvin Xavier 733*1ac5a404SSelvin Xavier resp = (struct creq_register_mr_resp *) 734*1ac5a404SSelvin Xavier bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, 735*1ac5a404SSelvin Xavier NULL, block); 736*1ac5a404SSelvin Xavier if (!resp) { 737*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "SP: REG_MR send failed"); 738*1ac5a404SSelvin Xavier rc = -EINVAL; 739*1ac5a404SSelvin Xavier goto fail; 740*1ac5a404SSelvin Xavier } 741*1ac5a404SSelvin Xavier if (block) 742*1ac5a404SSelvin Xavier rc = bnxt_qplib_rcfw_block_for_resp(rcfw, 743*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie)); 744*1ac5a404SSelvin Xavier else 745*1ac5a404SSelvin Xavier rc = bnxt_qplib_rcfw_wait_for_resp(rcfw, 746*1ac5a404SSelvin Xavier le16_to_cpu(req.cookie)); 747*1ac5a404SSelvin Xavier if (!rc) { 748*1ac5a404SSelvin Xavier /* Cmd timed out */ 749*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "SP: REG_MR timed out"); 750*1ac5a404SSelvin Xavier rc = -ETIMEDOUT; 751*1ac5a404SSelvin Xavier goto fail; 752*1ac5a404SSelvin Xavier } 753*1ac5a404SSelvin Xavier if (resp->status || 754*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 755*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: REG_MR failed "); 756*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 757*1ac5a404SSelvin Xavier "QPLIB: SP: with status 0x%x cmdq 0x%x resp 0x%x", 758*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 759*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 760*1ac5a404SSelvin Xavier rc = -EINVAL; 761*1ac5a404SSelvin Xavier goto fail; 762*1ac5a404SSelvin Xavier } 763*1ac5a404SSelvin Xavier return 0; 764*1ac5a404SSelvin Xavier 765*1ac5a404SSelvin Xavier fail: 766*1ac5a404SSelvin Xavier if (mr->hwq.max_elements) 767*1ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &mr->hwq); 768*1ac5a404SSelvin Xavier return rc; 769*1ac5a404SSelvin Xavier } 770*1ac5a404SSelvin Xavier 771*1ac5a404SSelvin Xavier int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, 772*1ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl, 773*1ac5a404SSelvin Xavier int max_pg_ptrs) 774*1ac5a404SSelvin Xavier { 775*1ac5a404SSelvin Xavier int pg_ptrs, pages, rc; 776*1ac5a404SSelvin Xavier 777*1ac5a404SSelvin Xavier /* Re-calculate the max to fit the HWQ allocation model */ 778*1ac5a404SSelvin Xavier pg_ptrs = roundup_pow_of_two(max_pg_ptrs); 779*1ac5a404SSelvin Xavier pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; 780*1ac5a404SSelvin Xavier if (!pages) 781*1ac5a404SSelvin Xavier pages++; 782*1ac5a404SSelvin Xavier 783*1ac5a404SSelvin Xavier if (pages > MAX_PBL_LVL_1_PGS) 784*1ac5a404SSelvin Xavier return -ENOMEM; 785*1ac5a404SSelvin Xavier 786*1ac5a404SSelvin Xavier frpl->hwq.max_elements = pages; 787*1ac5a404SSelvin Xavier rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0, 788*1ac5a404SSelvin Xavier &frpl->hwq.max_elements, PAGE_SIZE, 0, 789*1ac5a404SSelvin Xavier PAGE_SIZE, HWQ_TYPE_CTX); 790*1ac5a404SSelvin Xavier if (!rc) 791*1ac5a404SSelvin Xavier frpl->max_pg_ptrs = pg_ptrs; 792*1ac5a404SSelvin Xavier 793*1ac5a404SSelvin Xavier return rc; 794*1ac5a404SSelvin Xavier } 795*1ac5a404SSelvin Xavier 796*1ac5a404SSelvin Xavier int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, 797*1ac5a404SSelvin Xavier struct bnxt_qplib_frpl *frpl) 798*1ac5a404SSelvin Xavier { 799*1ac5a404SSelvin Xavier bnxt_qplib_free_hwq(res->pdev, &frpl->hwq); 800*1ac5a404SSelvin Xavier return 0; 801*1ac5a404SSelvin Xavier } 802*1ac5a404SSelvin Xavier 803*1ac5a404SSelvin Xavier int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) 804*1ac5a404SSelvin Xavier { 805*1ac5a404SSelvin Xavier struct bnxt_qplib_rcfw *rcfw = res->rcfw; 806*1ac5a404SSelvin Xavier struct cmdq_map_tc_to_cos req; 807*1ac5a404SSelvin Xavier struct creq_map_tc_to_cos_resp *resp; 808*1ac5a404SSelvin Xavier u16 cmd_flags = 0; 809*1ac5a404SSelvin Xavier int tleft; 810*1ac5a404SSelvin Xavier 811*1ac5a404SSelvin Xavier RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); 812*1ac5a404SSelvin Xavier req.cos0 = cpu_to_le16(cids[0]); 813*1ac5a404SSelvin Xavier req.cos1 = cpu_to_le16(cids[1]); 814*1ac5a404SSelvin Xavier 815*1ac5a404SSelvin Xavier resp = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 0); 816*1ac5a404SSelvin Xavier if (!resp) { 817*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS send failed"); 818*1ac5a404SSelvin Xavier return -EINVAL; 819*1ac5a404SSelvin Xavier } 820*1ac5a404SSelvin Xavier 821*1ac5a404SSelvin Xavier tleft = bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie)); 822*1ac5a404SSelvin Xavier if (!tleft) { 823*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS timed out"); 824*1ac5a404SSelvin Xavier return -ETIMEDOUT; 825*1ac5a404SSelvin Xavier } 826*1ac5a404SSelvin Xavier 827*1ac5a404SSelvin Xavier if (resp->status || 828*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { 829*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS failed "); 830*1ac5a404SSelvin Xavier dev_err(&res->pdev->dev, 831*1ac5a404SSelvin Xavier "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", 832*1ac5a404SSelvin Xavier resp->status, le16_to_cpu(req.cookie), 833*1ac5a404SSelvin Xavier le16_to_cpu(resp->cookie)); 834*1ac5a404SSelvin Xavier return -EINVAL; 835*1ac5a404SSelvin Xavier } 836*1ac5a404SSelvin Xavier 837*1ac5a404SSelvin Xavier return 0; 838*1ac5a404SSelvin Xavier } 839