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