linux/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
<<
>>
Prefs
   1/*******************************************************************************
   2*
   3* Copyright (c) 2015-2016 Intel Corporation.  All rights reserved.
   4*
   5* This software is available to you under a choice of one of two
   6* licenses.  You may choose to be licensed under the terms of the GNU
   7* General Public License (GPL) Version 2, available from the file
   8* COPYING in the main directory of this source tree, or the
   9* OpenFabrics.org BSD license below:
  10*
  11*   Redistribution and use in source and binary forms, with or
  12*   without modification, are permitted provided that the following
  13*   conditions are met:
  14*
  15*    - Redistributions of source code must retain the above
  16*       copyright notice, this list of conditions and the following
  17*       disclaimer.
  18*
  19*    - Redistributions in binary form must reproduce the above
  20*       copyright notice, this list of conditions and the following
  21*       disclaimer in the documentation and/or other materials
  22*       provided with the distribution.
  23*
  24* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31* SOFTWARE.
  32*
  33*******************************************************************************/
  34
  35#include "i40iw_osdep.h"
  36#include "i40iw_register.h"
  37#include "i40iw_status.h"
  38#include "i40iw_hmc.h"
  39
  40#include "i40iw_d.h"
  41#include "i40iw_type.h"
  42#include "i40iw_p.h"
  43#include "i40iw_vf.h"
  44#include "i40iw_virtchnl.h"
  45
  46/**
  47 * i40iw_insert_wqe_hdr - write wqe header
  48 * @wqe: cqp wqe for header
  49 * @header: header for the cqp wqe
  50 */
  51void i40iw_insert_wqe_hdr(u64 *wqe, u64 header)
  52{
  53        wmb();            /* make sure WQE is populated before polarity is set */
  54        set_64bit_val(wqe, 24, header);
  55}
  56
  57void i40iw_check_cqp_progress(struct i40iw_cqp_timeout *cqp_timeout, struct i40iw_sc_dev *dev)
  58{
  59        if (cqp_timeout->compl_cqp_cmds != dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS]) {
  60                cqp_timeout->compl_cqp_cmds = dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS];
  61                cqp_timeout->count = 0;
  62        } else {
  63                if (dev->cqp_cmd_stats[OP_REQUESTED_COMMANDS] != cqp_timeout->compl_cqp_cmds)
  64                        cqp_timeout->count++;
  65        }
  66}
  67
  68/**
  69 * i40iw_get_cqp_reg_info - get head and tail for cqp using registers
  70 * @cqp: struct for cqp hw
  71 * @val: cqp tail register value
  72 * @tail:wqtail register value
  73 * @error: cqp processing err
  74 */
  75static inline void i40iw_get_cqp_reg_info(struct i40iw_sc_cqp *cqp,
  76                                          u32 *val,
  77                                          u32 *tail,
  78                                          u32 *error)
  79{
  80        if (cqp->dev->is_pf) {
  81                *val = i40iw_rd32(cqp->dev->hw, I40E_PFPE_CQPTAIL);
  82                *tail = RS_32(*val, I40E_PFPE_CQPTAIL_WQTAIL);
  83                *error = RS_32(*val, I40E_PFPE_CQPTAIL_CQP_OP_ERR);
  84        } else {
  85                *val = i40iw_rd32(cqp->dev->hw, I40E_VFPE_CQPTAIL1);
  86                *tail = RS_32(*val, I40E_VFPE_CQPTAIL_WQTAIL);
  87                *error = RS_32(*val, I40E_VFPE_CQPTAIL_CQP_OP_ERR);
  88        }
  89}
  90
  91/**
  92 * i40iw_cqp_poll_registers - poll cqp registers
  93 * @cqp: struct for cqp hw
  94 * @tail:wqtail register value
  95 * @count: how many times to try for completion
  96 */
  97static enum i40iw_status_code i40iw_cqp_poll_registers(
  98                                                struct i40iw_sc_cqp *cqp,
  99                                                u32 tail,
 100                                                u32 count)
 101{
 102        u32 i = 0;
 103        u32 newtail, error, val;
 104
 105        while (i < count) {
 106                i++;
 107                i40iw_get_cqp_reg_info(cqp, &val, &newtail, &error);
 108                if (error) {
 109                        error = (cqp->dev->is_pf) ?
 110                                 i40iw_rd32(cqp->dev->hw, I40E_PFPE_CQPERRCODES) :
 111                                 i40iw_rd32(cqp->dev->hw, I40E_VFPE_CQPERRCODES1);
 112                        return I40IW_ERR_CQP_COMPL_ERROR;
 113                }
 114                if (newtail != tail) {
 115                        /* SUCCESS */
 116                        I40IW_RING_MOVE_TAIL(cqp->sq_ring);
 117                        cqp->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS]++;
 118                        return 0;
 119                }
 120                udelay(I40IW_SLEEP_COUNT);
 121        }
 122        return I40IW_ERR_TIMEOUT;
 123}
 124
 125/**
 126 * i40iw_sc_parse_fpm_commit_buf - parse fpm commit buffer
 127 * @buf: ptr to fpm commit buffer
 128 * @info: ptr to i40iw_hmc_obj_info struct
 129 * @sd: number of SDs for HMC objects
 130 *
 131 * parses fpm commit info and copy base value
 132 * of hmc objects in hmc_info
 133 */
 134static enum i40iw_status_code i40iw_sc_parse_fpm_commit_buf(
 135                                u64 *buf,
 136                                struct i40iw_hmc_obj_info *info,
 137                                u32 *sd)
 138{
 139        u64 temp;
 140        u64 size;
 141        u64 base = 0;
 142        u32 i, j;
 143        u32 k = 0;
 144
 145        /* copy base values in obj_info */
 146        for (i = I40IW_HMC_IW_QP, j = 0; i <= I40IW_HMC_IW_PBLE; i++, j += 8) {
 147                if ((i == I40IW_HMC_IW_SRQ) ||
 148                        (i == I40IW_HMC_IW_FSIMC) ||
 149                        (i == I40IW_HMC_IW_FSIAV)) {
 150                        info[i].base = 0;
 151                        info[i].cnt = 0;
 152                        continue;
 153                }
 154                get_64bit_val(buf, j, &temp);
 155                info[i].base = RS_64_1(temp, 32) * 512;
 156                if (info[i].base > base) {
 157                        base = info[i].base;
 158                        k = i;
 159                }
 160                if (i == I40IW_HMC_IW_APBVT_ENTRY) {
 161                        info[i].cnt = 1;
 162                        continue;
 163                }
 164                if (i == I40IW_HMC_IW_QP)
 165                        info[i].cnt = (u32)RS_64(temp, I40IW_QUERY_FPM_MAX_QPS);
 166                else if (i == I40IW_HMC_IW_CQ)
 167                        info[i].cnt = (u32)RS_64(temp, I40IW_QUERY_FPM_MAX_CQS);
 168                else
 169                        info[i].cnt = (u32)(temp);
 170        }
 171        size = info[k].cnt * info[k].size + info[k].base;
 172        if (size & 0x1FFFFF)
 173                *sd = (u32)((size >> 21) + 1); /* add 1 for remainder */
 174        else
 175                *sd = (u32)(size >> 21);
 176
 177        return 0;
 178}
 179
 180/**
 181 * i40iw_sc_decode_fpm_query() - Decode a 64 bit value into max count and size
 182 * @buf: ptr to fpm query buffer
 183 * @buf_idx: index into buf
 184 * @info: ptr to i40iw_hmc_obj_info struct
 185 * @rsrc_idx: resource index into info
 186 *
 187 * Decode a 64 bit value from fpm query buffer into max count and size
 188 */
 189static u64 i40iw_sc_decode_fpm_query(u64 *buf,
 190                                            u32 buf_idx,
 191                                            struct i40iw_hmc_obj_info *obj_info,
 192                                            u32 rsrc_idx)
 193{
 194        u64 temp;
 195        u32 size;
 196
 197        get_64bit_val(buf, buf_idx, &temp);
 198        obj_info[rsrc_idx].max_cnt = (u32)temp;
 199        size = (u32)RS_64_1(temp, 32);
 200        obj_info[rsrc_idx].size = LS_64_1(1, size);
 201
 202        return temp;
 203}
 204
 205/**
 206 * i40iw_sc_parse_fpm_query_buf() - parses fpm query buffer
 207 * @buf: ptr to fpm query buffer
 208 * @info: ptr to i40iw_hmc_obj_info struct
 209 * @hmc_fpm_misc: ptr to fpm data
 210 *
 211 * parses fpm query buffer and copy max_cnt and
 212 * size value of hmc objects in hmc_info
 213 */
 214static enum i40iw_status_code i40iw_sc_parse_fpm_query_buf(
 215                                u64 *buf,
 216                                struct i40iw_hmc_info *hmc_info,
 217                                struct i40iw_hmc_fpm_misc *hmc_fpm_misc)
 218{
 219        struct i40iw_hmc_obj_info *obj_info;
 220        u64 temp;
 221        u32 size;
 222        u16 max_pe_sds;
 223
 224        obj_info = hmc_info->hmc_obj;
 225
 226        get_64bit_val(buf, 0, &temp);
 227        hmc_info->first_sd_index = (u16)RS_64(temp, I40IW_QUERY_FPM_FIRST_PE_SD_INDEX);
 228        max_pe_sds = (u16)RS_64(temp, I40IW_QUERY_FPM_MAX_PE_SDS);
 229
 230        /* Reduce SD count for VFs by 1 to account for PBLE backing page rounding */
 231        if (hmc_info->hmc_fn_id >= I40IW_FIRST_VF_FPM_ID)
 232                max_pe_sds--;
 233        hmc_fpm_misc->max_sds = max_pe_sds;
 234        hmc_info->sd_table.sd_cnt = max_pe_sds + hmc_info->first_sd_index;
 235
 236        get_64bit_val(buf, 8, &temp);
 237        obj_info[I40IW_HMC_IW_QP].max_cnt = (u32)RS_64(temp, I40IW_QUERY_FPM_MAX_QPS);
 238        size = (u32)RS_64_1(temp, 32);
 239        obj_info[I40IW_HMC_IW_QP].size = LS_64_1(1, size);
 240
 241        get_64bit_val(buf, 16, &temp);
 242        obj_info[I40IW_HMC_IW_CQ].max_cnt = (u32)RS_64(temp, I40IW_QUERY_FPM_MAX_CQS);
 243        size = (u32)RS_64_1(temp, 32);
 244        obj_info[I40IW_HMC_IW_CQ].size = LS_64_1(1, size);
 245
 246        i40iw_sc_decode_fpm_query(buf, 32, obj_info, I40IW_HMC_IW_HTE);
 247        i40iw_sc_decode_fpm_query(buf, 40, obj_info, I40IW_HMC_IW_ARP);
 248
 249        obj_info[I40IW_HMC_IW_APBVT_ENTRY].size = 8192;
 250        obj_info[I40IW_HMC_IW_APBVT_ENTRY].max_cnt = 1;
 251
 252        i40iw_sc_decode_fpm_query(buf, 48, obj_info, I40IW_HMC_IW_MR);
 253        i40iw_sc_decode_fpm_query(buf, 56, obj_info, I40IW_HMC_IW_XF);
 254
 255        get_64bit_val(buf, 64, &temp);
 256        obj_info[I40IW_HMC_IW_XFFL].max_cnt = (u32)temp;
 257        obj_info[I40IW_HMC_IW_XFFL].size = 4;
 258        hmc_fpm_misc->xf_block_size = RS_64(temp, I40IW_QUERY_FPM_XFBLOCKSIZE);
 259        if (!hmc_fpm_misc->xf_block_size)
 260                return I40IW_ERR_INVALID_SIZE;
 261
 262        i40iw_sc_decode_fpm_query(buf, 72, obj_info, I40IW_HMC_IW_Q1);
 263
 264        get_64bit_val(buf, 80, &temp);
 265        obj_info[I40IW_HMC_IW_Q1FL].max_cnt = (u32)temp;
 266        obj_info[I40IW_HMC_IW_Q1FL].size = 4;
 267        hmc_fpm_misc->q1_block_size = RS_64(temp, I40IW_QUERY_FPM_Q1BLOCKSIZE);
 268        if (!hmc_fpm_misc->q1_block_size)
 269                return I40IW_ERR_INVALID_SIZE;
 270
 271        i40iw_sc_decode_fpm_query(buf, 88, obj_info, I40IW_HMC_IW_TIMER);
 272
 273        get_64bit_val(buf, 112, &temp);
 274        obj_info[I40IW_HMC_IW_PBLE].max_cnt = (u32)temp;
 275        obj_info[I40IW_HMC_IW_PBLE].size = 8;
 276
 277        get_64bit_val(buf, 120, &temp);
 278        hmc_fpm_misc->max_ceqs = (u8)RS_64(temp, I40IW_QUERY_FPM_MAX_CEQS);
 279        hmc_fpm_misc->ht_multiplier = RS_64(temp, I40IW_QUERY_FPM_HTMULTIPLIER);
 280        hmc_fpm_misc->timer_bucket = RS_64(temp, I40IW_QUERY_FPM_TIMERBUCKET);
 281
 282        return 0;
 283}
 284
 285/**
 286 * i40iw_fill_qos_list - Change all unknown qs handles to available ones
 287 * @qs_list: list of qs_handles to be fixed with valid qs_handles
 288 */
 289static void i40iw_fill_qos_list(u16 *qs_list)
 290{
 291        u16 qshandle = qs_list[0];
 292        int i;
 293
 294        for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
 295                if (qs_list[i] == QS_HANDLE_UNKNOWN)
 296                        qs_list[i] = qshandle;
 297                else
 298                        qshandle = qs_list[i];
 299        }
 300}
 301
 302/**
 303 * i40iw_qp_from_entry - Given entry, get to the qp structure
 304 * @entry: Points to list of qp structure
 305 */
 306static struct i40iw_sc_qp *i40iw_qp_from_entry(struct list_head *entry)
 307{
 308        if (!entry)
 309                return NULL;
 310
 311        return (struct i40iw_sc_qp *)((char *)entry - offsetof(struct i40iw_sc_qp, list));
 312}
 313
 314/**
 315 * i40iw_get_qp - get the next qp from the list given current qp
 316 * @head: Listhead of qp's
 317 * @qp: current qp
 318 */
 319static struct i40iw_sc_qp *i40iw_get_qp(struct list_head *head, struct i40iw_sc_qp *qp)
 320{
 321        struct list_head *entry = NULL;
 322        struct list_head *lastentry;
 323
 324        if (list_empty(head))
 325                return NULL;
 326
 327        if (!qp) {
 328                entry = head->next;
 329        } else {
 330                lastentry = &qp->list;
 331                entry = (lastentry != head) ? lastentry->next : NULL;
 332        }
 333
 334        return i40iw_qp_from_entry(entry);
 335}
 336
 337/**
 338 * i40iw_change_l2params - given the new l2 parameters, change all qp
 339 * @vsi: pointer to the vsi structure
 340 * @l2params: New paramaters from l2
 341 */
 342void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2params)
 343{
 344        struct i40iw_sc_dev *dev = vsi->dev;
 345        struct i40iw_sc_qp *qp = NULL;
 346        bool qs_handle_change = false;
 347        unsigned long flags;
 348        u16 qs_handle;
 349        int i;
 350
 351        if (vsi->mtu != l2params->mtu) {
 352                vsi->mtu = l2params->mtu;
 353                i40iw_reinitialize_ieq(dev);
 354        }
 355
 356        i40iw_fill_qos_list(l2params->qs_handle_list);
 357        for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
 358                qs_handle = l2params->qs_handle_list[i];
 359                if (vsi->qos[i].qs_handle != qs_handle)
 360                        qs_handle_change = true;
 361                spin_lock_irqsave(&vsi->qos[i].lock, flags);
 362                qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
 363                while (qp) {
 364                        if (qs_handle_change) {
 365                                qp->qs_handle = qs_handle;
 366                                /* issue cqp suspend command */
 367                                i40iw_qp_suspend_resume(dev, qp, true);
 368                        }
 369                        qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
 370                }
 371                spin_unlock_irqrestore(&vsi->qos[i].lock, flags);
 372                vsi->qos[i].qs_handle = qs_handle;
 373        }
 374}
 375
 376/**
 377 * i40iw_qp_rem_qos - remove qp from qos lists during destroy qp
 378 * @qp: qp to be removed from qos
 379 */
 380void i40iw_qp_rem_qos(struct i40iw_sc_qp *qp)
 381{
 382        struct i40iw_sc_vsi *vsi = qp->vsi;
 383        unsigned long flags;
 384
 385        if (!qp->on_qoslist)
 386                return;
 387        spin_lock_irqsave(&vsi->qos[qp->user_pri].lock, flags);
 388        list_del(&qp->list);
 389        spin_unlock_irqrestore(&vsi->qos[qp->user_pri].lock, flags);
 390}
 391
 392/**
 393 * i40iw_qp_add_qos - called during setctx fot qp to be added to qos
 394 * @qp: qp to be added to qos
 395 */
 396void i40iw_qp_add_qos(struct i40iw_sc_qp *qp)
 397{
 398        struct i40iw_sc_vsi *vsi = qp->vsi;
 399        unsigned long flags;
 400
 401        if (qp->on_qoslist)
 402                return;
 403        spin_lock_irqsave(&vsi->qos[qp->user_pri].lock, flags);
 404        qp->qs_handle = vsi->qos[qp->user_pri].qs_handle;
 405        list_add(&qp->list, &vsi->qos[qp->user_pri].qplist);
 406        qp->on_qoslist = true;
 407        spin_unlock_irqrestore(&vsi->qos[qp->user_pri].lock, flags);
 408}
 409
 410/**
 411 * i40iw_sc_pd_init - initialize sc pd struct
 412 * @dev: sc device struct
 413 * @pd: sc pd ptr
 414 * @pd_id: pd_id for allocated pd
 415 * @abi_ver: ABI version from user context, -1 if not valid
 416 */
 417static void i40iw_sc_pd_init(struct i40iw_sc_dev *dev,
 418                             struct i40iw_sc_pd *pd,
 419                             u16 pd_id,
 420                             int abi_ver)
 421{
 422        pd->size = sizeof(*pd);
 423        pd->pd_id = pd_id;
 424        pd->abi_ver = abi_ver;
 425        pd->dev = dev;
 426}
 427
 428/**
 429 * i40iw_get_encoded_wqe_size - given wq size, returns hardware encoded size
 430 * @wqsize: size of the wq (sq, rq, srq) to encoded_size
 431 * @cqpsq: encoded size for sq for cqp as its encoded size is 1+ other wq's
 432 */
 433u8 i40iw_get_encoded_wqe_size(u32 wqsize, bool cqpsq)
 434{
 435        u8 encoded_size = 0;
 436
 437        /* cqp sq's hw coded value starts from 1 for size of 4
 438         * while it starts from 0 for qp' wq's.
 439         */
 440        if (cqpsq)
 441                encoded_size = 1;
 442        wqsize >>= 2;
 443        while (wqsize >>= 1)
 444                encoded_size++;
 445        return encoded_size;
 446}
 447
 448/**
 449 * i40iw_sc_cqp_init - Initialize buffers for a control Queue Pair
 450 * @cqp: IWARP control queue pair pointer
 451 * @info: IWARP control queue pair init info pointer
 452 *
 453 * Initializes the object and context buffers for a control Queue Pair.
 454 */
 455static enum i40iw_status_code i40iw_sc_cqp_init(struct i40iw_sc_cqp *cqp,
 456                                                struct i40iw_cqp_init_info *info)
 457{
 458        u8 hw_sq_size;
 459
 460        if ((info->sq_size > I40IW_CQP_SW_SQSIZE_2048) ||
 461            (info->sq_size < I40IW_CQP_SW_SQSIZE_4) ||
 462            ((info->sq_size & (info->sq_size - 1))))
 463                return I40IW_ERR_INVALID_SIZE;
 464
 465        hw_sq_size = i40iw_get_encoded_wqe_size(info->sq_size, true);
 466        cqp->size = sizeof(*cqp);
 467        cqp->sq_size = info->sq_size;
 468        cqp->hw_sq_size = hw_sq_size;
 469        cqp->sq_base = info->sq;
 470        cqp->host_ctx = info->host_ctx;
 471        cqp->sq_pa = info->sq_pa;
 472        cqp->host_ctx_pa = info->host_ctx_pa;
 473        cqp->dev = info->dev;
 474        cqp->struct_ver = info->struct_ver;
 475        cqp->scratch_array = info->scratch_array;
 476        cqp->polarity = 0;
 477        cqp->en_datacenter_tcp = info->en_datacenter_tcp;
 478        cqp->enabled_vf_count = info->enabled_vf_count;
 479        cqp->hmc_profile = info->hmc_profile;
 480        info->dev->cqp = cqp;
 481
 482        I40IW_RING_INIT(cqp->sq_ring, cqp->sq_size);
 483        cqp->dev->cqp_cmd_stats[OP_REQUESTED_COMMANDS] = 0;
 484        cqp->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS] = 0;
 485        INIT_LIST_HEAD(&cqp->dev->cqp_cmd_head);               /* for the cqp commands backlog. */
 486
 487        i40iw_wr32(cqp->dev->hw, I40E_PFPE_CQPTAIL, 0);
 488        i40iw_wr32(cqp->dev->hw, I40E_PFPE_CQPDB, 0);
 489
 490        i40iw_debug(cqp->dev, I40IW_DEBUG_WQE,
 491                    "%s: sq_size[%04d] hw_sq_size[%04d] sq_base[%p] sq_pa[%llxh] cqp[%p] polarity[x%04X]\n",
 492                    __func__, cqp->sq_size, cqp->hw_sq_size,
 493                    cqp->sq_base, cqp->sq_pa, cqp, cqp->polarity);
 494        return 0;
 495}
 496
 497/**
 498 * i40iw_sc_cqp_create - create cqp during bringup
 499 * @cqp: struct for cqp hw
 500 * @maj_err: If error, major err number
 501 * @min_err: If error, minor err number
 502 */
 503static enum i40iw_status_code i40iw_sc_cqp_create(struct i40iw_sc_cqp *cqp,
 504                                                  u16 *maj_err,
 505                                                  u16 *min_err)
 506{
 507        u64 temp;
 508        u32 cnt = 0, p1, p2, val = 0, err_code;
 509        enum i40iw_status_code ret_code;
 510
 511        *maj_err = 0;
 512        *min_err = 0;
 513
 514        ret_code = i40iw_allocate_dma_mem(cqp->dev->hw,
 515                                          &cqp->sdbuf,
 516                                          I40IW_UPDATE_SD_BUF_SIZE * cqp->sq_size,
 517                                          I40IW_SD_BUF_ALIGNMENT);
 518
 519        if (ret_code)
 520                goto exit;
 521
 522        temp = LS_64(cqp->hw_sq_size, I40IW_CQPHC_SQSIZE) |
 523               LS_64(cqp->struct_ver, I40IW_CQPHC_SVER);
 524
 525        set_64bit_val(cqp->host_ctx, 0, temp);
 526        set_64bit_val(cqp->host_ctx, 8, cqp->sq_pa);
 527        temp = LS_64(cqp->enabled_vf_count, I40IW_CQPHC_ENABLED_VFS) |
 528               LS_64(cqp->hmc_profile, I40IW_CQPHC_HMC_PROFILE);
 529        set_64bit_val(cqp->host_ctx, 16, temp);
 530        set_64bit_val(cqp->host_ctx, 24, (uintptr_t)cqp);
 531        set_64bit_val(cqp->host_ctx, 32, 0);
 532        set_64bit_val(cqp->host_ctx, 40, 0);
 533        set_64bit_val(cqp->host_ctx, 48, 0);
 534        set_64bit_val(cqp->host_ctx, 56, 0);
 535
 536        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CQP_HOST_CTX",
 537                        cqp->host_ctx, I40IW_CQP_CTX_SIZE * 8);
 538
 539        p1 = RS_32_1(cqp->host_ctx_pa, 32);
 540        p2 = (u32)cqp->host_ctx_pa;
 541
 542        if (cqp->dev->is_pf) {
 543                i40iw_wr32(cqp->dev->hw, I40E_PFPE_CCQPHIGH, p1);
 544                i40iw_wr32(cqp->dev->hw, I40E_PFPE_CCQPLOW, p2);
 545        } else {
 546                i40iw_wr32(cqp->dev->hw, I40E_VFPE_CCQPHIGH1, p1);
 547                i40iw_wr32(cqp->dev->hw, I40E_VFPE_CCQPLOW1, p2);
 548        }
 549        do {
 550                if (cnt++ > I40IW_DONE_COUNT) {
 551                        i40iw_free_dma_mem(cqp->dev->hw, &cqp->sdbuf);
 552                        ret_code = I40IW_ERR_TIMEOUT;
 553                        /*
 554                         * read PFPE_CQPERRORCODES register to get the minor
 555                         * and major error code
 556                         */
 557                        if (cqp->dev->is_pf)
 558                                err_code = i40iw_rd32(cqp->dev->hw, I40E_PFPE_CQPERRCODES);
 559                        else
 560                                err_code = i40iw_rd32(cqp->dev->hw, I40E_VFPE_CQPERRCODES1);
 561                        *min_err = RS_32(err_code, I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE);
 562                        *maj_err = RS_32(err_code, I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE);
 563                        goto exit;
 564                }
 565                udelay(I40IW_SLEEP_COUNT);
 566                if (cqp->dev->is_pf)
 567                        val = i40iw_rd32(cqp->dev->hw, I40E_PFPE_CCQPSTATUS);
 568                else
 569                        val = i40iw_rd32(cqp->dev->hw, I40E_VFPE_CCQPSTATUS1);
 570        } while (!val);
 571
 572exit:
 573        if (!ret_code)
 574                cqp->process_cqp_sds = i40iw_update_sds_noccq;
 575        return ret_code;
 576}
 577
 578/**
 579 * i40iw_sc_cqp_post_sq - post of cqp's sq
 580 * @cqp: struct for cqp hw
 581 */
 582void i40iw_sc_cqp_post_sq(struct i40iw_sc_cqp *cqp)
 583{
 584        if (cqp->dev->is_pf)
 585                i40iw_wr32(cqp->dev->hw, I40E_PFPE_CQPDB, I40IW_RING_GETCURRENT_HEAD(cqp->sq_ring));
 586        else
 587                i40iw_wr32(cqp->dev->hw, I40E_VFPE_CQPDB1, I40IW_RING_GETCURRENT_HEAD(cqp->sq_ring));
 588
 589        i40iw_debug(cqp->dev,
 590                    I40IW_DEBUG_WQE,
 591                    "%s: HEAD_TAIL[%04d,%04d,%04d]\n",
 592                    __func__,
 593                    cqp->sq_ring.head,
 594                    cqp->sq_ring.tail,
 595                    cqp->sq_ring.size);
 596}
 597
 598/**
 599 * i40iw_sc_cqp_get_next_send_wqe_idx - get next WQE on CQP SQ and pass back the index
 600 * @cqp: pointer to CQP structure
 601 * @scratch: private data for CQP WQE
 602 * @wqe_idx: WQE index for next WQE on CQP SQ
 603 */
 604static u64 *i40iw_sc_cqp_get_next_send_wqe_idx(struct i40iw_sc_cqp *cqp,
 605                                               u64 scratch, u32 *wqe_idx)
 606{
 607        u64 *wqe = NULL;
 608        enum i40iw_status_code ret_code;
 609
 610        if (I40IW_RING_FULL_ERR(cqp->sq_ring)) {
 611                i40iw_debug(cqp->dev,
 612                            I40IW_DEBUG_WQE,
 613                            "%s: ring is full head %x tail %x size %x\n",
 614                            __func__,
 615                            cqp->sq_ring.head,
 616                            cqp->sq_ring.tail,
 617                            cqp->sq_ring.size);
 618                return NULL;
 619        }
 620        I40IW_ATOMIC_RING_MOVE_HEAD(cqp->sq_ring, *wqe_idx, ret_code);
 621        cqp->dev->cqp_cmd_stats[OP_REQUESTED_COMMANDS]++;
 622        if (ret_code)
 623                return NULL;
 624        if (!*wqe_idx)
 625                cqp->polarity = !cqp->polarity;
 626
 627        wqe = cqp->sq_base[*wqe_idx].elem;
 628        cqp->scratch_array[*wqe_idx] = scratch;
 629        I40IW_CQP_INIT_WQE(wqe);
 630
 631        return wqe;
 632}
 633
 634/**
 635 * i40iw_sc_cqp_get_next_send_wqe - get next wqe on cqp sq
 636 * @cqp: struct for cqp hw
 637 * @scratch: private data for CQP WQE
 638 */
 639u64 *i40iw_sc_cqp_get_next_send_wqe(struct i40iw_sc_cqp *cqp, u64 scratch)
 640{
 641        u32 wqe_idx;
 642
 643        return i40iw_sc_cqp_get_next_send_wqe_idx(cqp, scratch, &wqe_idx);
 644}
 645
 646/**
 647 * i40iw_sc_cqp_destroy - destroy cqp during close
 648 * @cqp: struct for cqp hw
 649 */
 650static enum i40iw_status_code i40iw_sc_cqp_destroy(struct i40iw_sc_cqp *cqp)
 651{
 652        u32 cnt = 0, val = 1;
 653        enum i40iw_status_code ret_code = 0;
 654        u32 cqpstat_addr;
 655
 656        if (cqp->dev->is_pf) {
 657                i40iw_wr32(cqp->dev->hw, I40E_PFPE_CCQPHIGH, 0);
 658                i40iw_wr32(cqp->dev->hw, I40E_PFPE_CCQPLOW, 0);
 659                cqpstat_addr = I40E_PFPE_CCQPSTATUS;
 660        } else {
 661                i40iw_wr32(cqp->dev->hw, I40E_VFPE_CCQPHIGH1, 0);
 662                i40iw_wr32(cqp->dev->hw, I40E_VFPE_CCQPLOW1, 0);
 663                cqpstat_addr = I40E_VFPE_CCQPSTATUS1;
 664        }
 665        do {
 666                if (cnt++ > I40IW_DONE_COUNT) {
 667                        ret_code = I40IW_ERR_TIMEOUT;
 668                        break;
 669                }
 670                udelay(I40IW_SLEEP_COUNT);
 671                val = i40iw_rd32(cqp->dev->hw, cqpstat_addr);
 672        } while (val);
 673
 674        i40iw_free_dma_mem(cqp->dev->hw, &cqp->sdbuf);
 675        return ret_code;
 676}
 677
 678/**
 679 * i40iw_sc_ccq_arm - enable intr for control cq
 680 * @ccq: ccq sc struct
 681 */
 682static void i40iw_sc_ccq_arm(struct i40iw_sc_cq *ccq)
 683{
 684        u64 temp_val;
 685        u16 sw_cq_sel;
 686        u8 arm_next_se;
 687        u8 arm_seq_num;
 688
 689        /* write to cq doorbell shadow area */
 690        /* arm next se should always be zero */
 691        get_64bit_val(ccq->cq_uk.shadow_area, 32, &temp_val);
 692
 693        sw_cq_sel = (u16)RS_64(temp_val, I40IW_CQ_DBSA_SW_CQ_SELECT);
 694        arm_next_se = (u8)RS_64(temp_val, I40IW_CQ_DBSA_ARM_NEXT_SE);
 695
 696        arm_seq_num = (u8)RS_64(temp_val, I40IW_CQ_DBSA_ARM_SEQ_NUM);
 697        arm_seq_num++;
 698
 699        temp_val = LS_64(arm_seq_num, I40IW_CQ_DBSA_ARM_SEQ_NUM) |
 700                   LS_64(sw_cq_sel, I40IW_CQ_DBSA_SW_CQ_SELECT) |
 701                   LS_64(arm_next_se, I40IW_CQ_DBSA_ARM_NEXT_SE) |
 702                   LS_64(1, I40IW_CQ_DBSA_ARM_NEXT);
 703
 704        set_64bit_val(ccq->cq_uk.shadow_area, 32, temp_val);
 705
 706        wmb();       /* make sure shadow area is updated before arming */
 707
 708        if (ccq->dev->is_pf)
 709                i40iw_wr32(ccq->dev->hw, I40E_PFPE_CQARM, ccq->cq_uk.cq_id);
 710        else
 711                i40iw_wr32(ccq->dev->hw, I40E_VFPE_CQARM1, ccq->cq_uk.cq_id);
 712}
 713
 714/**
 715 * i40iw_sc_ccq_get_cqe_info - get ccq's cq entry
 716 * @ccq: ccq sc struct
 717 * @info: completion q entry to return
 718 */
 719static enum i40iw_status_code i40iw_sc_ccq_get_cqe_info(
 720                                        struct i40iw_sc_cq *ccq,
 721                                        struct i40iw_ccq_cqe_info *info)
 722{
 723        u64 qp_ctx, temp, temp1;
 724        u64 *cqe;
 725        struct i40iw_sc_cqp *cqp;
 726        u32 wqe_idx;
 727        u8 polarity;
 728        enum i40iw_status_code ret_code = 0;
 729
 730        if (ccq->cq_uk.avoid_mem_cflct)
 731                cqe = (u64 *)I40IW_GET_CURRENT_EXTENDED_CQ_ELEMENT(&ccq->cq_uk);
 732        else
 733                cqe = (u64 *)I40IW_GET_CURRENT_CQ_ELEMENT(&ccq->cq_uk);
 734
 735        get_64bit_val(cqe, 24, &temp);
 736        polarity = (u8)RS_64(temp, I40IW_CQ_VALID);
 737        if (polarity != ccq->cq_uk.polarity)
 738                return I40IW_ERR_QUEUE_EMPTY;
 739
 740        get_64bit_val(cqe, 8, &qp_ctx);
 741        cqp = (struct i40iw_sc_cqp *)(unsigned long)qp_ctx;
 742        info->error = (bool)RS_64(temp, I40IW_CQ_ERROR);
 743        info->min_err_code = (u16)RS_64(temp, I40IW_CQ_MINERR);
 744        if (info->error) {
 745                info->maj_err_code = (u16)RS_64(temp, I40IW_CQ_MAJERR);
 746                info->min_err_code = (u16)RS_64(temp, I40IW_CQ_MINERR);
 747        }
 748        wqe_idx = (u32)RS_64(temp, I40IW_CQ_WQEIDX);
 749        info->scratch = cqp->scratch_array[wqe_idx];
 750
 751        get_64bit_val(cqe, 16, &temp1);
 752        info->op_ret_val = (u32)RS_64(temp1, I40IW_CCQ_OPRETVAL);
 753        get_64bit_val(cqp->sq_base[wqe_idx].elem, 24, &temp1);
 754        info->op_code = (u8)RS_64(temp1, I40IW_CQPSQ_OPCODE);
 755        info->cqp = cqp;
 756
 757        /*  move the head for cq */
 758        I40IW_RING_MOVE_HEAD(ccq->cq_uk.cq_ring, ret_code);
 759        if (I40IW_RING_GETCURRENT_HEAD(ccq->cq_uk.cq_ring) == 0)
 760                ccq->cq_uk.polarity ^= 1;
 761
 762        /* update cq tail in cq shadow memory also */
 763        I40IW_RING_MOVE_TAIL(ccq->cq_uk.cq_ring);
 764        set_64bit_val(ccq->cq_uk.shadow_area,
 765                      0,
 766                      I40IW_RING_GETCURRENT_HEAD(ccq->cq_uk.cq_ring));
 767        wmb(); /* write shadow area before tail */
 768        I40IW_RING_MOVE_TAIL(cqp->sq_ring);
 769        ccq->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS]++;
 770
 771        return ret_code;
 772}
 773
 774/**
 775 * i40iw_sc_poll_for_cqp_op_done - Waits for last write to complete in CQP SQ
 776 * @cqp: struct for cqp hw
 777 * @op_code: cqp opcode for completion
 778 * @info: completion q entry to return
 779 */
 780static enum i40iw_status_code i40iw_sc_poll_for_cqp_op_done(
 781                                        struct i40iw_sc_cqp *cqp,
 782                                        u8 op_code,
 783                                        struct i40iw_ccq_cqe_info *compl_info)
 784{
 785        struct i40iw_ccq_cqe_info info;
 786        struct i40iw_sc_cq *ccq;
 787        enum i40iw_status_code ret_code = 0;
 788        u32 cnt = 0;
 789
 790        memset(&info, 0, sizeof(info));
 791        ccq = cqp->dev->ccq;
 792        while (1) {
 793                if (cnt++ > I40IW_DONE_COUNT)
 794                        return I40IW_ERR_TIMEOUT;
 795
 796                if (i40iw_sc_ccq_get_cqe_info(ccq, &info)) {
 797                        udelay(I40IW_SLEEP_COUNT);
 798                        continue;
 799                }
 800
 801                if (info.error) {
 802                        ret_code = I40IW_ERR_CQP_COMPL_ERROR;
 803                        break;
 804                }
 805                /* check if opcode is cq create */
 806                if (op_code != info.op_code) {
 807                        i40iw_debug(cqp->dev, I40IW_DEBUG_WQE,
 808                                    "%s: opcode mismatch for my op code 0x%x, returned opcode %x\n",
 809                                    __func__, op_code, info.op_code);
 810                }
 811                /* success, exit out of the loop */
 812                if (op_code == info.op_code)
 813                        break;
 814        }
 815
 816        if (compl_info)
 817                memcpy(compl_info, &info, sizeof(*compl_info));
 818
 819        return ret_code;
 820}
 821
 822/**
 823 * i40iw_sc_manage_push_page - Handle push page
 824 * @cqp: struct for cqp hw
 825 * @info: push page info
 826 * @scratch: u64 saved to be used during cqp completion
 827 * @post_sq: flag for cqp db to ring
 828 */
 829static enum i40iw_status_code i40iw_sc_manage_push_page(
 830                                struct i40iw_sc_cqp *cqp,
 831                                struct i40iw_cqp_manage_push_page_info *info,
 832                                u64 scratch,
 833                                bool post_sq)
 834{
 835        u64 *wqe;
 836        u64 header;
 837
 838        if (info->push_idx >= I40IW_MAX_PUSH_PAGE_COUNT)
 839                return I40IW_ERR_INVALID_PUSH_PAGE_INDEX;
 840
 841        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 842        if (!wqe)
 843                return I40IW_ERR_RING_FULL;
 844
 845        set_64bit_val(wqe, 16, info->qs_handle);
 846
 847        header = LS_64(info->push_idx, I40IW_CQPSQ_MPP_PPIDX) |
 848                 LS_64(I40IW_CQP_OP_MANAGE_PUSH_PAGES, I40IW_CQPSQ_OPCODE) |
 849                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID) |
 850                 LS_64(info->free_page, I40IW_CQPSQ_MPP_FREE_PAGE);
 851
 852        i40iw_insert_wqe_hdr(wqe, header);
 853
 854        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "MANAGE_PUSH_PAGES WQE",
 855                        wqe, I40IW_CQP_WQE_SIZE * 8);
 856
 857        if (post_sq)
 858                i40iw_sc_cqp_post_sq(cqp);
 859        return 0;
 860}
 861
 862/**
 863 * i40iw_sc_manage_hmc_pm_func_table - manage of function table
 864 * @cqp: struct for cqp hw
 865 * @scratch: u64 saved to be used during cqp completion
 866 * @vf_index: vf index for cqp
 867 * @free_pm_fcn: function number
 868 * @post_sq: flag for cqp db to ring
 869 */
 870static enum i40iw_status_code i40iw_sc_manage_hmc_pm_func_table(
 871                                struct i40iw_sc_cqp *cqp,
 872                                u64 scratch,
 873                                u8 vf_index,
 874                                bool free_pm_fcn,
 875                                bool post_sq)
 876{
 877        u64 *wqe;
 878        u64 header;
 879
 880        if (vf_index >= I40IW_MAX_VF_PER_PF)
 881                return I40IW_ERR_INVALID_VF_ID;
 882        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 883        if (!wqe)
 884                return I40IW_ERR_RING_FULL;
 885
 886        header = LS_64(vf_index, I40IW_CQPSQ_MHMC_VFIDX) |
 887                 LS_64(I40IW_CQP_OP_MANAGE_HMC_PM_FUNC_TABLE, I40IW_CQPSQ_OPCODE) |
 888                 LS_64(free_pm_fcn, I40IW_CQPSQ_MHMC_FREEPMFN) |
 889                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
 890
 891        i40iw_insert_wqe_hdr(wqe, header);
 892        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "MANAGE_HMC_PM_FUNC_TABLE WQE",
 893                        wqe, I40IW_CQP_WQE_SIZE * 8);
 894        if (post_sq)
 895                i40iw_sc_cqp_post_sq(cqp);
 896        return 0;
 897}
 898
 899/**
 900 * i40iw_sc_set_hmc_resource_profile - cqp wqe for hmc profile
 901 * @cqp: struct for cqp hw
 902 * @scratch: u64 saved to be used during cqp completion
 903 * @hmc_profile_type: type of profile to set
 904 * @vf_num: vf number for profile
 905 * @post_sq: flag for cqp db to ring
 906 * @poll_registers: flag to poll register for cqp completion
 907 */
 908static enum i40iw_status_code i40iw_sc_set_hmc_resource_profile(
 909                                struct i40iw_sc_cqp *cqp,
 910                                u64 scratch,
 911                                u8 hmc_profile_type,
 912                                u8 vf_num, bool post_sq,
 913                                bool poll_registers)
 914{
 915        u64 *wqe;
 916        u64 header;
 917        u32 val, tail, error;
 918        enum i40iw_status_code ret_code = 0;
 919
 920        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 921        if (!wqe)
 922                return I40IW_ERR_RING_FULL;
 923
 924        set_64bit_val(wqe, 16,
 925                      (LS_64(hmc_profile_type, I40IW_CQPSQ_SHMCRP_HMC_PROFILE) |
 926                                LS_64(vf_num, I40IW_CQPSQ_SHMCRP_VFNUM)));
 927
 928        header = LS_64(I40IW_CQP_OP_SET_HMC_RESOURCE_PROFILE, I40IW_CQPSQ_OPCODE) |
 929                       LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
 930
 931        i40iw_insert_wqe_hdr(wqe, header);
 932
 933        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "MANAGE_HMC_PM_FUNC_TABLE WQE",
 934                        wqe, I40IW_CQP_WQE_SIZE * 8);
 935
 936        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
 937        if (error)
 938                return I40IW_ERR_CQP_COMPL_ERROR;
 939
 940        if (post_sq) {
 941                i40iw_sc_cqp_post_sq(cqp);
 942                if (poll_registers)
 943                        ret_code = i40iw_cqp_poll_registers(cqp, tail, 1000000);
 944                else
 945                        ret_code = i40iw_sc_poll_for_cqp_op_done(cqp,
 946                                                                 I40IW_CQP_OP_SHMC_PAGES_ALLOCATED,
 947                                                                 NULL);
 948        }
 949
 950        return ret_code;
 951}
 952
 953/**
 954 * i40iw_sc_manage_hmc_pm_func_table_done - wait for cqp wqe completion for function table
 955 * @cqp: struct for cqp hw
 956 */
 957static enum i40iw_status_code i40iw_sc_manage_hmc_pm_func_table_done(struct i40iw_sc_cqp *cqp)
 958{
 959        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_MANAGE_HMC_PM_FUNC_TABLE, NULL);
 960}
 961
 962/**
 963 * i40iw_sc_commit_fpm_values_done - wait for cqp eqe completion for fpm commit
 964 * @cqp: struct for cqp hw
 965 */
 966static enum i40iw_status_code i40iw_sc_commit_fpm_values_done(struct i40iw_sc_cqp *cqp)
 967{
 968        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_COMMIT_FPM_VALUES, NULL);
 969}
 970
 971/**
 972 * i40iw_sc_commit_fpm_values - cqp wqe for commit fpm values
 973 * @cqp: struct for cqp hw
 974 * @scratch: u64 saved to be used during cqp completion
 975 * @hmc_fn_id: hmc function id
 976 * @commit_fpm_mem; Memory for fpm values
 977 * @post_sq: flag for cqp db to ring
 978 * @wait_type: poll ccq or cqp registers for cqp completion
 979 */
 980static enum i40iw_status_code i40iw_sc_commit_fpm_values(
 981                                        struct i40iw_sc_cqp *cqp,
 982                                        u64 scratch,
 983                                        u8 hmc_fn_id,
 984                                        struct i40iw_dma_mem *commit_fpm_mem,
 985                                        bool post_sq,
 986                                        u8 wait_type)
 987{
 988        u64 *wqe;
 989        u64 header;
 990        u32 tail, val, error;
 991        enum i40iw_status_code ret_code = 0;
 992
 993        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 994        if (!wqe)
 995                return I40IW_ERR_RING_FULL;
 996
 997        set_64bit_val(wqe, 16, hmc_fn_id);
 998        set_64bit_val(wqe, 32, commit_fpm_mem->pa);
 999
1000        header = LS_64(I40IW_CQP_OP_COMMIT_FPM_VALUES, I40IW_CQPSQ_OPCODE) |
1001                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1002
1003        i40iw_insert_wqe_hdr(wqe, header);
1004
1005        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "COMMIT_FPM_VALUES WQE",
1006                        wqe, I40IW_CQP_WQE_SIZE * 8);
1007
1008        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
1009        if (error)
1010                return I40IW_ERR_CQP_COMPL_ERROR;
1011
1012        if (post_sq) {
1013                i40iw_sc_cqp_post_sq(cqp);
1014
1015                if (wait_type == I40IW_CQP_WAIT_POLL_REGS)
1016                        ret_code = i40iw_cqp_poll_registers(cqp, tail, I40IW_DONE_COUNT);
1017                else if (wait_type == I40IW_CQP_WAIT_POLL_CQ)
1018                        ret_code = i40iw_sc_commit_fpm_values_done(cqp);
1019        }
1020
1021        return ret_code;
1022}
1023
1024/**
1025 * i40iw_sc_query_fpm_values_done - poll for cqp wqe completion for query fpm
1026 * @cqp: struct for cqp hw
1027 */
1028static enum i40iw_status_code i40iw_sc_query_fpm_values_done(struct i40iw_sc_cqp *cqp)
1029{
1030        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_QUERY_FPM_VALUES, NULL);
1031}
1032
1033/**
1034 * i40iw_sc_query_fpm_values - cqp wqe query fpm values
1035 * @cqp: struct for cqp hw
1036 * @scratch: u64 saved to be used during cqp completion
1037 * @hmc_fn_id: hmc function id
1038 * @query_fpm_mem: memory for return fpm values
1039 * @post_sq: flag for cqp db to ring
1040 * @wait_type: poll ccq or cqp registers for cqp completion
1041 */
1042static enum i40iw_status_code i40iw_sc_query_fpm_values(
1043                                        struct i40iw_sc_cqp *cqp,
1044                                        u64 scratch,
1045                                        u8 hmc_fn_id,
1046                                        struct i40iw_dma_mem *query_fpm_mem,
1047                                        bool post_sq,
1048                                        u8 wait_type)
1049{
1050        u64 *wqe;
1051        u64 header;
1052        u32 tail, val, error;
1053        enum i40iw_status_code ret_code = 0;
1054
1055        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1056        if (!wqe)
1057                return I40IW_ERR_RING_FULL;
1058
1059        set_64bit_val(wqe, 16, hmc_fn_id);
1060        set_64bit_val(wqe, 32, query_fpm_mem->pa);
1061
1062        header = LS_64(I40IW_CQP_OP_QUERY_FPM_VALUES, I40IW_CQPSQ_OPCODE) |
1063                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1064
1065        i40iw_insert_wqe_hdr(wqe, header);
1066
1067        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QUERY_FPM WQE",
1068                        wqe, I40IW_CQP_WQE_SIZE * 8);
1069
1070        /* read the tail from CQP_TAIL register */
1071        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
1072
1073        if (error)
1074                return I40IW_ERR_CQP_COMPL_ERROR;
1075
1076        if (post_sq) {
1077                i40iw_sc_cqp_post_sq(cqp);
1078                if (wait_type == I40IW_CQP_WAIT_POLL_REGS)
1079                        ret_code = i40iw_cqp_poll_registers(cqp, tail, I40IW_DONE_COUNT);
1080                else if (wait_type == I40IW_CQP_WAIT_POLL_CQ)
1081                        ret_code = i40iw_sc_query_fpm_values_done(cqp);
1082        }
1083
1084        return ret_code;
1085}
1086
1087/**
1088 * i40iw_sc_add_arp_cache_entry - cqp wqe add arp cache entry
1089 * @cqp: struct for cqp hw
1090 * @info: arp entry information
1091 * @scratch: u64 saved to be used during cqp completion
1092 * @post_sq: flag for cqp db to ring
1093 */
1094static enum i40iw_status_code i40iw_sc_add_arp_cache_entry(
1095                                struct i40iw_sc_cqp *cqp,
1096                                struct i40iw_add_arp_cache_entry_info *info,
1097                                u64 scratch,
1098                                bool post_sq)
1099{
1100        u64 *wqe;
1101        u64 temp, header;
1102
1103        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1104        if (!wqe)
1105                return I40IW_ERR_RING_FULL;
1106        set_64bit_val(wqe, 8, info->reach_max);
1107
1108        temp = info->mac_addr[5] |
1109               LS_64_1(info->mac_addr[4], 8) |
1110               LS_64_1(info->mac_addr[3], 16) |
1111               LS_64_1(info->mac_addr[2], 24) |
1112               LS_64_1(info->mac_addr[1], 32) |
1113               LS_64_1(info->mac_addr[0], 40);
1114
1115        set_64bit_val(wqe, 16, temp);
1116
1117        header = info->arp_index |
1118                 LS_64(I40IW_CQP_OP_MANAGE_ARP, I40IW_CQPSQ_OPCODE) |
1119                 LS_64((info->permanent ? 1 : 0), I40IW_CQPSQ_MAT_PERMANENT) |
1120                 LS_64(1, I40IW_CQPSQ_MAT_ENTRYVALID) |
1121                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1122
1123        i40iw_insert_wqe_hdr(wqe, header);
1124
1125        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "ARP_CACHE_ENTRY WQE",
1126                        wqe, I40IW_CQP_WQE_SIZE * 8);
1127
1128        if (post_sq)
1129                i40iw_sc_cqp_post_sq(cqp);
1130        return 0;
1131}
1132
1133/**
1134 * i40iw_sc_del_arp_cache_entry - dele arp cache entry
1135 * @cqp: struct for cqp hw
1136 * @scratch: u64 saved to be used during cqp completion
1137 * @arp_index: arp index to delete arp entry
1138 * @post_sq: flag for cqp db to ring
1139 */
1140static enum i40iw_status_code i40iw_sc_del_arp_cache_entry(
1141                                        struct i40iw_sc_cqp *cqp,
1142                                        u64 scratch,
1143                                        u16 arp_index,
1144                                        bool post_sq)
1145{
1146        u64 *wqe;
1147        u64 header;
1148
1149        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1150        if (!wqe)
1151                return I40IW_ERR_RING_FULL;
1152
1153        header = arp_index |
1154                 LS_64(I40IW_CQP_OP_MANAGE_ARP, I40IW_CQPSQ_OPCODE) |
1155                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1156        i40iw_insert_wqe_hdr(wqe, header);
1157
1158        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "ARP_CACHE_DEL_ENTRY WQE",
1159                        wqe, I40IW_CQP_WQE_SIZE * 8);
1160
1161        if (post_sq)
1162                i40iw_sc_cqp_post_sq(cqp);
1163        return 0;
1164}
1165
1166/**
1167 * i40iw_sc_query_arp_cache_entry - cqp wqe to query arp and arp index
1168 * @cqp: struct for cqp hw
1169 * @scratch: u64 saved to be used during cqp completion
1170 * @arp_index: arp index to delete arp entry
1171 * @post_sq: flag for cqp db to ring
1172 */
1173static enum i40iw_status_code i40iw_sc_query_arp_cache_entry(
1174                                struct i40iw_sc_cqp *cqp,
1175                                u64 scratch,
1176                                u16 arp_index,
1177                                bool post_sq)
1178{
1179        u64 *wqe;
1180        u64 header;
1181
1182        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1183        if (!wqe)
1184                return I40IW_ERR_RING_FULL;
1185
1186        header = arp_index |
1187                 LS_64(I40IW_CQP_OP_MANAGE_ARP, I40IW_CQPSQ_OPCODE) |
1188                 LS_64(1, I40IW_CQPSQ_MAT_QUERY) |
1189                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1190
1191        i40iw_insert_wqe_hdr(wqe, header);
1192
1193        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QUERY_ARP_CACHE_ENTRY WQE",
1194                        wqe, I40IW_CQP_WQE_SIZE * 8);
1195
1196        if (post_sq)
1197                i40iw_sc_cqp_post_sq(cqp);
1198        return 0;
1199}
1200
1201/**
1202 * i40iw_sc_manage_apbvt_entry - for adding and deleting apbvt entries
1203 * @cqp: struct for cqp hw
1204 * @info: info for apbvt entry to add or delete
1205 * @scratch: u64 saved to be used during cqp completion
1206 * @post_sq: flag for cqp db to ring
1207 */
1208static enum i40iw_status_code i40iw_sc_manage_apbvt_entry(
1209                                struct i40iw_sc_cqp *cqp,
1210                                struct i40iw_apbvt_info *info,
1211                                u64 scratch,
1212                                bool post_sq)
1213{
1214        u64 *wqe;
1215        u64 header;
1216
1217        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1218        if (!wqe)
1219                return I40IW_ERR_RING_FULL;
1220
1221        set_64bit_val(wqe, 16, info->port);
1222
1223        header = LS_64(I40IW_CQP_OP_MANAGE_APBVT, I40IW_CQPSQ_OPCODE) |
1224                 LS_64(info->add, I40IW_CQPSQ_MAPT_ADDPORT) |
1225                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1226
1227        i40iw_insert_wqe_hdr(wqe, header);
1228
1229        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "MANAGE_APBVT WQE",
1230                        wqe, I40IW_CQP_WQE_SIZE * 8);
1231
1232        if (post_sq)
1233                i40iw_sc_cqp_post_sq(cqp);
1234        return 0;
1235}
1236
1237/**
1238 * i40iw_sc_manage_qhash_table_entry - manage quad hash entries
1239 * @cqp: struct for cqp hw
1240 * @info: info for quad hash to manage
1241 * @scratch: u64 saved to be used during cqp completion
1242 * @post_sq: flag for cqp db to ring
1243 *
1244 * This is called before connection establishment is started. For passive connections, when
1245 * listener is created, it will call with entry type of  I40IW_QHASH_TYPE_TCP_SYN with local
1246 * ip address and tcp port. When SYN is received (passive connections) or
1247 * sent (active connections), this routine is called with entry type of
1248 * I40IW_QHASH_TYPE_TCP_ESTABLISHED and quad is passed in info.
1249 *
1250 * When iwarp connection is done and its state moves to RTS, the quad hash entry in
1251 * the hardware will point to iwarp's qp number and requires no calls from the driver.
1252 */
1253static enum i40iw_status_code i40iw_sc_manage_qhash_table_entry(
1254                                        struct i40iw_sc_cqp *cqp,
1255                                        struct i40iw_qhash_table_info *info,
1256                                        u64 scratch,
1257                                        bool post_sq)
1258{
1259        u64 *wqe;
1260        u64 qw1 = 0;
1261        u64 qw2 = 0;
1262        u64 temp;
1263        struct i40iw_sc_vsi *vsi = info->vsi;
1264
1265        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1266        if (!wqe)
1267                return I40IW_ERR_RING_FULL;
1268
1269        temp = info->mac_addr[5] |
1270                LS_64_1(info->mac_addr[4], 8) |
1271                LS_64_1(info->mac_addr[3], 16) |
1272                LS_64_1(info->mac_addr[2], 24) |
1273                LS_64_1(info->mac_addr[1], 32) |
1274                LS_64_1(info->mac_addr[0], 40);
1275
1276        set_64bit_val(wqe, 0, temp);
1277
1278        qw1 = LS_64(info->qp_num, I40IW_CQPSQ_QHASH_QPN) |
1279              LS_64(info->dest_port, I40IW_CQPSQ_QHASH_DEST_PORT);
1280        if (info->ipv4_valid) {
1281                set_64bit_val(wqe,
1282                              48,
1283                              LS_64(info->dest_ip[0], I40IW_CQPSQ_QHASH_ADDR3));
1284        } else {
1285                set_64bit_val(wqe,
1286                              56,
1287                              LS_64(info->dest_ip[0], I40IW_CQPSQ_QHASH_ADDR0) |
1288                              LS_64(info->dest_ip[1], I40IW_CQPSQ_QHASH_ADDR1));
1289
1290                set_64bit_val(wqe,
1291                              48,
1292                              LS_64(info->dest_ip[2], I40IW_CQPSQ_QHASH_ADDR2) |
1293                              LS_64(info->dest_ip[3], I40IW_CQPSQ_QHASH_ADDR3));
1294        }
1295        qw2 = LS_64(vsi->qos[info->user_pri].qs_handle, I40IW_CQPSQ_QHASH_QS_HANDLE);
1296        if (info->vlan_valid)
1297                qw2 |= LS_64(info->vlan_id, I40IW_CQPSQ_QHASH_VLANID);
1298        set_64bit_val(wqe, 16, qw2);
1299        if (info->entry_type == I40IW_QHASH_TYPE_TCP_ESTABLISHED) {
1300                qw1 |= LS_64(info->src_port, I40IW_CQPSQ_QHASH_SRC_PORT);
1301                if (!info->ipv4_valid) {
1302                        set_64bit_val(wqe,
1303                                      40,
1304                                      LS_64(info->src_ip[0], I40IW_CQPSQ_QHASH_ADDR0) |
1305                                      LS_64(info->src_ip[1], I40IW_CQPSQ_QHASH_ADDR1));
1306                        set_64bit_val(wqe,
1307                                      32,
1308                                      LS_64(info->src_ip[2], I40IW_CQPSQ_QHASH_ADDR2) |
1309                                      LS_64(info->src_ip[3], I40IW_CQPSQ_QHASH_ADDR3));
1310                } else {
1311                        set_64bit_val(wqe,
1312                                      32,
1313                                      LS_64(info->src_ip[0], I40IW_CQPSQ_QHASH_ADDR3));
1314                }
1315        }
1316
1317        set_64bit_val(wqe, 8, qw1);
1318        temp = LS_64(cqp->polarity, I40IW_CQPSQ_QHASH_WQEVALID) |
1319               LS_64(I40IW_CQP_OP_MANAGE_QUAD_HASH_TABLE_ENTRY, I40IW_CQPSQ_QHASH_OPCODE) |
1320               LS_64(info->manage, I40IW_CQPSQ_QHASH_MANAGE) |
1321               LS_64(info->ipv4_valid, I40IW_CQPSQ_QHASH_IPV4VALID) |
1322               LS_64(info->vlan_valid, I40IW_CQPSQ_QHASH_VLANVALID) |
1323               LS_64(info->entry_type, I40IW_CQPSQ_QHASH_ENTRYTYPE);
1324
1325        i40iw_insert_wqe_hdr(wqe, temp);
1326
1327        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "MANAGE_QHASH WQE",
1328                        wqe, I40IW_CQP_WQE_SIZE * 8);
1329
1330        if (post_sq)
1331                i40iw_sc_cqp_post_sq(cqp);
1332        return 0;
1333}
1334
1335/**
1336 * i40iw_sc_alloc_local_mac_ipaddr_entry - cqp wqe for loc mac entry
1337 * @cqp: struct for cqp hw
1338 * @scratch: u64 saved to be used during cqp completion
1339 * @post_sq: flag for cqp db to ring
1340 */
1341static enum i40iw_status_code i40iw_sc_alloc_local_mac_ipaddr_entry(
1342                                        struct i40iw_sc_cqp *cqp,
1343                                        u64 scratch,
1344                                        bool post_sq)
1345{
1346        u64 *wqe;
1347        u64 header;
1348
1349        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1350        if (!wqe)
1351                return I40IW_ERR_RING_FULL;
1352        header = LS_64(I40IW_CQP_OP_ALLOCATE_LOC_MAC_IP_TABLE_ENTRY, I40IW_CQPSQ_OPCODE) |
1353                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1354
1355        i40iw_insert_wqe_hdr(wqe, header);
1356        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "ALLOCATE_LOCAL_MAC_IPADDR WQE",
1357                        wqe, I40IW_CQP_WQE_SIZE * 8);
1358        if (post_sq)
1359                i40iw_sc_cqp_post_sq(cqp);
1360        return 0;
1361}
1362
1363/**
1364 * i40iw_sc_add_local_mac_ipaddr_entry - add mac enry
1365 * @cqp: struct for cqp hw
1366 * @info:mac addr info
1367 * @scratch: u64 saved to be used during cqp completion
1368 * @post_sq: flag for cqp db to ring
1369 */
1370static enum i40iw_status_code i40iw_sc_add_local_mac_ipaddr_entry(
1371                                struct i40iw_sc_cqp *cqp,
1372                                struct i40iw_local_mac_ipaddr_entry_info *info,
1373                                u64 scratch,
1374                                bool post_sq)
1375{
1376        u64 *wqe;
1377        u64 temp, header;
1378
1379        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1380        if (!wqe)
1381                return I40IW_ERR_RING_FULL;
1382        temp = info->mac_addr[5] |
1383                LS_64_1(info->mac_addr[4], 8) |
1384                LS_64_1(info->mac_addr[3], 16) |
1385                LS_64_1(info->mac_addr[2], 24) |
1386                LS_64_1(info->mac_addr[1], 32) |
1387                LS_64_1(info->mac_addr[0], 40);
1388
1389        set_64bit_val(wqe, 32, temp);
1390
1391        header = LS_64(info->entry_idx, I40IW_CQPSQ_MLIPA_IPTABLEIDX) |
1392                 LS_64(I40IW_CQP_OP_MANAGE_LOC_MAC_IP_TABLE, I40IW_CQPSQ_OPCODE) |
1393                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1394
1395        i40iw_insert_wqe_hdr(wqe, header);
1396
1397        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "ADD_LOCAL_MAC_IPADDR WQE",
1398                        wqe, I40IW_CQP_WQE_SIZE * 8);
1399
1400        if (post_sq)
1401                i40iw_sc_cqp_post_sq(cqp);
1402        return 0;
1403}
1404
1405/**
1406 * i40iw_sc_del_local_mac_ipaddr_entry - cqp wqe to dele local mac
1407 * @cqp: struct for cqp hw
1408 * @scratch: u64 saved to be used during cqp completion
1409 * @entry_idx: index of mac entry
1410 * @ ignore_ref_count: to force mac adde delete
1411 * @post_sq: flag for cqp db to ring
1412 */
1413static enum i40iw_status_code i40iw_sc_del_local_mac_ipaddr_entry(
1414                                struct i40iw_sc_cqp *cqp,
1415                                u64 scratch,
1416                                u8 entry_idx,
1417                                u8 ignore_ref_count,
1418                                bool post_sq)
1419{
1420        u64 *wqe;
1421        u64 header;
1422
1423        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1424        if (!wqe)
1425                return I40IW_ERR_RING_FULL;
1426        header = LS_64(entry_idx, I40IW_CQPSQ_MLIPA_IPTABLEIDX) |
1427                 LS_64(I40IW_CQP_OP_MANAGE_LOC_MAC_IP_TABLE, I40IW_CQPSQ_OPCODE) |
1428                 LS_64(1, I40IW_CQPSQ_MLIPA_FREEENTRY) |
1429                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID) |
1430                 LS_64(ignore_ref_count, I40IW_CQPSQ_MLIPA_IGNORE_REF_CNT);
1431
1432        i40iw_insert_wqe_hdr(wqe, header);
1433
1434        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "DEL_LOCAL_MAC_IPADDR WQE",
1435                        wqe, I40IW_CQP_WQE_SIZE * 8);
1436
1437        if (post_sq)
1438                i40iw_sc_cqp_post_sq(cqp);
1439        return 0;
1440}
1441
1442/**
1443 * i40iw_sc_cqp_nop - send a nop wqe
1444 * @cqp: struct for cqp hw
1445 * @scratch: u64 saved to be used during cqp completion
1446 * @post_sq: flag for cqp db to ring
1447 */
1448static enum i40iw_status_code i40iw_sc_cqp_nop(struct i40iw_sc_cqp *cqp,
1449                                               u64 scratch,
1450                                               bool post_sq)
1451{
1452        u64 *wqe;
1453        u64 header;
1454
1455        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1456        if (!wqe)
1457                return I40IW_ERR_RING_FULL;
1458        header = LS_64(I40IW_CQP_OP_NOP, I40IW_CQPSQ_OPCODE) |
1459                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1460        i40iw_insert_wqe_hdr(wqe, header);
1461        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "NOP WQE",
1462                        wqe, I40IW_CQP_WQE_SIZE * 8);
1463
1464        if (post_sq)
1465                i40iw_sc_cqp_post_sq(cqp);
1466        return 0;
1467}
1468
1469/**
1470 * i40iw_sc_ceq_init - initialize ceq
1471 * @ceq: ceq sc structure
1472 * @info: ceq initialization info
1473 */
1474static enum i40iw_status_code i40iw_sc_ceq_init(struct i40iw_sc_ceq *ceq,
1475                                                struct i40iw_ceq_init_info *info)
1476{
1477        u32 pble_obj_cnt;
1478
1479        if ((info->elem_cnt < I40IW_MIN_CEQ_ENTRIES) ||
1480            (info->elem_cnt > I40IW_MAX_CEQ_ENTRIES))
1481                return I40IW_ERR_INVALID_SIZE;
1482
1483        if (info->ceq_id >= I40IW_MAX_CEQID)
1484                return I40IW_ERR_INVALID_CEQ_ID;
1485
1486        pble_obj_cnt = info->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
1487
1488        if (info->virtual_map && (info->first_pm_pbl_idx >= pble_obj_cnt))
1489                return I40IW_ERR_INVALID_PBLE_INDEX;
1490
1491        ceq->size = sizeof(*ceq);
1492        ceq->ceqe_base = (struct i40iw_ceqe *)info->ceqe_base;
1493        ceq->ceq_id = info->ceq_id;
1494        ceq->dev = info->dev;
1495        ceq->elem_cnt = info->elem_cnt;
1496        ceq->ceq_elem_pa = info->ceqe_pa;
1497        ceq->virtual_map = info->virtual_map;
1498
1499        ceq->pbl_chunk_size = (ceq->virtual_map ? info->pbl_chunk_size : 0);
1500        ceq->first_pm_pbl_idx = (ceq->virtual_map ? info->first_pm_pbl_idx : 0);
1501        ceq->pbl_list = (ceq->virtual_map ? info->pbl_list : NULL);
1502
1503        ceq->tph_en = info->tph_en;
1504        ceq->tph_val = info->tph_val;
1505        ceq->polarity = 1;
1506        I40IW_RING_INIT(ceq->ceq_ring, ceq->elem_cnt);
1507        ceq->dev->ceq[info->ceq_id] = ceq;
1508
1509        return 0;
1510}
1511
1512/**
1513 * i40iw_sc_ceq_create - create ceq wqe
1514 * @ceq: ceq sc structure
1515 * @scratch: u64 saved to be used during cqp completion
1516 * @post_sq: flag for cqp db to ring
1517 */
1518static enum i40iw_status_code i40iw_sc_ceq_create(struct i40iw_sc_ceq *ceq,
1519                                                  u64 scratch,
1520                                                  bool post_sq)
1521{
1522        struct i40iw_sc_cqp *cqp;
1523        u64 *wqe;
1524        u64 header;
1525
1526        cqp = ceq->dev->cqp;
1527        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1528        if (!wqe)
1529                return I40IW_ERR_RING_FULL;
1530        set_64bit_val(wqe, 16, ceq->elem_cnt);
1531        set_64bit_val(wqe, 32, (ceq->virtual_map ? 0 : ceq->ceq_elem_pa));
1532        set_64bit_val(wqe, 48, (ceq->virtual_map ? ceq->first_pm_pbl_idx : 0));
1533        set_64bit_val(wqe, 56, LS_64(ceq->tph_val, I40IW_CQPSQ_TPHVAL));
1534
1535        header = ceq->ceq_id |
1536                 LS_64(I40IW_CQP_OP_CREATE_CEQ, I40IW_CQPSQ_OPCODE) |
1537                 LS_64(ceq->pbl_chunk_size, I40IW_CQPSQ_CEQ_LPBLSIZE) |
1538                 LS_64(ceq->virtual_map, I40IW_CQPSQ_CEQ_VMAP) |
1539                 LS_64(ceq->tph_en, I40IW_CQPSQ_TPHEN) |
1540                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1541
1542        i40iw_insert_wqe_hdr(wqe, header);
1543
1544        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CEQ_CREATE WQE",
1545                        wqe, I40IW_CQP_WQE_SIZE * 8);
1546
1547        if (post_sq)
1548                i40iw_sc_cqp_post_sq(cqp);
1549        return 0;
1550}
1551
1552/**
1553 * i40iw_sc_cceq_create_done - poll for control ceq wqe to complete
1554 * @ceq: ceq sc structure
1555 */
1556static enum i40iw_status_code i40iw_sc_cceq_create_done(struct i40iw_sc_ceq *ceq)
1557{
1558        struct i40iw_sc_cqp *cqp;
1559
1560        cqp = ceq->dev->cqp;
1561        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_CREATE_CEQ, NULL);
1562}
1563
1564/**
1565 * i40iw_sc_cceq_destroy_done - poll for destroy cceq to complete
1566 * @ceq: ceq sc structure
1567 */
1568static enum i40iw_status_code i40iw_sc_cceq_destroy_done(struct i40iw_sc_ceq *ceq)
1569{
1570        struct i40iw_sc_cqp *cqp;
1571
1572        cqp = ceq->dev->cqp;
1573        cqp->process_cqp_sds = i40iw_update_sds_noccq;
1574        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_DESTROY_CEQ, NULL);
1575}
1576
1577/**
1578 * i40iw_sc_cceq_create - create cceq
1579 * @ceq: ceq sc structure
1580 * @scratch: u64 saved to be used during cqp completion
1581 */
1582static enum i40iw_status_code i40iw_sc_cceq_create(struct i40iw_sc_ceq *ceq, u64 scratch)
1583{
1584        enum i40iw_status_code ret_code;
1585
1586        ret_code = i40iw_sc_ceq_create(ceq, scratch, true);
1587        if (!ret_code)
1588                ret_code = i40iw_sc_cceq_create_done(ceq);
1589        return ret_code;
1590}
1591
1592/**
1593 * i40iw_sc_ceq_destroy - destroy ceq
1594 * @ceq: ceq sc structure
1595 * @scratch: u64 saved to be used during cqp completion
1596 * @post_sq: flag for cqp db to ring
1597 */
1598static enum i40iw_status_code i40iw_sc_ceq_destroy(struct i40iw_sc_ceq *ceq,
1599                                                   u64 scratch,
1600                                                   bool post_sq)
1601{
1602        struct i40iw_sc_cqp *cqp;
1603        u64 *wqe;
1604        u64 header;
1605
1606        cqp = ceq->dev->cqp;
1607        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1608        if (!wqe)
1609                return I40IW_ERR_RING_FULL;
1610        set_64bit_val(wqe, 16, ceq->elem_cnt);
1611        set_64bit_val(wqe, 48, ceq->first_pm_pbl_idx);
1612        header = ceq->ceq_id |
1613                 LS_64(I40IW_CQP_OP_DESTROY_CEQ, I40IW_CQPSQ_OPCODE) |
1614                 LS_64(ceq->pbl_chunk_size, I40IW_CQPSQ_CEQ_LPBLSIZE) |
1615                 LS_64(ceq->virtual_map, I40IW_CQPSQ_CEQ_VMAP) |
1616                 LS_64(ceq->tph_en, I40IW_CQPSQ_TPHEN) |
1617                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1618        i40iw_insert_wqe_hdr(wqe, header);
1619        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CEQ_DESTROY WQE",
1620                        wqe, I40IW_CQP_WQE_SIZE * 8);
1621
1622        if (post_sq)
1623                i40iw_sc_cqp_post_sq(cqp);
1624        return 0;
1625}
1626
1627/**
1628 * i40iw_sc_process_ceq - process ceq
1629 * @dev: sc device struct
1630 * @ceq: ceq sc structure
1631 */
1632static void *i40iw_sc_process_ceq(struct i40iw_sc_dev *dev, struct i40iw_sc_ceq *ceq)
1633{
1634        u64 temp;
1635        u64 *ceqe;
1636        struct i40iw_sc_cq *cq = NULL;
1637        u8 polarity;
1638
1639        ceqe = (u64 *)I40IW_GET_CURRENT_CEQ_ELEMENT(ceq);
1640        get_64bit_val(ceqe, 0, &temp);
1641        polarity = (u8)RS_64(temp, I40IW_CEQE_VALID);
1642        if (polarity != ceq->polarity)
1643                return cq;
1644
1645        cq = (struct i40iw_sc_cq *)(unsigned long)LS_64_1(temp, 1);
1646
1647        I40IW_RING_MOVE_TAIL(ceq->ceq_ring);
1648        if (I40IW_RING_GETCURRENT_TAIL(ceq->ceq_ring) == 0)
1649                ceq->polarity ^= 1;
1650
1651        if (dev->is_pf)
1652                i40iw_wr32(dev->hw, I40E_PFPE_CQACK, cq->cq_uk.cq_id);
1653        else
1654                i40iw_wr32(dev->hw, I40E_VFPE_CQACK1, cq->cq_uk.cq_id);
1655
1656        return cq;
1657}
1658
1659/**
1660 * i40iw_sc_aeq_init - initialize aeq
1661 * @aeq: aeq structure ptr
1662 * @info: aeq initialization info
1663 */
1664static enum i40iw_status_code i40iw_sc_aeq_init(struct i40iw_sc_aeq *aeq,
1665                                                struct i40iw_aeq_init_info *info)
1666{
1667        u32 pble_obj_cnt;
1668
1669        if ((info->elem_cnt < I40IW_MIN_AEQ_ENTRIES) ||
1670            (info->elem_cnt > I40IW_MAX_AEQ_ENTRIES))
1671                return I40IW_ERR_INVALID_SIZE;
1672        pble_obj_cnt = info->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
1673
1674        if (info->virtual_map && (info->first_pm_pbl_idx >= pble_obj_cnt))
1675                return I40IW_ERR_INVALID_PBLE_INDEX;
1676
1677        aeq->size = sizeof(*aeq);
1678        aeq->polarity = 1;
1679        aeq->aeqe_base = (struct i40iw_sc_aeqe *)info->aeqe_base;
1680        aeq->dev = info->dev;
1681        aeq->elem_cnt = info->elem_cnt;
1682
1683        aeq->aeq_elem_pa = info->aeq_elem_pa;
1684        I40IW_RING_INIT(aeq->aeq_ring, aeq->elem_cnt);
1685        info->dev->aeq = aeq;
1686
1687        aeq->virtual_map = info->virtual_map;
1688        aeq->pbl_list = (aeq->virtual_map ? info->pbl_list : NULL);
1689        aeq->pbl_chunk_size = (aeq->virtual_map ? info->pbl_chunk_size : 0);
1690        aeq->first_pm_pbl_idx = (aeq->virtual_map ? info->first_pm_pbl_idx : 0);
1691        info->dev->aeq = aeq;
1692        return 0;
1693}
1694
1695/**
1696 * i40iw_sc_aeq_create - create aeq
1697 * @aeq: aeq structure ptr
1698 * @scratch: u64 saved to be used during cqp completion
1699 * @post_sq: flag for cqp db to ring
1700 */
1701static enum i40iw_status_code i40iw_sc_aeq_create(struct i40iw_sc_aeq *aeq,
1702                                                  u64 scratch,
1703                                                  bool post_sq)
1704{
1705        u64 *wqe;
1706        struct i40iw_sc_cqp *cqp;
1707        u64 header;
1708
1709        cqp = aeq->dev->cqp;
1710        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1711        if (!wqe)
1712                return I40IW_ERR_RING_FULL;
1713        set_64bit_val(wqe, 16, aeq->elem_cnt);
1714        set_64bit_val(wqe, 32,
1715                      (aeq->virtual_map ? 0 : aeq->aeq_elem_pa));
1716        set_64bit_val(wqe, 48,
1717                      (aeq->virtual_map ? aeq->first_pm_pbl_idx : 0));
1718
1719        header = LS_64(I40IW_CQP_OP_CREATE_AEQ, I40IW_CQPSQ_OPCODE) |
1720                 LS_64(aeq->pbl_chunk_size, I40IW_CQPSQ_AEQ_LPBLSIZE) |
1721                 LS_64(aeq->virtual_map, I40IW_CQPSQ_AEQ_VMAP) |
1722                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1723
1724        i40iw_insert_wqe_hdr(wqe, header);
1725        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "AEQ_CREATE WQE",
1726                        wqe, I40IW_CQP_WQE_SIZE * 8);
1727        if (post_sq)
1728                i40iw_sc_cqp_post_sq(cqp);
1729        return 0;
1730}
1731
1732/**
1733 * i40iw_sc_aeq_destroy - destroy aeq during close
1734 * @aeq: aeq structure ptr
1735 * @scratch: u64 saved to be used during cqp completion
1736 * @post_sq: flag for cqp db to ring
1737 */
1738static enum i40iw_status_code i40iw_sc_aeq_destroy(struct i40iw_sc_aeq *aeq,
1739                                                   u64 scratch,
1740                                                   bool post_sq)
1741{
1742        u64 *wqe;
1743        struct i40iw_sc_cqp *cqp;
1744        u64 header;
1745
1746        cqp = aeq->dev->cqp;
1747        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1748        if (!wqe)
1749                return I40IW_ERR_RING_FULL;
1750        set_64bit_val(wqe, 16, aeq->elem_cnt);
1751        set_64bit_val(wqe, 48, aeq->first_pm_pbl_idx);
1752        header = LS_64(I40IW_CQP_OP_DESTROY_AEQ, I40IW_CQPSQ_OPCODE) |
1753                 LS_64(aeq->pbl_chunk_size, I40IW_CQPSQ_AEQ_LPBLSIZE) |
1754                 LS_64(aeq->virtual_map, I40IW_CQPSQ_AEQ_VMAP) |
1755                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
1756        i40iw_insert_wqe_hdr(wqe, header);
1757
1758        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "AEQ_DESTROY WQE",
1759                        wqe, I40IW_CQP_WQE_SIZE * 8);
1760        if (post_sq)
1761                i40iw_sc_cqp_post_sq(cqp);
1762        return 0;
1763}
1764
1765/**
1766 * i40iw_sc_get_next_aeqe - get next aeq entry
1767 * @aeq: aeq structure ptr
1768 * @info: aeqe info to be returned
1769 */
1770static enum i40iw_status_code i40iw_sc_get_next_aeqe(struct i40iw_sc_aeq *aeq,
1771                                                     struct i40iw_aeqe_info *info)
1772{
1773        u64 temp, compl_ctx;
1774        u64 *aeqe;
1775        u16 wqe_idx;
1776        u8 ae_src;
1777        u8 polarity;
1778
1779        aeqe = (u64 *)I40IW_GET_CURRENT_AEQ_ELEMENT(aeq);
1780        get_64bit_val(aeqe, 0, &compl_ctx);
1781        get_64bit_val(aeqe, 8, &temp);
1782        polarity = (u8)RS_64(temp, I40IW_AEQE_VALID);
1783
1784        if (aeq->polarity != polarity)
1785                return I40IW_ERR_QUEUE_EMPTY;
1786
1787        i40iw_debug_buf(aeq->dev, I40IW_DEBUG_WQE, "AEQ_ENTRY", aeqe, 16);
1788
1789        ae_src = (u8)RS_64(temp, I40IW_AEQE_AESRC);
1790        wqe_idx = (u16)RS_64(temp, I40IW_AEQE_WQDESCIDX);
1791        info->qp_cq_id = (u32)RS_64(temp, I40IW_AEQE_QPCQID);
1792        info->ae_id = (u16)RS_64(temp, I40IW_AEQE_AECODE);
1793        info->tcp_state = (u8)RS_64(temp, I40IW_AEQE_TCPSTATE);
1794        info->iwarp_state = (u8)RS_64(temp, I40IW_AEQE_IWSTATE);
1795        info->q2_data_written = (u8)RS_64(temp, I40IW_AEQE_Q2DATA);
1796        info->aeqe_overflow = (bool)RS_64(temp, I40IW_AEQE_OVERFLOW);
1797
1798        switch (info->ae_id) {
1799        case I40IW_AE_PRIV_OPERATION_DENIED:
1800        case I40IW_AE_UDA_XMIT_DGRAM_TOO_LONG:
1801        case I40IW_AE_UDA_XMIT_DGRAM_TOO_SHORT:
1802        case I40IW_AE_BAD_CLOSE:
1803        case I40IW_AE_RDMAP_ROE_BAD_LLP_CLOSE:
1804        case I40IW_AE_RDMA_READ_WHILE_ORD_ZERO:
1805        case I40IW_AE_STAG_ZERO_INVALID:
1806        case I40IW_AE_IB_RREQ_AND_Q1_FULL:
1807        case I40IW_AE_WQE_UNEXPECTED_OPCODE:
1808        case I40IW_AE_DDP_UBE_INVALID_DDP_VERSION:
1809        case I40IW_AE_DDP_UBE_INVALID_MO:
1810        case I40IW_AE_DDP_UBE_INVALID_QN:
1811        case I40IW_AE_DDP_NO_L_BIT:
1812        case I40IW_AE_RDMAP_ROE_INVALID_RDMAP_VERSION:
1813        case I40IW_AE_RDMAP_ROE_UNEXPECTED_OPCODE:
1814        case I40IW_AE_ROE_INVALID_RDMA_READ_REQUEST:
1815        case I40IW_AE_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
1816        case I40IW_AE_INVALID_ARP_ENTRY:
1817        case I40IW_AE_INVALID_TCP_OPTION_RCVD:
1818        case I40IW_AE_STALE_ARP_ENTRY:
1819        case I40IW_AE_LLP_CLOSE_COMPLETE:
1820        case I40IW_AE_LLP_CONNECTION_RESET:
1821        case I40IW_AE_LLP_FIN_RECEIVED:
1822        case I40IW_AE_LLP_RECEIVED_MPA_CRC_ERROR:
1823        case I40IW_AE_LLP_SEGMENT_TOO_SMALL:
1824        case I40IW_AE_LLP_SYN_RECEIVED:
1825        case I40IW_AE_LLP_TERMINATE_RECEIVED:
1826        case I40IW_AE_LLP_TOO_MANY_RETRIES:
1827        case I40IW_AE_LLP_DOUBT_REACHABILITY:
1828        case I40IW_AE_RESET_SENT:
1829        case I40IW_AE_TERMINATE_SENT:
1830        case I40IW_AE_RESET_NOT_SENT:
1831        case I40IW_AE_LCE_QP_CATASTROPHIC:
1832        case I40IW_AE_QP_SUSPEND_COMPLETE:
1833                info->qp = true;
1834                info->compl_ctx = compl_ctx;
1835                ae_src = I40IW_AE_SOURCE_RSVD;
1836                break;
1837        case I40IW_AE_LCE_CQ_CATASTROPHIC:
1838                info->cq = true;
1839                info->compl_ctx = LS_64_1(compl_ctx, 1);
1840                ae_src = I40IW_AE_SOURCE_RSVD;
1841                break;
1842        }
1843
1844        switch (ae_src) {
1845        case I40IW_AE_SOURCE_RQ:
1846        case I40IW_AE_SOURCE_RQ_0011:
1847                info->qp = true;
1848                info->wqe_idx = wqe_idx;
1849                info->compl_ctx = compl_ctx;
1850                break;
1851        case I40IW_AE_SOURCE_CQ:
1852        case I40IW_AE_SOURCE_CQ_0110:
1853        case I40IW_AE_SOURCE_CQ_1010:
1854        case I40IW_AE_SOURCE_CQ_1110:
1855                info->cq = true;
1856                info->compl_ctx = LS_64_1(compl_ctx, 1);
1857                break;
1858        case I40IW_AE_SOURCE_SQ:
1859        case I40IW_AE_SOURCE_SQ_0111:
1860                info->qp = true;
1861                info->sq = true;
1862                info->wqe_idx = wqe_idx;
1863                info->compl_ctx = compl_ctx;
1864                break;
1865        case I40IW_AE_SOURCE_IN_RR_WR:
1866        case I40IW_AE_SOURCE_IN_RR_WR_1011:
1867                info->qp = true;
1868                info->compl_ctx = compl_ctx;
1869                info->in_rdrsp_wr = true;
1870                break;
1871        case I40IW_AE_SOURCE_OUT_RR:
1872        case I40IW_AE_SOURCE_OUT_RR_1111:
1873                info->qp = true;
1874                info->compl_ctx = compl_ctx;
1875                info->out_rdrsp = true;
1876                break;
1877        case I40IW_AE_SOURCE_RSVD:
1878                /* fallthrough */
1879        default:
1880                break;
1881        }
1882        I40IW_RING_MOVE_TAIL(aeq->aeq_ring);
1883        if (I40IW_RING_GETCURRENT_TAIL(aeq->aeq_ring) == 0)
1884                aeq->polarity ^= 1;
1885        return 0;
1886}
1887
1888/**
1889 * i40iw_sc_repost_aeq_entries - repost completed aeq entries
1890 * @dev: sc device struct
1891 * @count: allocate count
1892 */
1893static enum i40iw_status_code i40iw_sc_repost_aeq_entries(struct i40iw_sc_dev *dev,
1894                                                          u32 count)
1895{
1896
1897        if (dev->is_pf)
1898                i40iw_wr32(dev->hw, I40E_PFPE_AEQALLOC, count);
1899        else
1900                i40iw_wr32(dev->hw, I40E_VFPE_AEQALLOC1, count);
1901
1902        return 0;
1903}
1904
1905/**
1906 * i40iw_sc_aeq_create_done - create aeq
1907 * @aeq: aeq structure ptr
1908 */
1909static enum i40iw_status_code i40iw_sc_aeq_create_done(struct i40iw_sc_aeq *aeq)
1910{
1911        struct i40iw_sc_cqp *cqp;
1912
1913        cqp = aeq->dev->cqp;
1914        return i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_CREATE_AEQ, NULL);
1915}
1916
1917/**
1918 * i40iw_sc_aeq_destroy_done - destroy of aeq during close
1919 * @aeq: aeq structure ptr
1920 */
1921static enum i40iw_status_code i40iw_sc_aeq_destroy_done(struct i40iw_sc_aeq *aeq)
1922{
1923        struct i40iw_sc_cqp *cqp;
1924
1925        cqp = aeq->dev->cqp;
1926        return  i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_DESTROY_AEQ, NULL);
1927}
1928
1929/**
1930 * i40iw_sc_ccq_init - initialize control cq
1931 * @cq: sc's cq ctruct
1932 * @info: info for control cq initialization
1933 */
1934static enum i40iw_status_code i40iw_sc_ccq_init(struct i40iw_sc_cq *cq,
1935                                                struct i40iw_ccq_init_info *info)
1936{
1937        u32 pble_obj_cnt;
1938
1939        if (info->num_elem < I40IW_MIN_CQ_SIZE || info->num_elem > I40IW_MAX_CQ_SIZE)
1940                return I40IW_ERR_INVALID_SIZE;
1941
1942        if (info->ceq_id > I40IW_MAX_CEQID)
1943                return I40IW_ERR_INVALID_CEQ_ID;
1944
1945        pble_obj_cnt = info->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
1946
1947        if (info->virtual_map && (info->first_pm_pbl_idx >= pble_obj_cnt))
1948                return I40IW_ERR_INVALID_PBLE_INDEX;
1949
1950        cq->cq_pa = info->cq_pa;
1951        cq->cq_uk.cq_base = info->cq_base;
1952        cq->shadow_area_pa = info->shadow_area_pa;
1953        cq->cq_uk.shadow_area = info->shadow_area;
1954        cq->shadow_read_threshold = info->shadow_read_threshold;
1955        cq->dev = info->dev;
1956        cq->ceq_id = info->ceq_id;
1957        cq->cq_uk.cq_size = info->num_elem;
1958        cq->cq_type = I40IW_CQ_TYPE_CQP;
1959        cq->ceqe_mask = info->ceqe_mask;
1960        I40IW_RING_INIT(cq->cq_uk.cq_ring, info->num_elem);
1961
1962        cq->cq_uk.cq_id = 0;    /* control cq is id 0 always */
1963        cq->ceq_id_valid = info->ceq_id_valid;
1964        cq->tph_en = info->tph_en;
1965        cq->tph_val = info->tph_val;
1966        cq->cq_uk.avoid_mem_cflct = info->avoid_mem_cflct;
1967
1968        cq->pbl_list = info->pbl_list;
1969        cq->virtual_map = info->virtual_map;
1970        cq->pbl_chunk_size = info->pbl_chunk_size;
1971        cq->first_pm_pbl_idx = info->first_pm_pbl_idx;
1972        cq->cq_uk.polarity = true;
1973
1974        /* following are only for iw cqs so initialize them to zero */
1975        cq->cq_uk.cqe_alloc_reg = NULL;
1976        info->dev->ccq = cq;
1977        return 0;
1978}
1979
1980/**
1981 * i40iw_sc_ccq_create_done - poll cqp for ccq create
1982 * @ccq: ccq sc struct
1983 */
1984static enum i40iw_status_code i40iw_sc_ccq_create_done(struct i40iw_sc_cq *ccq)
1985{
1986        struct i40iw_sc_cqp *cqp;
1987
1988        cqp = ccq->dev->cqp;
1989        return  i40iw_sc_poll_for_cqp_op_done(cqp, I40IW_CQP_OP_CREATE_CQ, NULL);
1990}
1991
1992/**
1993 * i40iw_sc_ccq_create - create control cq
1994 * @ccq: ccq sc struct
1995 * @scratch: u64 saved to be used during cqp completion
1996 * @check_overflow: overlow flag for ccq
1997 * @post_sq: flag for cqp db to ring
1998 */
1999static enum i40iw_status_code i40iw_sc_ccq_create(struct i40iw_sc_cq *ccq,
2000                                                  u64 scratch,
2001                                                  bool check_overflow,
2002                                                  bool post_sq)
2003{
2004        u64 *wqe;
2005        struct i40iw_sc_cqp *cqp;
2006        u64 header;
2007        enum i40iw_status_code ret_code;
2008
2009        cqp = ccq->dev->cqp;
2010        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2011        if (!wqe)
2012                return I40IW_ERR_RING_FULL;
2013        set_64bit_val(wqe, 0, ccq->cq_uk.cq_size);
2014        set_64bit_val(wqe, 8, RS_64_1(ccq, 1));
2015        set_64bit_val(wqe, 16,
2016                      LS_64(ccq->shadow_read_threshold, I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
2017        set_64bit_val(wqe, 32, (ccq->virtual_map ? 0 : ccq->cq_pa));
2018        set_64bit_val(wqe, 40, ccq->shadow_area_pa);
2019        set_64bit_val(wqe, 48,
2020                      (ccq->virtual_map ? ccq->first_pm_pbl_idx : 0));
2021        set_64bit_val(wqe, 56,
2022                      LS_64(ccq->tph_val, I40IW_CQPSQ_TPHVAL));
2023
2024        header = ccq->cq_uk.cq_id |
2025                 LS_64((ccq->ceq_id_valid ? ccq->ceq_id : 0), I40IW_CQPSQ_CQ_CEQID) |
2026                 LS_64(I40IW_CQP_OP_CREATE_CQ, I40IW_CQPSQ_OPCODE) |
2027                 LS_64(ccq->pbl_chunk_size, I40IW_CQPSQ_CQ_LPBLSIZE) |
2028                 LS_64(check_overflow, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
2029                 LS_64(ccq->virtual_map, I40IW_CQPSQ_CQ_VIRTMAP) |
2030                 LS_64(ccq->ceqe_mask, I40IW_CQPSQ_CQ_ENCEQEMASK) |
2031                 LS_64(ccq->ceq_id_valid, I40IW_CQPSQ_CQ_CEQIDVALID) |
2032                 LS_64(ccq->tph_en, I40IW_CQPSQ_TPHEN) |
2033                 LS_64(ccq->cq_uk.avoid_mem_cflct, I40IW_CQPSQ_CQ_AVOIDMEMCNFLCT) |
2034                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2035
2036        i40iw_insert_wqe_hdr(wqe, header);
2037
2038        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CCQ_CREATE WQE",
2039                        wqe, I40IW_CQP_WQE_SIZE * 8);
2040
2041        if (post_sq) {
2042                i40iw_sc_cqp_post_sq(cqp);
2043                ret_code = i40iw_sc_ccq_create_done(ccq);
2044                if (ret_code)
2045                        return ret_code;
2046        }
2047        cqp->process_cqp_sds = i40iw_cqp_sds_cmd;
2048
2049        return 0;
2050}
2051
2052/**
2053 * i40iw_sc_ccq_destroy - destroy ccq during close
2054 * @ccq: ccq sc struct
2055 * @scratch: u64 saved to be used during cqp completion
2056 * @post_sq: flag for cqp db to ring
2057 */
2058static enum i40iw_status_code i40iw_sc_ccq_destroy(struct i40iw_sc_cq *ccq,
2059                                                   u64 scratch,
2060                                                   bool post_sq)
2061{
2062        struct i40iw_sc_cqp *cqp;
2063        u64 *wqe;
2064        u64 header;
2065        enum i40iw_status_code ret_code = 0;
2066        u32 tail, val, error;
2067
2068        cqp = ccq->dev->cqp;
2069        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2070        if (!wqe)
2071                return I40IW_ERR_RING_FULL;
2072        set_64bit_val(wqe, 0, ccq->cq_uk.cq_size);
2073        set_64bit_val(wqe, 8, RS_64_1(ccq, 1));
2074        set_64bit_val(wqe, 40, ccq->shadow_area_pa);
2075
2076        header = ccq->cq_uk.cq_id |
2077                 LS_64((ccq->ceq_id_valid ? ccq->ceq_id : 0), I40IW_CQPSQ_CQ_CEQID) |
2078                 LS_64(I40IW_CQP_OP_DESTROY_CQ, I40IW_CQPSQ_OPCODE) |
2079                 LS_64(ccq->ceqe_mask, I40IW_CQPSQ_CQ_ENCEQEMASK) |
2080                 LS_64(ccq->ceq_id_valid, I40IW_CQPSQ_CQ_CEQIDVALID) |
2081                 LS_64(ccq->tph_en, I40IW_CQPSQ_TPHEN) |
2082                 LS_64(ccq->cq_uk.avoid_mem_cflct, I40IW_CQPSQ_CQ_AVOIDMEMCNFLCT) |
2083                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2084
2085        i40iw_insert_wqe_hdr(wqe, header);
2086
2087        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CCQ_DESTROY WQE",
2088                        wqe, I40IW_CQP_WQE_SIZE * 8);
2089
2090        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
2091        if (error)
2092                return I40IW_ERR_CQP_COMPL_ERROR;
2093
2094        if (post_sq) {
2095                i40iw_sc_cqp_post_sq(cqp);
2096                ret_code = i40iw_cqp_poll_registers(cqp, tail, 1000);
2097        }
2098
2099        cqp->process_cqp_sds = i40iw_update_sds_noccq;
2100
2101        return ret_code;
2102}
2103
2104/**
2105 * i40iw_sc_cq_init - initialize completion q
2106 * @cq: cq struct
2107 * @info: cq initialization info
2108 */
2109static enum i40iw_status_code i40iw_sc_cq_init(struct i40iw_sc_cq *cq,
2110                                               struct i40iw_cq_init_info *info)
2111{
2112        u32 __iomem *cqe_alloc_reg = NULL;
2113        enum i40iw_status_code ret_code;
2114        u32 pble_obj_cnt;
2115        u32 arm_offset;
2116
2117        pble_obj_cnt = info->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
2118
2119        if (info->virtual_map && (info->first_pm_pbl_idx >= pble_obj_cnt))
2120                return I40IW_ERR_INVALID_PBLE_INDEX;
2121
2122        cq->cq_pa = info->cq_base_pa;
2123        cq->dev = info->dev;
2124        cq->ceq_id = info->ceq_id;
2125        arm_offset = (info->dev->is_pf) ? I40E_PFPE_CQARM : I40E_VFPE_CQARM1;
2126        if (i40iw_get_hw_addr(cq->dev))
2127                cqe_alloc_reg = (u32 __iomem *)(i40iw_get_hw_addr(cq->dev) +
2128                                              arm_offset);
2129        info->cq_uk_init_info.cqe_alloc_reg = cqe_alloc_reg;
2130        ret_code = i40iw_cq_uk_init(&cq->cq_uk, &info->cq_uk_init_info);
2131        if (ret_code)
2132                return ret_code;
2133        cq->virtual_map = info->virtual_map;
2134        cq->pbl_chunk_size = info->pbl_chunk_size;
2135        cq->ceqe_mask = info->ceqe_mask;
2136        cq->cq_type = (info->type) ? info->type : I40IW_CQ_TYPE_IWARP;
2137
2138        cq->shadow_area_pa = info->shadow_area_pa;
2139        cq->shadow_read_threshold = info->shadow_read_threshold;
2140
2141        cq->ceq_id_valid = info->ceq_id_valid;
2142        cq->tph_en = info->tph_en;
2143        cq->tph_val = info->tph_val;
2144
2145        cq->first_pm_pbl_idx = info->first_pm_pbl_idx;
2146
2147        return 0;
2148}
2149
2150/**
2151 * i40iw_sc_cq_create - create completion q
2152 * @cq: cq struct
2153 * @scratch: u64 saved to be used during cqp completion
2154 * @check_overflow: flag for overflow check
2155 * @post_sq: flag for cqp db to ring
2156 */
2157static enum i40iw_status_code i40iw_sc_cq_create(struct i40iw_sc_cq *cq,
2158                                                 u64 scratch,
2159                                                 bool check_overflow,
2160                                                 bool post_sq)
2161{
2162        u64 *wqe;
2163        struct i40iw_sc_cqp *cqp;
2164        u64 header;
2165
2166        if (cq->cq_uk.cq_id > I40IW_MAX_CQID)
2167                return I40IW_ERR_INVALID_CQ_ID;
2168
2169        if (cq->ceq_id > I40IW_MAX_CEQID)
2170                return I40IW_ERR_INVALID_CEQ_ID;
2171
2172        cqp = cq->dev->cqp;
2173        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2174        if (!wqe)
2175                return I40IW_ERR_RING_FULL;
2176
2177        set_64bit_val(wqe, 0, cq->cq_uk.cq_size);
2178        set_64bit_val(wqe, 8, RS_64_1(cq, 1));
2179        set_64bit_val(wqe,
2180                      16,
2181                      LS_64(cq->shadow_read_threshold, I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
2182
2183        set_64bit_val(wqe, 32, (cq->virtual_map ? 0 : cq->cq_pa));
2184
2185        set_64bit_val(wqe, 40, cq->shadow_area_pa);
2186        set_64bit_val(wqe, 48, (cq->virtual_map ? cq->first_pm_pbl_idx : 0));
2187        set_64bit_val(wqe, 56, LS_64(cq->tph_val, I40IW_CQPSQ_TPHVAL));
2188
2189        header = cq->cq_uk.cq_id |
2190                 LS_64((cq->ceq_id_valid ? cq->ceq_id : 0), I40IW_CQPSQ_CQ_CEQID) |
2191                 LS_64(I40IW_CQP_OP_CREATE_CQ, I40IW_CQPSQ_OPCODE) |
2192                 LS_64(cq->pbl_chunk_size, I40IW_CQPSQ_CQ_LPBLSIZE) |
2193                 LS_64(check_overflow, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
2194                 LS_64(cq->virtual_map, I40IW_CQPSQ_CQ_VIRTMAP) |
2195                 LS_64(cq->ceqe_mask, I40IW_CQPSQ_CQ_ENCEQEMASK) |
2196                 LS_64(cq->ceq_id_valid, I40IW_CQPSQ_CQ_CEQIDVALID) |
2197                 LS_64(cq->tph_en, I40IW_CQPSQ_TPHEN) |
2198                 LS_64(cq->cq_uk.avoid_mem_cflct, I40IW_CQPSQ_CQ_AVOIDMEMCNFLCT) |
2199                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2200
2201        i40iw_insert_wqe_hdr(wqe, header);
2202
2203        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CQ_CREATE WQE",
2204                        wqe, I40IW_CQP_WQE_SIZE * 8);
2205
2206        if (post_sq)
2207                i40iw_sc_cqp_post_sq(cqp);
2208        return 0;
2209}
2210
2211/**
2212 * i40iw_sc_cq_destroy - destroy completion q
2213 * @cq: cq struct
2214 * @scratch: u64 saved to be used during cqp completion
2215 * @post_sq: flag for cqp db to ring
2216 */
2217static enum i40iw_status_code i40iw_sc_cq_destroy(struct i40iw_sc_cq *cq,
2218                                                  u64 scratch,
2219                                                  bool post_sq)
2220{
2221        struct i40iw_sc_cqp *cqp;
2222        u64 *wqe;
2223        u64 header;
2224
2225        cqp = cq->dev->cqp;
2226        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2227        if (!wqe)
2228                return I40IW_ERR_RING_FULL;
2229        set_64bit_val(wqe, 0, cq->cq_uk.cq_size);
2230        set_64bit_val(wqe, 8, RS_64_1(cq, 1));
2231        set_64bit_val(wqe, 40, cq->shadow_area_pa);
2232        set_64bit_val(wqe, 48, (cq->virtual_map ? cq->first_pm_pbl_idx : 0));
2233
2234        header = cq->cq_uk.cq_id |
2235                 LS_64((cq->ceq_id_valid ? cq->ceq_id : 0), I40IW_CQPSQ_CQ_CEQID) |
2236                 LS_64(I40IW_CQP_OP_DESTROY_CQ, I40IW_CQPSQ_OPCODE) |
2237                 LS_64(cq->pbl_chunk_size, I40IW_CQPSQ_CQ_LPBLSIZE) |
2238                 LS_64(cq->virtual_map, I40IW_CQPSQ_CQ_VIRTMAP) |
2239                 LS_64(cq->ceqe_mask, I40IW_CQPSQ_CQ_ENCEQEMASK) |
2240                 LS_64(cq->ceq_id_valid, I40IW_CQPSQ_CQ_CEQIDVALID) |
2241                 LS_64(cq->tph_en, I40IW_CQPSQ_TPHEN) |
2242                 LS_64(cq->cq_uk.avoid_mem_cflct, I40IW_CQPSQ_CQ_AVOIDMEMCNFLCT) |
2243                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2244
2245        i40iw_insert_wqe_hdr(wqe, header);
2246
2247        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CQ_DESTROY WQE",
2248                        wqe, I40IW_CQP_WQE_SIZE * 8);
2249
2250        if (post_sq)
2251                i40iw_sc_cqp_post_sq(cqp);
2252        return 0;
2253}
2254
2255/**
2256 * i40iw_sc_cq_modify - modify a Completion Queue
2257 * @cq: cq struct
2258 * @info: modification info struct
2259 * @scratch:
2260 * @post_sq: flag to post to sq
2261 */
2262static enum i40iw_status_code i40iw_sc_cq_modify(struct i40iw_sc_cq *cq,
2263                                                 struct i40iw_modify_cq_info *info,
2264                                                 u64 scratch,
2265                                                 bool post_sq)
2266{
2267        struct i40iw_sc_cqp *cqp;
2268        u64 *wqe;
2269        u64 header;
2270        u32 cq_size, ceq_id, first_pm_pbl_idx;
2271        u8 pbl_chunk_size;
2272        bool virtual_map, ceq_id_valid, check_overflow;
2273        u32 pble_obj_cnt;
2274
2275        if (info->ceq_valid && (info->ceq_id > I40IW_MAX_CEQID))
2276                return I40IW_ERR_INVALID_CEQ_ID;
2277
2278        pble_obj_cnt = cq->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
2279
2280        if (info->cq_resize && info->virtual_map &&
2281            (info->first_pm_pbl_idx >= pble_obj_cnt))
2282                return I40IW_ERR_INVALID_PBLE_INDEX;
2283
2284        cqp = cq->dev->cqp;
2285        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2286        if (!wqe)
2287                return I40IW_ERR_RING_FULL;
2288
2289        cq->pbl_list = info->pbl_list;
2290        cq->cq_pa = info->cq_pa;
2291        cq->first_pm_pbl_idx = info->first_pm_pbl_idx;
2292
2293        cq_size = info->cq_resize ? info->cq_size : cq->cq_uk.cq_size;
2294        if (info->ceq_change) {
2295                ceq_id_valid = true;
2296                ceq_id = info->ceq_id;
2297        } else {
2298                ceq_id_valid = cq->ceq_id_valid;
2299                ceq_id = ceq_id_valid ? cq->ceq_id : 0;
2300        }
2301        virtual_map = info->cq_resize ? info->virtual_map : cq->virtual_map;
2302        first_pm_pbl_idx = (info->cq_resize ?
2303                            (info->virtual_map ? info->first_pm_pbl_idx : 0) :
2304                            (cq->virtual_map ? cq->first_pm_pbl_idx : 0));
2305        pbl_chunk_size = (info->cq_resize ?
2306                          (info->virtual_map ? info->pbl_chunk_size : 0) :
2307                          (cq->virtual_map ? cq->pbl_chunk_size : 0));
2308        check_overflow = info->check_overflow_change ? info->check_overflow :
2309                         cq->check_overflow;
2310        cq->cq_uk.cq_size = cq_size;
2311        cq->ceq_id_valid = ceq_id_valid;
2312        cq->ceq_id = ceq_id;
2313        cq->virtual_map = virtual_map;
2314        cq->first_pm_pbl_idx = first_pm_pbl_idx;
2315        cq->pbl_chunk_size = pbl_chunk_size;
2316        cq->check_overflow = check_overflow;
2317
2318        set_64bit_val(wqe, 0, cq_size);
2319        set_64bit_val(wqe, 8, RS_64_1(cq, 1));
2320        set_64bit_val(wqe, 16,
2321                      LS_64(info->shadow_read_threshold, I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
2322        set_64bit_val(wqe, 32, (cq->virtual_map ? 0 : cq->cq_pa));
2323        set_64bit_val(wqe, 40, cq->shadow_area_pa);
2324        set_64bit_val(wqe, 48, (cq->virtual_map ? first_pm_pbl_idx : 0));
2325        set_64bit_val(wqe, 56, LS_64(cq->tph_val, I40IW_CQPSQ_TPHVAL));
2326
2327        header = cq->cq_uk.cq_id |
2328                 LS_64(ceq_id, I40IW_CQPSQ_CQ_CEQID) |
2329                 LS_64(I40IW_CQP_OP_MODIFY_CQ, I40IW_CQPSQ_OPCODE) |
2330                 LS_64(info->cq_resize, I40IW_CQPSQ_CQ_CQRESIZE) |
2331                 LS_64(pbl_chunk_size, I40IW_CQPSQ_CQ_LPBLSIZE) |
2332                 LS_64(check_overflow, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
2333                 LS_64(virtual_map, I40IW_CQPSQ_CQ_VIRTMAP) |
2334                 LS_64(cq->ceqe_mask, I40IW_CQPSQ_CQ_ENCEQEMASK) |
2335                 LS_64(ceq_id_valid, I40IW_CQPSQ_CQ_CEQIDVALID) |
2336                 LS_64(cq->tph_en, I40IW_CQPSQ_TPHEN) |
2337                 LS_64(cq->cq_uk.avoid_mem_cflct, I40IW_CQPSQ_CQ_AVOIDMEMCNFLCT) |
2338                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2339
2340        i40iw_insert_wqe_hdr(wqe, header);
2341
2342        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "CQ_MODIFY WQE",
2343                        wqe, I40IW_CQP_WQE_SIZE * 8);
2344
2345        if (post_sq)
2346                i40iw_sc_cqp_post_sq(cqp);
2347        return 0;
2348}
2349
2350/**
2351 * i40iw_sc_qp_init - initialize qp
2352 * @qp: sc qp
2353 * @info: initialization qp info
2354 */
2355static enum i40iw_status_code i40iw_sc_qp_init(struct i40iw_sc_qp *qp,
2356                                               struct i40iw_qp_init_info *info)
2357{
2358        u32 __iomem *wqe_alloc_reg = NULL;
2359        enum i40iw_status_code ret_code;
2360        u32 pble_obj_cnt;
2361        u8 wqe_size;
2362        u32 offset;
2363
2364        qp->dev = info->pd->dev;
2365        qp->vsi = info->vsi;
2366        qp->sq_pa = info->sq_pa;
2367        qp->rq_pa = info->rq_pa;
2368        qp->hw_host_ctx_pa = info->host_ctx_pa;
2369        qp->q2_pa = info->q2_pa;
2370        qp->shadow_area_pa = info->shadow_area_pa;
2371
2372        qp->q2_buf = info->q2;
2373        qp->pd = info->pd;
2374        qp->hw_host_ctx = info->host_ctx;
2375        offset = (qp->pd->dev->is_pf) ? I40E_PFPE_WQEALLOC : I40E_VFPE_WQEALLOC1;
2376        if (i40iw_get_hw_addr(qp->pd->dev))
2377                wqe_alloc_reg = (u32 __iomem *)(i40iw_get_hw_addr(qp->pd->dev) +
2378                                              offset);
2379
2380        info->qp_uk_init_info.wqe_alloc_reg = wqe_alloc_reg;
2381        info->qp_uk_init_info.abi_ver = qp->pd->abi_ver;
2382        ret_code = i40iw_qp_uk_init(&qp->qp_uk, &info->qp_uk_init_info);
2383        if (ret_code)
2384                return ret_code;
2385        qp->virtual_map = info->virtual_map;
2386
2387        pble_obj_cnt = info->pd->dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
2388
2389        if ((info->virtual_map && (info->sq_pa >= pble_obj_cnt)) ||
2390            (info->virtual_map && (info->rq_pa >= pble_obj_cnt)))
2391                return I40IW_ERR_INVALID_PBLE_INDEX;
2392
2393        qp->llp_stream_handle = (void *)(-1);
2394        qp->qp_type = (info->type) ? info->type : I40IW_QP_TYPE_IWARP;
2395
2396        qp->hw_sq_size = i40iw_get_encoded_wqe_size(qp->qp_uk.sq_ring.size,
2397                                                    false);
2398        i40iw_debug(qp->dev, I40IW_DEBUG_WQE, "%s: hw_sq_size[%04d] sq_ring.size[%04d]\n",
2399                    __func__, qp->hw_sq_size, qp->qp_uk.sq_ring.size);
2400
2401        switch (qp->pd->abi_ver) {
2402        case 4:
2403                ret_code = i40iw_fragcnt_to_wqesize_rq(qp->qp_uk.max_rq_frag_cnt,
2404                                                       &wqe_size);
2405                if (ret_code)
2406                        return ret_code;
2407                break;
2408        case 5: /* fallthrough until next ABI version */
2409        default:
2410                if (qp->qp_uk.max_rq_frag_cnt > I40IW_MAX_WQ_FRAGMENT_COUNT)
2411                        return I40IW_ERR_INVALID_FRAG_COUNT;
2412                wqe_size = I40IW_MAX_WQE_SIZE_RQ;
2413                break;
2414        }
2415        qp->hw_rq_size = i40iw_get_encoded_wqe_size(qp->qp_uk.rq_size *
2416                                (wqe_size / I40IW_QP_WQE_MIN_SIZE), false);
2417        i40iw_debug(qp->dev, I40IW_DEBUG_WQE,
2418                    "%s: hw_rq_size[%04d] qp_uk.rq_size[%04d] wqe_size[%04d]\n",
2419                    __func__, qp->hw_rq_size, qp->qp_uk.rq_size, wqe_size);
2420        qp->sq_tph_val = info->sq_tph_val;
2421        qp->rq_tph_val = info->rq_tph_val;
2422        qp->sq_tph_en = info->sq_tph_en;
2423        qp->rq_tph_en = info->rq_tph_en;
2424        qp->rcv_tph_en = info->rcv_tph_en;
2425        qp->xmit_tph_en = info->xmit_tph_en;
2426        qp->qs_handle = qp->vsi->qos[qp->user_pri].qs_handle;
2427
2428        return 0;
2429}
2430
2431/**
2432 * i40iw_sc_qp_create - create qp
2433 * @qp: sc qp
2434 * @info: qp create info
2435 * @scratch: u64 saved to be used during cqp completion
2436 * @post_sq: flag for cqp db to ring
2437 */
2438static enum i40iw_status_code i40iw_sc_qp_create(
2439                                struct i40iw_sc_qp *qp,
2440                                struct i40iw_create_qp_info *info,
2441                                u64 scratch,
2442                                bool post_sq)
2443{
2444        struct i40iw_sc_cqp *cqp;
2445        u64 *wqe;
2446        u64 header;
2447
2448        if ((qp->qp_uk.qp_id < I40IW_MIN_IW_QP_ID) ||
2449            (qp->qp_uk.qp_id > I40IW_MAX_IW_QP_ID))
2450                return I40IW_ERR_INVALID_QP_ID;
2451
2452        cqp = qp->pd->dev->cqp;
2453        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2454        if (!wqe)
2455                return I40IW_ERR_RING_FULL;
2456
2457        set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
2458
2459        set_64bit_val(wqe, 40, qp->shadow_area_pa);
2460
2461        header = qp->qp_uk.qp_id |
2462                 LS_64(I40IW_CQP_OP_CREATE_QP, I40IW_CQPSQ_OPCODE) |
2463                 LS_64((info->ord_valid ? 1 : 0), I40IW_CQPSQ_QP_ORDVALID) |
2464                 LS_64(info->tcp_ctx_valid, I40IW_CQPSQ_QP_TOECTXVALID) |
2465                 LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) |
2466                 LS_64(qp->virtual_map, I40IW_CQPSQ_QP_VQ) |
2467                 LS_64(info->cq_num_valid, I40IW_CQPSQ_QP_CQNUMVALID) |
2468                 LS_64(info->arp_cache_idx_valid, I40IW_CQPSQ_QP_ARPTABIDXVALID) |
2469                 LS_64(info->next_iwarp_state, I40IW_CQPSQ_QP_NEXTIWSTATE) |
2470                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2471
2472        i40iw_insert_wqe_hdr(wqe, header);
2473        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QP_CREATE WQE",
2474                        wqe, I40IW_CQP_WQE_SIZE * 8);
2475
2476        if (post_sq)
2477                i40iw_sc_cqp_post_sq(cqp);
2478        return 0;
2479}
2480
2481/**
2482 * i40iw_sc_qp_modify - modify qp cqp wqe
2483 * @qp: sc qp
2484 * @info: modify qp info
2485 * @scratch: u64 saved to be used during cqp completion
2486 * @post_sq: flag for cqp db to ring
2487 */
2488static enum i40iw_status_code i40iw_sc_qp_modify(
2489                                struct i40iw_sc_qp *qp,
2490                                struct i40iw_modify_qp_info *info,
2491                                u64 scratch,
2492                                bool post_sq)
2493{
2494        u64 *wqe;
2495        struct i40iw_sc_cqp *cqp;
2496        u64 header;
2497        u8 term_actions = 0;
2498        u8 term_len = 0;
2499
2500        cqp = qp->pd->dev->cqp;
2501        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2502        if (!wqe)
2503                return I40IW_ERR_RING_FULL;
2504        if (info->next_iwarp_state == I40IW_QP_STATE_TERMINATE) {
2505                if (info->dont_send_fin)
2506                        term_actions += I40IWQP_TERM_SEND_TERM_ONLY;
2507                if (info->dont_send_term)
2508                        term_actions += I40IWQP_TERM_SEND_FIN_ONLY;
2509                if ((term_actions == I40IWQP_TERM_SEND_TERM_AND_FIN) ||
2510                    (term_actions == I40IWQP_TERM_SEND_TERM_ONLY))
2511                        term_len = info->termlen;
2512        }
2513
2514        set_64bit_val(wqe,
2515                      8,
2516                      LS_64(term_len, I40IW_CQPSQ_QP_TERMLEN));
2517
2518        set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
2519        set_64bit_val(wqe, 40, qp->shadow_area_pa);
2520
2521        header = qp->qp_uk.qp_id |
2522                 LS_64(I40IW_CQP_OP_MODIFY_QP, I40IW_CQPSQ_OPCODE) |
2523                 LS_64(info->ord_valid, I40IW_CQPSQ_QP_ORDVALID) |
2524                 LS_64(info->tcp_ctx_valid, I40IW_CQPSQ_QP_TOECTXVALID) |
2525                 LS_64(info->cached_var_valid, I40IW_CQPSQ_QP_CACHEDVARVALID) |
2526                 LS_64(qp->virtual_map, I40IW_CQPSQ_QP_VQ) |
2527                 LS_64(info->cq_num_valid, I40IW_CQPSQ_QP_CQNUMVALID) |
2528                 LS_64(info->force_loopback, I40IW_CQPSQ_QP_FORCELOOPBACK) |
2529                 LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) |
2530                 LS_64(info->remove_hash_idx, I40IW_CQPSQ_QP_REMOVEHASHENTRY) |
2531                 LS_64(term_actions, I40IW_CQPSQ_QP_TERMACT) |
2532                 LS_64(info->reset_tcp_conn, I40IW_CQPSQ_QP_RESETCON) |
2533                 LS_64(info->arp_cache_idx_valid, I40IW_CQPSQ_QP_ARPTABIDXVALID) |
2534                 LS_64(info->next_iwarp_state, I40IW_CQPSQ_QP_NEXTIWSTATE) |
2535                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2536
2537        i40iw_insert_wqe_hdr(wqe, header);
2538
2539        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QP_MODIFY WQE",
2540                        wqe, I40IW_CQP_WQE_SIZE * 8);
2541
2542        if (post_sq)
2543                i40iw_sc_cqp_post_sq(cqp);
2544        return 0;
2545}
2546
2547/**
2548 * i40iw_sc_qp_destroy - cqp destroy qp
2549 * @qp: sc qp
2550 * @scratch: u64 saved to be used during cqp completion
2551 * @remove_hash_idx: flag if to remove hash idx
2552 * @ignore_mw_bnd: memory window bind flag
2553 * @post_sq: flag for cqp db to ring
2554 */
2555static enum i40iw_status_code i40iw_sc_qp_destroy(
2556                                        struct i40iw_sc_qp *qp,
2557                                        u64 scratch,
2558                                        bool remove_hash_idx,
2559                                        bool ignore_mw_bnd,
2560                                        bool post_sq)
2561{
2562        u64 *wqe;
2563        struct i40iw_sc_cqp *cqp;
2564        u64 header;
2565
2566        i40iw_qp_rem_qos(qp);
2567        cqp = qp->pd->dev->cqp;
2568        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2569        if (!wqe)
2570                return I40IW_ERR_RING_FULL;
2571        set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
2572        set_64bit_val(wqe, 40, qp->shadow_area_pa);
2573
2574        header = qp->qp_uk.qp_id |
2575                 LS_64(I40IW_CQP_OP_DESTROY_QP, I40IW_CQPSQ_OPCODE) |
2576                 LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) |
2577                 LS_64(ignore_mw_bnd, I40IW_CQPSQ_QP_IGNOREMWBOUND) |
2578                 LS_64(remove_hash_idx, I40IW_CQPSQ_QP_REMOVEHASHENTRY) |
2579                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2580
2581        i40iw_insert_wqe_hdr(wqe, header);
2582        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QP_DESTROY WQE",
2583                        wqe, I40IW_CQP_WQE_SIZE * 8);
2584
2585        if (post_sq)
2586                i40iw_sc_cqp_post_sq(cqp);
2587        return 0;
2588}
2589
2590/**
2591 * i40iw_sc_qp_flush_wqes - flush qp's wqe
2592 * @qp: sc qp
2593 * @info: dlush information
2594 * @scratch: u64 saved to be used during cqp completion
2595 * @post_sq: flag for cqp db to ring
2596 */
2597static enum i40iw_status_code i40iw_sc_qp_flush_wqes(
2598                                struct i40iw_sc_qp *qp,
2599                                struct i40iw_qp_flush_info *info,
2600                                u64 scratch,
2601                                bool post_sq)
2602{
2603        u64 temp = 0;
2604        u64 *wqe;
2605        struct i40iw_sc_cqp *cqp;
2606        u64 header;
2607        bool flush_sq = false, flush_rq = false;
2608
2609        if (info->rq && !qp->flush_rq)
2610                flush_rq = true;
2611
2612        if (info->sq && !qp->flush_sq)
2613                flush_sq = true;
2614
2615        qp->flush_sq |= flush_sq;
2616        qp->flush_rq |= flush_rq;
2617        if (!flush_sq && !flush_rq)
2618                return 0;
2619
2620        cqp = qp->pd->dev->cqp;
2621        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2622        if (!wqe)
2623                return I40IW_ERR_RING_FULL;
2624        if (info->userflushcode) {
2625                if (flush_rq) {
2626                        temp |= LS_64(info->rq_minor_code, I40IW_CQPSQ_FWQE_RQMNERR) |
2627                                LS_64(info->rq_major_code, I40IW_CQPSQ_FWQE_RQMJERR);
2628                }
2629                if (flush_sq) {
2630                        temp |= LS_64(info->sq_minor_code, I40IW_CQPSQ_FWQE_SQMNERR) |
2631                                LS_64(info->sq_major_code, I40IW_CQPSQ_FWQE_SQMJERR);
2632                }
2633        }
2634        set_64bit_val(wqe, 16, temp);
2635
2636        temp = (info->generate_ae) ?
2637                info->ae_code | LS_64(info->ae_source, I40IW_CQPSQ_FWQE_AESOURCE) : 0;
2638
2639        set_64bit_val(wqe, 8, temp);
2640
2641        header = qp->qp_uk.qp_id |
2642                 LS_64(I40IW_CQP_OP_FLUSH_WQES, I40IW_CQPSQ_OPCODE) |
2643                 LS_64(info->generate_ae, I40IW_CQPSQ_FWQE_GENERATE_AE) |
2644                 LS_64(info->userflushcode, I40IW_CQPSQ_FWQE_USERFLCODE) |
2645                 LS_64(flush_sq, I40IW_CQPSQ_FWQE_FLUSHSQ) |
2646                 LS_64(flush_rq, I40IW_CQPSQ_FWQE_FLUSHRQ) |
2647                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2648
2649        i40iw_insert_wqe_hdr(wqe, header);
2650
2651        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "QP_FLUSH WQE",
2652                        wqe, I40IW_CQP_WQE_SIZE * 8);
2653
2654        if (post_sq)
2655                i40iw_sc_cqp_post_sq(cqp);
2656        return 0;
2657}
2658
2659/**
2660 * i40iw_sc_gen_ae - generate AE, currently uses flush WQE CQP OP
2661 * @qp: sc qp
2662 * @info: gen ae information
2663 * @scratch: u64 saved to be used during cqp completion
2664 * @post_sq: flag for cqp db to ring
2665 */
2666static enum i40iw_status_code i40iw_sc_gen_ae(
2667                                struct i40iw_sc_qp *qp,
2668                                struct i40iw_gen_ae_info *info,
2669                                u64 scratch,
2670                                bool post_sq)
2671{
2672        u64 temp;
2673        u64 *wqe;
2674        struct i40iw_sc_cqp *cqp;
2675        u64 header;
2676
2677        cqp = qp->pd->dev->cqp;
2678        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2679        if (!wqe)
2680                return I40IW_ERR_RING_FULL;
2681
2682        temp = info->ae_code |
2683               LS_64(info->ae_source, I40IW_CQPSQ_FWQE_AESOURCE);
2684
2685        set_64bit_val(wqe, 8, temp);
2686
2687        header = qp->qp_uk.qp_id |
2688                 LS_64(I40IW_CQP_OP_GEN_AE, I40IW_CQPSQ_OPCODE) |
2689                 LS_64(1, I40IW_CQPSQ_FWQE_GENERATE_AE) |
2690                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2691
2692        i40iw_insert_wqe_hdr(wqe, header);
2693
2694        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "GEN_AE WQE",
2695                        wqe, I40IW_CQP_WQE_SIZE * 8);
2696
2697        if (post_sq)
2698                i40iw_sc_cqp_post_sq(cqp);
2699        return 0;
2700}
2701
2702/**
2703 * i40iw_sc_qp_upload_context - upload qp's context
2704 * @dev: sc device struct
2705 * @info: upload context info ptr for return
2706 * @scratch: u64 saved to be used during cqp completion
2707 * @post_sq: flag for cqp db to ring
2708 */
2709static enum i40iw_status_code i40iw_sc_qp_upload_context(
2710                                        struct i40iw_sc_dev *dev,
2711                                        struct i40iw_upload_context_info *info,
2712                                        u64 scratch,
2713                                        bool post_sq)
2714{
2715        u64 *wqe;
2716        struct i40iw_sc_cqp *cqp;
2717        u64 header;
2718
2719        cqp = dev->cqp;
2720        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2721        if (!wqe)
2722                return I40IW_ERR_RING_FULL;
2723        set_64bit_val(wqe, 16, info->buf_pa);
2724
2725        header = LS_64(info->qp_id, I40IW_CQPSQ_UCTX_QPID) |
2726                 LS_64(I40IW_CQP_OP_UPLOAD_CONTEXT, I40IW_CQPSQ_OPCODE) |
2727                 LS_64(info->qp_type, I40IW_CQPSQ_UCTX_QPTYPE) |
2728                 LS_64(info->raw_format, I40IW_CQPSQ_UCTX_RAWFORMAT) |
2729                 LS_64(info->freeze_qp, I40IW_CQPSQ_UCTX_FREEZEQP) |
2730                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2731
2732        i40iw_insert_wqe_hdr(wqe, header);
2733
2734        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "QP_UPLOAD_CTX WQE",
2735                        wqe, I40IW_CQP_WQE_SIZE * 8);
2736
2737        if (post_sq)
2738                i40iw_sc_cqp_post_sq(cqp);
2739        return 0;
2740}
2741
2742/**
2743 * i40iw_sc_qp_setctx - set qp's context
2744 * @qp: sc qp
2745 * @qp_ctx: context ptr
2746 * @info: ctx info
2747 */
2748static enum i40iw_status_code i40iw_sc_qp_setctx(
2749                                struct i40iw_sc_qp *qp,
2750                                u64 *qp_ctx,
2751                                struct i40iw_qp_host_ctx_info *info)
2752{
2753        struct i40iwarp_offload_info *iw;
2754        struct i40iw_tcp_offload_info *tcp;
2755        struct i40iw_sc_vsi *vsi;
2756        struct i40iw_sc_dev *dev;
2757        u64 qw0, qw3, qw7 = 0;
2758
2759        iw = info->iwarp_info;
2760        tcp = info->tcp_info;
2761        vsi = qp->vsi;
2762        dev = qp->dev;
2763        if (info->add_to_qoslist) {
2764                qp->user_pri = info->user_pri;
2765                i40iw_qp_add_qos(qp);
2766                i40iw_debug(qp->dev, I40IW_DEBUG_DCB, "%s qp[%d] UP[%d] qset[%d]\n",
2767                            __func__, qp->qp_uk.qp_id, qp->user_pri, qp->qs_handle);
2768        }
2769        qw0 = LS_64(qp->qp_uk.rq_wqe_size, I40IWQPC_RQWQESIZE) |
2770              LS_64(info->err_rq_idx_valid, I40IWQPC_ERR_RQ_IDX_VALID) |
2771              LS_64(qp->rcv_tph_en, I40IWQPC_RCVTPHEN) |
2772              LS_64(qp->xmit_tph_en, I40IWQPC_XMITTPHEN) |
2773              LS_64(qp->rq_tph_en, I40IWQPC_RQTPHEN) |
2774              LS_64(qp->sq_tph_en, I40IWQPC_SQTPHEN) |
2775              LS_64(info->push_idx, I40IWQPC_PPIDX) |
2776              LS_64(info->push_mode_en, I40IWQPC_PMENA);
2777
2778        set_64bit_val(qp_ctx, 8, qp->sq_pa);
2779        set_64bit_val(qp_ctx, 16, qp->rq_pa);
2780
2781        qw3 = LS_64(qp->src_mac_addr_idx, I40IWQPC_SRCMACADDRIDX) |
2782              LS_64(qp->hw_rq_size, I40IWQPC_RQSIZE) |
2783              LS_64(qp->hw_sq_size, I40IWQPC_SQSIZE);
2784
2785        set_64bit_val(qp_ctx,
2786                      128,
2787                      LS_64(info->err_rq_idx, I40IWQPC_ERR_RQ_IDX));
2788
2789        set_64bit_val(qp_ctx,
2790                      136,
2791                      LS_64(info->send_cq_num, I40IWQPC_TXCQNUM) |
2792                      LS_64(info->rcv_cq_num, I40IWQPC_RXCQNUM));
2793
2794        set_64bit_val(qp_ctx,
2795                      168,
2796                      LS_64(info->qp_compl_ctx, I40IWQPC_QPCOMPCTX));
2797        set_64bit_val(qp_ctx,
2798                      176,
2799                      LS_64(qp->sq_tph_val, I40IWQPC_SQTPHVAL) |
2800                      LS_64(qp->rq_tph_val, I40IWQPC_RQTPHVAL) |
2801                      LS_64(qp->qs_handle, I40IWQPC_QSHANDLE) |
2802                      LS_64(vsi->exception_lan_queue, I40IWQPC_EXCEPTION_LAN_QUEUE));
2803
2804        if (info->iwarp_info_valid) {
2805                qw0 |= LS_64(iw->ddp_ver, I40IWQPC_DDP_VER) |
2806                       LS_64(iw->rdmap_ver, I40IWQPC_RDMAP_VER);
2807
2808                qw7 |= LS_64(iw->pd_id, I40IWQPC_PDIDX);
2809                set_64bit_val(qp_ctx,
2810                              144,
2811                              LS_64(qp->q2_pa, I40IWQPC_Q2ADDR) |
2812                              LS_64(vsi->fcn_id, I40IWQPC_STAT_INDEX));
2813                set_64bit_val(qp_ctx,
2814                              152,
2815                              LS_64(iw->last_byte_sent, I40IWQPC_LASTBYTESENT));
2816
2817                set_64bit_val(qp_ctx,
2818                              160,
2819                              LS_64(iw->ord_size, I40IWQPC_ORDSIZE) |
2820                              LS_64(iw->ird_size, I40IWQPC_IRDSIZE) |
2821                              LS_64(iw->wr_rdresp_en, I40IWQPC_WRRDRSPOK) |
2822                              LS_64(iw->rd_enable, I40IWQPC_RDOK) |
2823                              LS_64(iw->snd_mark_en, I40IWQPC_SNDMARKERS) |
2824                              LS_64(iw->bind_en, I40IWQPC_BINDEN) |
2825                              LS_64(iw->fast_reg_en, I40IWQPC_FASTREGEN) |
2826                              LS_64(iw->priv_mode_en, I40IWQPC_PRIVEN) |
2827                              LS_64((((vsi->stats_fcn_id_alloc) &&
2828                                      (dev->is_pf) && (vsi->fcn_id >= I40IW_FIRST_NON_PF_STAT)) ? 1 : 0),
2829                                    I40IWQPC_USESTATSINSTANCE) |
2830                              LS_64(1, I40IWQPC_IWARPMODE) |
2831                              LS_64(iw->rcv_mark_en, I40IWQPC_RCVMARKERS) |
2832                              LS_64(iw->align_hdrs, I40IWQPC_ALIGNHDRS) |
2833                              LS_64(iw->rcv_no_mpa_crc, I40IWQPC_RCVNOMPACRC) |
2834                              LS_64(iw->rcv_mark_offset, I40IWQPC_RCVMARKOFFSET) |
2835                              LS_64(iw->snd_mark_offset, I40IWQPC_SNDMARKOFFSET));
2836        }
2837        if (info->tcp_info_valid) {
2838                qw0 |= LS_64(tcp->ipv4, I40IWQPC_IPV4) |
2839                       LS_64(tcp->no_nagle, I40IWQPC_NONAGLE) |
2840                       LS_64(tcp->insert_vlan_tag, I40IWQPC_INSERTVLANTAG) |
2841                       LS_64(tcp->time_stamp, I40IWQPC_TIMESTAMP) |
2842                       LS_64(tcp->cwnd_inc_limit, I40IWQPC_LIMIT) |
2843                       LS_64(tcp->drop_ooo_seg, I40IWQPC_DROPOOOSEG) |
2844                       LS_64(tcp->dup_ack_thresh, I40IWQPC_DUPACK_THRESH);
2845
2846                qw3 |= LS_64(tcp->ttl, I40IWQPC_TTL) |
2847                       LS_64(tcp->src_mac_addr_idx, I40IWQPC_SRCMACADDRIDX) |
2848                       LS_64(tcp->avoid_stretch_ack, I40IWQPC_AVOIDSTRETCHACK) |
2849                       LS_64(tcp->tos, I40IWQPC_TOS) |
2850                       LS_64(tcp->src_port, I40IWQPC_SRCPORTNUM) |
2851                       LS_64(tcp->dst_port, I40IWQPC_DESTPORTNUM);
2852
2853                qp->src_mac_addr_idx = tcp->src_mac_addr_idx;
2854                set_64bit_val(qp_ctx,
2855                              32,
2856                              LS_64(tcp->dest_ip_addr2, I40IWQPC_DESTIPADDR2) |
2857                              LS_64(tcp->dest_ip_addr3, I40IWQPC_DESTIPADDR3));
2858
2859                set_64bit_val(qp_ctx,
2860                              40,
2861                              LS_64(tcp->dest_ip_addr0, I40IWQPC_DESTIPADDR0) |
2862                              LS_64(tcp->dest_ip_addr1, I40IWQPC_DESTIPADDR1));
2863
2864                set_64bit_val(qp_ctx,
2865                              48,
2866                              LS_64(tcp->snd_mss, I40IWQPC_SNDMSS) |
2867                                LS_64(tcp->vlan_tag, I40IWQPC_VLANTAG) |
2868                                LS_64(tcp->arp_idx, I40IWQPC_ARPIDX));
2869
2870                qw7 |= LS_64(tcp->flow_label, I40IWQPC_FLOWLABEL) |
2871                       LS_64(tcp->wscale, I40IWQPC_WSCALE) |
2872                       LS_64(tcp->ignore_tcp_opt, I40IWQPC_IGNORE_TCP_OPT) |
2873                       LS_64(tcp->ignore_tcp_uns_opt, I40IWQPC_IGNORE_TCP_UNS_OPT) |
2874                       LS_64(tcp->tcp_state, I40IWQPC_TCPSTATE) |
2875                       LS_64(tcp->rcv_wscale, I40IWQPC_RCVSCALE) |
2876                       LS_64(tcp->snd_wscale, I40IWQPC_SNDSCALE);
2877
2878                set_64bit_val(qp_ctx,
2879                              72,
2880                              LS_64(tcp->time_stamp_recent, I40IWQPC_TIMESTAMP_RECENT) |
2881                              LS_64(tcp->time_stamp_age, I40IWQPC_TIMESTAMP_AGE));
2882                set_64bit_val(qp_ctx,
2883                              80,
2884                              LS_64(tcp->snd_nxt, I40IWQPC_SNDNXT) |
2885                              LS_64(tcp->snd_wnd, I40IWQPC_SNDWND));
2886
2887                set_64bit_val(qp_ctx,
2888                              88,
2889                              LS_64(tcp->rcv_nxt, I40IWQPC_RCVNXT) |
2890                              LS_64(tcp->rcv_wnd, I40IWQPC_RCVWND));
2891                set_64bit_val(qp_ctx,
2892                              96,
2893                              LS_64(tcp->snd_max, I40IWQPC_SNDMAX) |
2894                              LS_64(tcp->snd_una, I40IWQPC_SNDUNA));
2895                set_64bit_val(qp_ctx,
2896                              104,
2897                              LS_64(tcp->srtt, I40IWQPC_SRTT) |
2898                              LS_64(tcp->rtt_var, I40IWQPC_RTTVAR));
2899                set_64bit_val(qp_ctx,
2900                              112,
2901                              LS_64(tcp->ss_thresh, I40IWQPC_SSTHRESH) |
2902                              LS_64(tcp->cwnd, I40IWQPC_CWND));
2903                set_64bit_val(qp_ctx,
2904                              120,
2905                              LS_64(tcp->snd_wl1, I40IWQPC_SNDWL1) |
2906                              LS_64(tcp->snd_wl2, I40IWQPC_SNDWL2));
2907                set_64bit_val(qp_ctx,
2908                              128,
2909                              LS_64(tcp->max_snd_window, I40IWQPC_MAXSNDWND) |
2910                              LS_64(tcp->rexmit_thresh, I40IWQPC_REXMIT_THRESH));
2911                set_64bit_val(qp_ctx,
2912                              184,
2913                              LS_64(tcp->local_ipaddr3, I40IWQPC_LOCAL_IPADDR3) |
2914                              LS_64(tcp->local_ipaddr2, I40IWQPC_LOCAL_IPADDR2));
2915                set_64bit_val(qp_ctx,
2916                              192,
2917                              LS_64(tcp->local_ipaddr1, I40IWQPC_LOCAL_IPADDR1) |
2918                              LS_64(tcp->local_ipaddr0, I40IWQPC_LOCAL_IPADDR0));
2919        }
2920
2921        set_64bit_val(qp_ctx, 0, qw0);
2922        set_64bit_val(qp_ctx, 24, qw3);
2923        set_64bit_val(qp_ctx, 56, qw7);
2924
2925        i40iw_debug_buf(qp->dev, I40IW_DEBUG_WQE, "QP_HOST)CTX WQE",
2926                        qp_ctx, I40IW_QP_CTX_SIZE);
2927        return 0;
2928}
2929
2930/**
2931 * i40iw_sc_alloc_stag - mr stag alloc
2932 * @dev: sc device struct
2933 * @info: stag info
2934 * @scratch: u64 saved to be used during cqp completion
2935 * @post_sq: flag for cqp db to ring
2936 */
2937static enum i40iw_status_code i40iw_sc_alloc_stag(
2938                                struct i40iw_sc_dev *dev,
2939                                struct i40iw_allocate_stag_info *info,
2940                                u64 scratch,
2941                                bool post_sq)
2942{
2943        u64 *wqe;
2944        struct i40iw_sc_cqp *cqp;
2945        u64 header;
2946        enum i40iw_page_size page_size;
2947
2948        page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
2949        cqp = dev->cqp;
2950        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
2951        if (!wqe)
2952                return I40IW_ERR_RING_FULL;
2953        set_64bit_val(wqe,
2954                      8,
2955                      LS_64(info->pd_id, I40IW_CQPSQ_STAG_PDID) |
2956                      LS_64(info->total_len, I40IW_CQPSQ_STAG_STAGLEN));
2957        set_64bit_val(wqe,
2958                      16,
2959                      LS_64(info->stag_idx, I40IW_CQPSQ_STAG_IDX));
2960        set_64bit_val(wqe,
2961                      40,
2962                      LS_64(info->hmc_fcn_index, I40IW_CQPSQ_STAG_HMCFNIDX));
2963
2964        header = LS_64(I40IW_CQP_OP_ALLOC_STAG, I40IW_CQPSQ_OPCODE) |
2965                 LS_64(1, I40IW_CQPSQ_STAG_MR) |
2966                 LS_64(info->access_rights, I40IW_CQPSQ_STAG_ARIGHTS) |
2967                 LS_64(info->chunk_size, I40IW_CQPSQ_STAG_LPBLSIZE) |
2968                 LS_64(page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
2969                 LS_64(info->remote_access, I40IW_CQPSQ_STAG_REMACCENABLED) |
2970                 LS_64(info->use_hmc_fcn_index, I40IW_CQPSQ_STAG_USEHMCFNIDX) |
2971                 LS_64(info->use_pf_rid, I40IW_CQPSQ_STAG_USEPFRID) |
2972                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
2973
2974        i40iw_insert_wqe_hdr(wqe, header);
2975
2976        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "ALLOC_STAG WQE",
2977                        wqe, I40IW_CQP_WQE_SIZE * 8);
2978
2979        if (post_sq)
2980                i40iw_sc_cqp_post_sq(cqp);
2981        return 0;
2982}
2983
2984/**
2985 * i40iw_sc_mr_reg_non_shared - non-shared mr registration
2986 * @dev: sc device struct
2987 * @info: mr info
2988 * @scratch: u64 saved to be used during cqp completion
2989 * @post_sq: flag for cqp db to ring
2990 */
2991static enum i40iw_status_code i40iw_sc_mr_reg_non_shared(
2992                                struct i40iw_sc_dev *dev,
2993                                struct i40iw_reg_ns_stag_info *info,
2994                                u64 scratch,
2995                                bool post_sq)
2996{
2997        u64 *wqe;
2998        u64 temp;
2999        struct i40iw_sc_cqp *cqp;
3000        u64 header;
3001        u32 pble_obj_cnt;
3002        bool remote_access;
3003        u8 addr_type;
3004        enum i40iw_page_size page_size;
3005
3006        page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
3007        if (info->access_rights & (I40IW_ACCESS_FLAGS_REMOTEREAD_ONLY |
3008                                   I40IW_ACCESS_FLAGS_REMOTEWRITE_ONLY))
3009                remote_access = true;
3010        else
3011                remote_access = false;
3012
3013        pble_obj_cnt = dev->hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt;
3014
3015        if (info->chunk_size && (info->first_pm_pbl_index >= pble_obj_cnt))
3016                return I40IW_ERR_INVALID_PBLE_INDEX;
3017
3018        cqp = dev->cqp;
3019        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3020        if (!wqe)
3021                return I40IW_ERR_RING_FULL;
3022
3023        temp = (info->addr_type == I40IW_ADDR_TYPE_VA_BASED) ? (uintptr_t)info->va : info->fbo;
3024        set_64bit_val(wqe, 0, temp);
3025
3026        set_64bit_val(wqe,
3027                      8,
3028                      LS_64(info->total_len, I40IW_CQPSQ_STAG_STAGLEN) |
3029                      LS_64(info->pd_id, I40IW_CQPSQ_STAG_PDID));
3030
3031        set_64bit_val(wqe,
3032                      16,
3033                      LS_64(info->stag_key, I40IW_CQPSQ_STAG_KEY) |
3034                      LS_64(info->stag_idx, I40IW_CQPSQ_STAG_IDX));
3035        if (!info->chunk_size) {
3036                set_64bit_val(wqe, 32, info->reg_addr_pa);
3037                set_64bit_val(wqe, 48, 0);
3038        } else {
3039                set_64bit_val(wqe, 32, 0);
3040                set_64bit_val(wqe, 48, info->first_pm_pbl_index);
3041        }
3042        set_64bit_val(wqe, 40, info->hmc_fcn_index);
3043        set_64bit_val(wqe, 56, 0);
3044
3045        addr_type = (info->addr_type == I40IW_ADDR_TYPE_VA_BASED) ? 1 : 0;
3046        header = LS_64(I40IW_CQP_OP_REG_MR, I40IW_CQPSQ_OPCODE) |
3047                 LS_64(1, I40IW_CQPSQ_STAG_MR) |
3048                 LS_64(info->chunk_size, I40IW_CQPSQ_STAG_LPBLSIZE) |
3049                 LS_64(page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
3050                 LS_64(info->access_rights, I40IW_CQPSQ_STAG_ARIGHTS) |
3051                 LS_64(remote_access, I40IW_CQPSQ_STAG_REMACCENABLED) |
3052                 LS_64(addr_type, I40IW_CQPSQ_STAG_VABASEDTO) |
3053                 LS_64(info->use_hmc_fcn_index, I40IW_CQPSQ_STAG_USEHMCFNIDX) |
3054                 LS_64(info->use_pf_rid, I40IW_CQPSQ_STAG_USEPFRID) |
3055                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3056
3057        i40iw_insert_wqe_hdr(wqe, header);
3058
3059        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "MR_REG_NS WQE",
3060                        wqe, I40IW_CQP_WQE_SIZE * 8);
3061
3062        if (post_sq)
3063                i40iw_sc_cqp_post_sq(cqp);
3064        return 0;
3065}
3066
3067/**
3068 * i40iw_sc_mr_reg_shared - registered shared memory region
3069 * @dev: sc device struct
3070 * @info: info for shared memory registeration
3071 * @scratch: u64 saved to be used during cqp completion
3072 * @post_sq: flag for cqp db to ring
3073 */
3074static enum i40iw_status_code i40iw_sc_mr_reg_shared(
3075                                        struct i40iw_sc_dev *dev,
3076                                        struct i40iw_register_shared_stag *info,
3077                                        u64 scratch,
3078                                        bool post_sq)
3079{
3080        u64 *wqe;
3081        struct i40iw_sc_cqp *cqp;
3082        u64 temp, va64, fbo, header;
3083        u32 va32;
3084        bool remote_access;
3085        u8 addr_type;
3086
3087        if (info->access_rights & (I40IW_ACCESS_FLAGS_REMOTEREAD_ONLY |
3088                                   I40IW_ACCESS_FLAGS_REMOTEWRITE_ONLY))
3089                remote_access = true;
3090        else
3091                remote_access = false;
3092        cqp = dev->cqp;
3093        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3094        if (!wqe)
3095                return I40IW_ERR_RING_FULL;
3096        va64 = (uintptr_t)(info->va);
3097        va32 = (u32)(va64 & 0x00000000FFFFFFFF);
3098        fbo = (u64)(va32 & (4096 - 1));
3099
3100        set_64bit_val(wqe,
3101                      0,
3102                      (info->addr_type == I40IW_ADDR_TYPE_VA_BASED ? (uintptr_t)info->va : fbo));
3103
3104        set_64bit_val(wqe,
3105                      8,
3106                      LS_64(info->pd_id, I40IW_CQPSQ_STAG_PDID));
3107        temp = LS_64(info->new_stag_key, I40IW_CQPSQ_STAG_KEY) |
3108               LS_64(info->new_stag_idx, I40IW_CQPSQ_STAG_IDX) |
3109               LS_64(info->parent_stag_idx, I40IW_CQPSQ_STAG_PARENTSTAGIDX);
3110        set_64bit_val(wqe, 16, temp);
3111
3112        addr_type = (info->addr_type == I40IW_ADDR_TYPE_VA_BASED) ? 1 : 0;
3113        header = LS_64(I40IW_CQP_OP_REG_SMR, I40IW_CQPSQ_OPCODE) |
3114                 LS_64(1, I40IW_CQPSQ_STAG_MR) |
3115                 LS_64(info->access_rights, I40IW_CQPSQ_STAG_ARIGHTS) |
3116                 LS_64(remote_access, I40IW_CQPSQ_STAG_REMACCENABLED) |
3117                 LS_64(addr_type, I40IW_CQPSQ_STAG_VABASEDTO) |
3118                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3119
3120        i40iw_insert_wqe_hdr(wqe, header);
3121
3122        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "MR_REG_SHARED WQE",
3123                        wqe, I40IW_CQP_WQE_SIZE * 8);
3124
3125        if (post_sq)
3126                i40iw_sc_cqp_post_sq(cqp);
3127        return 0;
3128}
3129
3130/**
3131 * i40iw_sc_dealloc_stag - deallocate stag
3132 * @dev: sc device struct
3133 * @info: dealloc stag info
3134 * @scratch: u64 saved to be used during cqp completion
3135 * @post_sq: flag for cqp db to ring
3136 */
3137static enum i40iw_status_code i40iw_sc_dealloc_stag(
3138                                        struct i40iw_sc_dev *dev,
3139                                        struct i40iw_dealloc_stag_info *info,
3140                                        u64 scratch,
3141                                        bool post_sq)
3142{
3143        u64 header;
3144        u64 *wqe;
3145        struct i40iw_sc_cqp *cqp;
3146
3147        cqp = dev->cqp;
3148        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3149        if (!wqe)
3150                return I40IW_ERR_RING_FULL;
3151        set_64bit_val(wqe,
3152                      8,
3153                      LS_64(info->pd_id, I40IW_CQPSQ_STAG_PDID));
3154        set_64bit_val(wqe,
3155                      16,
3156                      LS_64(info->stag_idx, I40IW_CQPSQ_STAG_IDX));
3157
3158        header = LS_64(I40IW_CQP_OP_DEALLOC_STAG, I40IW_CQPSQ_OPCODE) |
3159                 LS_64(info->mr, I40IW_CQPSQ_STAG_MR) |
3160                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3161
3162        i40iw_insert_wqe_hdr(wqe, header);
3163
3164        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "DEALLOC_STAG WQE",
3165                        wqe, I40IW_CQP_WQE_SIZE * 8);
3166
3167        if (post_sq)
3168                i40iw_sc_cqp_post_sq(cqp);
3169        return 0;
3170}
3171
3172/**
3173 * i40iw_sc_query_stag - query hardware for stag
3174 * @dev: sc device struct
3175 * @scratch: u64 saved to be used during cqp completion
3176 * @stag_index: stag index for query
3177 * @post_sq: flag for cqp db to ring
3178 */
3179static enum i40iw_status_code i40iw_sc_query_stag(struct i40iw_sc_dev *dev,
3180                                                  u64 scratch,
3181                                                  u32 stag_index,
3182                                                  bool post_sq)
3183{
3184        u64 header;
3185        u64 *wqe;
3186        struct i40iw_sc_cqp *cqp;
3187
3188        cqp = dev->cqp;
3189        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3190        if (!wqe)
3191                return I40IW_ERR_RING_FULL;
3192        set_64bit_val(wqe,
3193                      16,
3194                      LS_64(stag_index, I40IW_CQPSQ_QUERYSTAG_IDX));
3195
3196        header = LS_64(I40IW_CQP_OP_QUERY_STAG, I40IW_CQPSQ_OPCODE) |
3197                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3198
3199        i40iw_insert_wqe_hdr(wqe, header);
3200
3201        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "QUERY_STAG WQE",
3202                        wqe, I40IW_CQP_WQE_SIZE * 8);
3203
3204        if (post_sq)
3205                i40iw_sc_cqp_post_sq(cqp);
3206        return 0;
3207}
3208
3209/**
3210 * i40iw_sc_mw_alloc - mw allocate
3211 * @dev: sc device struct
3212 * @scratch: u64 saved to be used during cqp completion
3213 * @mw_stag_index:stag index
3214 * @pd_id: pd is for this mw
3215 * @post_sq: flag for cqp db to ring
3216 */
3217static enum i40iw_status_code i40iw_sc_mw_alloc(
3218                                        struct i40iw_sc_dev *dev,
3219                                        u64 scratch,
3220                                        u32 mw_stag_index,
3221                                        u16 pd_id,
3222                                        bool post_sq)
3223{
3224        u64 header;
3225        struct i40iw_sc_cqp *cqp;
3226        u64 *wqe;
3227
3228        cqp = dev->cqp;
3229        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3230        if (!wqe)
3231                return I40IW_ERR_RING_FULL;
3232        set_64bit_val(wqe, 8, LS_64(pd_id, I40IW_CQPSQ_STAG_PDID));
3233        set_64bit_val(wqe,
3234                      16,
3235                      LS_64(mw_stag_index, I40IW_CQPSQ_STAG_IDX));
3236
3237        header = LS_64(I40IW_CQP_OP_ALLOC_STAG, I40IW_CQPSQ_OPCODE) |
3238                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3239
3240        i40iw_insert_wqe_hdr(wqe, header);
3241
3242        i40iw_debug_buf(dev, I40IW_DEBUG_WQE, "MW_ALLOC WQE",
3243                        wqe, I40IW_CQP_WQE_SIZE * 8);
3244
3245        if (post_sq)
3246                i40iw_sc_cqp_post_sq(cqp);
3247        return 0;
3248}
3249
3250/**
3251 * i40iw_sc_mr_fast_register - Posts RDMA fast register mr WR to iwarp qp
3252 * @qp: sc qp struct
3253 * @info: fast mr info
3254 * @post_sq: flag for cqp db to ring
3255 */
3256enum i40iw_status_code i40iw_sc_mr_fast_register(
3257                                struct i40iw_sc_qp *qp,
3258                                struct i40iw_fast_reg_stag_info *info,
3259                                bool post_sq)
3260{
3261        u64 temp, header;
3262        u64 *wqe;
3263        u32 wqe_idx;
3264        enum i40iw_page_size page_size;
3265
3266        page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
3267        wqe = i40iw_qp_get_next_send_wqe(&qp->qp_uk, &wqe_idx, I40IW_QP_WQE_MIN_SIZE,
3268                                         0, info->wr_id);
3269        if (!wqe)
3270                return I40IW_ERR_QP_TOOMANY_WRS_POSTED;
3271
3272        i40iw_debug(qp->dev, I40IW_DEBUG_MR, "%s: wr_id[%llxh] wqe_idx[%04d] location[%p]\n",
3273                    __func__, info->wr_id, wqe_idx,
3274                    &qp->qp_uk.sq_wrtrk_array[wqe_idx].wrid);
3275        temp = (info->addr_type == I40IW_ADDR_TYPE_VA_BASED) ? (uintptr_t)info->va : info->fbo;
3276        set_64bit_val(wqe, 0, temp);
3277
3278        temp = RS_64(info->first_pm_pbl_index >> 16, I40IWQPSQ_FIRSTPMPBLIDXHI);
3279        set_64bit_val(wqe,
3280                      8,
3281                      LS_64(temp, I40IWQPSQ_FIRSTPMPBLIDXHI) |
3282                      LS_64(info->reg_addr_pa >> I40IWQPSQ_PBLADDR_SHIFT, I40IWQPSQ_PBLADDR));
3283
3284        set_64bit_val(wqe,
3285                      16,
3286                      info->total_len |
3287                      LS_64(info->first_pm_pbl_index, I40IWQPSQ_FIRSTPMPBLIDXLO));
3288
3289        header = LS_64(info->stag_key, I40IWQPSQ_STAGKEY) |
3290                 LS_64(info->stag_idx, I40IWQPSQ_STAGINDEX) |
3291                 LS_64(I40IWQP_OP_FAST_REGISTER, I40IWQPSQ_OPCODE) |
3292                 LS_64(info->chunk_size, I40IWQPSQ_LPBLSIZE) |
3293                 LS_64(page_size, I40IWQPSQ_HPAGESIZE) |
3294                 LS_64(info->access_rights, I40IWQPSQ_STAGRIGHTS) |
3295                 LS_64(info->addr_type, I40IWQPSQ_VABASEDTO) |
3296                 LS_64(info->read_fence, I40IWQPSQ_READFENCE) |
3297                 LS_64(info->local_fence, I40IWQPSQ_LOCALFENCE) |
3298                 LS_64(info->signaled, I40IWQPSQ_SIGCOMPL) |
3299                 LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3300
3301        i40iw_insert_wqe_hdr(wqe, header);
3302
3303        i40iw_debug_buf(qp->dev, I40IW_DEBUG_WQE, "FAST_REG WQE",
3304                        wqe, I40IW_QP_WQE_MIN_SIZE);
3305
3306        if (post_sq)
3307                i40iw_qp_post_wr(&qp->qp_uk);
3308        return 0;
3309}
3310
3311/**
3312 * i40iw_sc_send_lsmm - send last streaming mode message
3313 * @qp: sc qp struct
3314 * @lsmm_buf: buffer with lsmm message
3315 * @size: size of lsmm buffer
3316 * @stag: stag of lsmm buffer
3317 */
3318static void i40iw_sc_send_lsmm(struct i40iw_sc_qp *qp,
3319                               void *lsmm_buf,
3320                               u32 size,
3321                               i40iw_stag stag)
3322{
3323        u64 *wqe;
3324        u64 header;
3325        struct i40iw_qp_uk *qp_uk;
3326
3327        qp_uk = &qp->qp_uk;
3328        wqe = qp_uk->sq_base->elem;
3329
3330        set_64bit_val(wqe, 0, (uintptr_t)lsmm_buf);
3331
3332        set_64bit_val(wqe, 8, (size | LS_64(stag, I40IWQPSQ_FRAG_STAG)));
3333
3334        set_64bit_val(wqe, 16, 0);
3335
3336        header = LS_64(I40IWQP_OP_RDMA_SEND, I40IWQPSQ_OPCODE) |
3337                 LS_64(1, I40IWQPSQ_STREAMMODE) |
3338                 LS_64(1, I40IWQPSQ_WAITFORRCVPDU) |
3339                 LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3340
3341        i40iw_insert_wqe_hdr(wqe, header);
3342
3343        i40iw_debug_buf(qp->dev, I40IW_DEBUG_QP, "SEND_LSMM WQE",
3344                        wqe, I40IW_QP_WQE_MIN_SIZE);
3345}
3346
3347/**
3348 * i40iw_sc_send_lsmm_nostag - for privilege qp
3349 * @qp: sc qp struct
3350 * @lsmm_buf: buffer with lsmm message
3351 * @size: size of lsmm buffer
3352 */
3353static void i40iw_sc_send_lsmm_nostag(struct i40iw_sc_qp *qp,
3354                                      void *lsmm_buf,
3355                                      u32 size)
3356{
3357        u64 *wqe;
3358        u64 header;
3359        struct i40iw_qp_uk *qp_uk;
3360
3361        qp_uk = &qp->qp_uk;
3362        wqe = qp_uk->sq_base->elem;
3363
3364        set_64bit_val(wqe, 0, (uintptr_t)lsmm_buf);
3365
3366        set_64bit_val(wqe, 8, size);
3367
3368        set_64bit_val(wqe, 16, 0);
3369
3370        header = LS_64(I40IWQP_OP_RDMA_SEND, I40IWQPSQ_OPCODE) |
3371                 LS_64(1, I40IWQPSQ_STREAMMODE) |
3372                 LS_64(1, I40IWQPSQ_WAITFORRCVPDU) |
3373                 LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3374
3375        i40iw_insert_wqe_hdr(wqe, header);
3376
3377        i40iw_debug_buf(qp->dev, I40IW_DEBUG_WQE, "SEND_LSMM_NOSTAG WQE",
3378                        wqe, I40IW_QP_WQE_MIN_SIZE);
3379}
3380
3381/**
3382 * i40iw_sc_send_rtt - send last read0 or write0
3383 * @qp: sc qp struct
3384 * @read: Do read0 or write0
3385 */
3386static void i40iw_sc_send_rtt(struct i40iw_sc_qp *qp, bool read)
3387{
3388        u64 *wqe;
3389        u64 header;
3390        struct i40iw_qp_uk *qp_uk;
3391
3392        qp_uk = &qp->qp_uk;
3393        wqe = qp_uk->sq_base->elem;
3394
3395        set_64bit_val(wqe, 0, 0);
3396        set_64bit_val(wqe, 8, 0);
3397        set_64bit_val(wqe, 16, 0);
3398        if (read) {
3399                header = LS_64(0x1234, I40IWQPSQ_REMSTAG) |
3400                         LS_64(I40IWQP_OP_RDMA_READ, I40IWQPSQ_OPCODE) |
3401                         LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3402                set_64bit_val(wqe, 8, ((u64)0xabcd << 32));
3403        } else {
3404                header = LS_64(I40IWQP_OP_RDMA_WRITE, I40IWQPSQ_OPCODE) |
3405                         LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3406        }
3407
3408        i40iw_insert_wqe_hdr(wqe, header);
3409
3410        i40iw_debug_buf(qp->dev, I40IW_DEBUG_WQE, "RTR WQE",
3411                        wqe, I40IW_QP_WQE_MIN_SIZE);
3412}
3413
3414/**
3415 * i40iw_sc_post_wqe0 - send wqe with opcode
3416 * @qp: sc qp struct
3417 * @opcode: opcode to use for wqe0
3418 */
3419static enum i40iw_status_code i40iw_sc_post_wqe0(struct i40iw_sc_qp *qp, u8 opcode)
3420{
3421        u64 *wqe;
3422        u64 header;
3423        struct i40iw_qp_uk *qp_uk;
3424
3425        qp_uk = &qp->qp_uk;
3426        wqe = qp_uk->sq_base->elem;
3427
3428        if (!wqe)
3429                return I40IW_ERR_QP_TOOMANY_WRS_POSTED;
3430        switch (opcode) {
3431        case I40IWQP_OP_NOP:
3432                set_64bit_val(wqe, 0, 0);
3433                set_64bit_val(wqe, 8, 0);
3434                set_64bit_val(wqe, 16, 0);
3435                header = LS_64(I40IWQP_OP_NOP, I40IWQPSQ_OPCODE) |
3436                         LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID);
3437
3438                i40iw_insert_wqe_hdr(wqe, header);
3439                break;
3440        case I40IWQP_OP_RDMA_SEND:
3441                set_64bit_val(wqe, 0, 0);
3442                set_64bit_val(wqe, 8, 0);
3443                set_64bit_val(wqe, 16, 0);
3444                header = LS_64(I40IWQP_OP_RDMA_SEND, I40IWQPSQ_OPCODE) |
3445                         LS_64(qp->qp_uk.swqe_polarity, I40IWQPSQ_VALID) |
3446                         LS_64(1, I40IWQPSQ_STREAMMODE) |
3447                         LS_64(1, I40IWQPSQ_WAITFORRCVPDU);
3448
3449                i40iw_insert_wqe_hdr(wqe, header);
3450                break;
3451        default:
3452                i40iw_debug(qp->dev, I40IW_DEBUG_QP, "%s: Invalid WQE zero opcode\n",
3453                            __func__);
3454                break;
3455        }
3456        return 0;
3457}
3458
3459/**
3460 * i40iw_sc_init_iw_hmc() - queries fpm values using cqp and populates hmc_info
3461 * @dev : ptr to i40iw_dev struct
3462 * @hmc_fn_id: hmc function id
3463 */
3464enum i40iw_status_code i40iw_sc_init_iw_hmc(struct i40iw_sc_dev *dev, u8 hmc_fn_id)
3465{
3466        struct i40iw_hmc_info *hmc_info;
3467        struct i40iw_dma_mem query_fpm_mem;
3468        struct i40iw_virt_mem virt_mem;
3469        struct i40iw_vfdev *vf_dev = NULL;
3470        u32 mem_size;
3471        enum i40iw_status_code ret_code = 0;
3472        bool poll_registers = true;
3473        u16 iw_vf_idx;
3474        u8 wait_type;
3475
3476        if (hmc_fn_id >= I40IW_MAX_VF_FPM_ID ||
3477            (dev->hmc_fn_id != hmc_fn_id && hmc_fn_id < I40IW_FIRST_VF_FPM_ID))
3478                return I40IW_ERR_INVALID_HMCFN_ID;
3479
3480        i40iw_debug(dev, I40IW_DEBUG_HMC, "hmc_fn_id %u, dev->hmc_fn_id %u\n", hmc_fn_id,
3481                    dev->hmc_fn_id);
3482        if (hmc_fn_id == dev->hmc_fn_id) {
3483                hmc_info = dev->hmc_info;
3484                query_fpm_mem.pa = dev->fpm_query_buf_pa;
3485                query_fpm_mem.va = dev->fpm_query_buf;
3486        } else {
3487                vf_dev = i40iw_vfdev_from_fpm(dev, hmc_fn_id);
3488                if (!vf_dev)
3489                        return I40IW_ERR_INVALID_VF_ID;
3490
3491                hmc_info = &vf_dev->hmc_info;
3492                iw_vf_idx = vf_dev->iw_vf_idx;
3493                i40iw_debug(dev, I40IW_DEBUG_HMC, "vf_dev %p, hmc_info %p, hmc_obj %p\n", vf_dev,
3494                            hmc_info, hmc_info->hmc_obj);
3495                if (!vf_dev->fpm_query_buf) {
3496                        if (!dev->vf_fpm_query_buf[iw_vf_idx].va) {
3497                                ret_code = i40iw_alloc_query_fpm_buf(dev,
3498                                                                     &dev->vf_fpm_query_buf[iw_vf_idx]);
3499                                if (ret_code)
3500                                        return ret_code;
3501                        }
3502                        vf_dev->fpm_query_buf = dev->vf_fpm_query_buf[iw_vf_idx].va;
3503                        vf_dev->fpm_query_buf_pa = dev->vf_fpm_query_buf[iw_vf_idx].pa;
3504                }
3505                query_fpm_mem.pa = vf_dev->fpm_query_buf_pa;
3506                query_fpm_mem.va = vf_dev->fpm_query_buf;
3507                /**
3508                 * It is HARDWARE specific:
3509                 * this call is done by PF for VF and
3510                 * i40iw_sc_query_fpm_values needs ccq poll
3511                 * because PF ccq is already created.
3512                 */
3513                poll_registers = false;
3514        }
3515
3516        hmc_info->hmc_fn_id = hmc_fn_id;
3517
3518        if (hmc_fn_id != dev->hmc_fn_id) {
3519                ret_code =
3520                        i40iw_cqp_query_fpm_values_cmd(dev, &query_fpm_mem, hmc_fn_id);
3521        } else {
3522                wait_type = poll_registers ? (u8)I40IW_CQP_WAIT_POLL_REGS :
3523                            (u8)I40IW_CQP_WAIT_POLL_CQ;
3524
3525                ret_code = i40iw_sc_query_fpm_values(
3526                                        dev->cqp,
3527                                        0,
3528                                        hmc_info->hmc_fn_id,
3529                                        &query_fpm_mem,
3530                                        true,
3531                                        wait_type);
3532        }
3533        if (ret_code)
3534                return ret_code;
3535
3536        /* parse the fpm_query_buf and fill hmc obj info */
3537        ret_code =
3538                i40iw_sc_parse_fpm_query_buf((u64 *)query_fpm_mem.va,
3539                                             hmc_info,
3540                                             &dev->hmc_fpm_misc);
3541        if (ret_code)
3542                return ret_code;
3543        i40iw_debug_buf(dev, I40IW_DEBUG_HMC, "QUERY FPM BUFFER",
3544                        query_fpm_mem.va, I40IW_QUERY_FPM_BUF_SIZE);
3545
3546        if (hmc_fn_id != dev->hmc_fn_id) {
3547                i40iw_cqp_commit_fpm_values_cmd(dev, &query_fpm_mem, hmc_fn_id);
3548
3549                /* parse the fpm_commit_buf and fill hmc obj info */
3550                i40iw_sc_parse_fpm_commit_buf((u64 *)query_fpm_mem.va, hmc_info->hmc_obj, &hmc_info->sd_table.sd_cnt);
3551                mem_size = sizeof(struct i40iw_hmc_sd_entry) *
3552                           (hmc_info->sd_table.sd_cnt + hmc_info->first_sd_index);
3553                ret_code = i40iw_allocate_virt_mem(dev->hw, &virt_mem, mem_size);
3554                if (ret_code)
3555                        return ret_code;
3556                hmc_info->sd_table.sd_entry = virt_mem.va;
3557        }
3558
3559        return ret_code;
3560}
3561
3562/**
3563 * i40iw_sc_configure_iw_fpm() - commits hmc obj cnt values using cqp command and
3564 * populates fpm base address in hmc_info
3565 * @dev : ptr to i40iw_dev struct
3566 * @hmc_fn_id: hmc function id
3567 */
3568static enum i40iw_status_code i40iw_sc_configure_iw_fpm(struct i40iw_sc_dev *dev,
3569                                                        u8 hmc_fn_id)
3570{
3571        struct i40iw_hmc_info *hmc_info;
3572        struct i40iw_hmc_obj_info *obj_info;
3573        u64 *buf;
3574        struct i40iw_dma_mem commit_fpm_mem;
3575        u32 i, j;
3576        enum i40iw_status_code ret_code = 0;
3577        bool poll_registers = true;
3578        u8 wait_type;
3579
3580        if (hmc_fn_id >= I40IW_MAX_VF_FPM_ID ||
3581            (dev->hmc_fn_id != hmc_fn_id && hmc_fn_id < I40IW_FIRST_VF_FPM_ID))
3582                return I40IW_ERR_INVALID_HMCFN_ID;
3583
3584        if (hmc_fn_id == dev->hmc_fn_id) {
3585                hmc_info = dev->hmc_info;
3586        } else {
3587                hmc_info = i40iw_vf_hmcinfo_from_fpm(dev, hmc_fn_id);
3588                poll_registers = false;
3589        }
3590        if (!hmc_info)
3591                return I40IW_ERR_BAD_PTR;
3592
3593        obj_info = hmc_info->hmc_obj;
3594        buf = dev->fpm_commit_buf;
3595
3596        /* copy cnt values in commit buf */
3597        for (i = I40IW_HMC_IW_QP, j = 0; i <= I40IW_HMC_IW_PBLE;
3598             i++, j += 8)
3599                set_64bit_val(buf, j, (u64)obj_info[i].cnt);
3600
3601        set_64bit_val(buf, 40, 0);   /* APBVT rsvd */
3602
3603        commit_fpm_mem.pa = dev->fpm_commit_buf_pa;
3604        commit_fpm_mem.va = dev->fpm_commit_buf;
3605        wait_type = poll_registers ? (u8)I40IW_CQP_WAIT_POLL_REGS :
3606                        (u8)I40IW_CQP_WAIT_POLL_CQ;
3607        ret_code = i40iw_sc_commit_fpm_values(
3608                                        dev->cqp,
3609                                        0,
3610                                        hmc_info->hmc_fn_id,
3611                                        &commit_fpm_mem,
3612                                        true,
3613                                        wait_type);
3614
3615        /* parse the fpm_commit_buf and fill hmc obj info */
3616        if (!ret_code)
3617                ret_code = i40iw_sc_parse_fpm_commit_buf(dev->fpm_commit_buf,
3618                                                         hmc_info->hmc_obj,
3619                                                         &hmc_info->sd_table.sd_cnt);
3620
3621        i40iw_debug_buf(dev, I40IW_DEBUG_HMC, "COMMIT FPM BUFFER",
3622                        commit_fpm_mem.va, I40IW_COMMIT_FPM_BUF_SIZE);
3623
3624        return ret_code;
3625}
3626
3627/**
3628 * cqp_sds_wqe_fill - fill cqp wqe doe sd
3629 * @cqp: struct for cqp hw
3630 * @info; sd info for wqe
3631 * @scratch: u64 saved to be used during cqp completion
3632 */
3633static enum i40iw_status_code cqp_sds_wqe_fill(struct i40iw_sc_cqp *cqp,
3634                                               struct i40iw_update_sds_info *info,
3635                                               u64 scratch)
3636{
3637        u64 data;
3638        u64 header;
3639        u64 *wqe;
3640        int mem_entries, wqe_entries;
3641        struct i40iw_dma_mem *sdbuf = &cqp->sdbuf;
3642        u64 offset;
3643        u32 wqe_idx;
3644
3645        wqe = i40iw_sc_cqp_get_next_send_wqe_idx(cqp, scratch, &wqe_idx);
3646        if (!wqe)
3647                return I40IW_ERR_RING_FULL;
3648
3649        I40IW_CQP_INIT_WQE(wqe);
3650        wqe_entries = (info->cnt > 3) ? 3 : info->cnt;
3651        mem_entries = info->cnt - wqe_entries;
3652
3653        header = LS_64(I40IW_CQP_OP_UPDATE_PE_SDS, I40IW_CQPSQ_OPCODE) |
3654                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID) |
3655                 LS_64(mem_entries, I40IW_CQPSQ_UPESD_ENTRY_COUNT);
3656
3657        if (mem_entries) {
3658                offset = wqe_idx * I40IW_UPDATE_SD_BUF_SIZE;
3659                memcpy((char *)sdbuf->va + offset, &info->entry[3],
3660                       mem_entries << 4);
3661                data = (u64)sdbuf->pa + offset;
3662        } else {
3663                data = 0;
3664        }
3665        data |= LS_64(info->hmc_fn_id, I40IW_CQPSQ_UPESD_HMCFNID);
3666
3667        set_64bit_val(wqe, 16, data);
3668
3669        switch (wqe_entries) {
3670        case 3:
3671                set_64bit_val(wqe, 48,
3672                              (LS_64(info->entry[2].cmd, I40IW_CQPSQ_UPESD_SDCMD) |
3673                                        LS_64(1, I40IW_CQPSQ_UPESD_ENTRY_VALID)));
3674
3675                set_64bit_val(wqe, 56, info->entry[2].data);
3676                /* fallthrough */
3677        case 2:
3678                set_64bit_val(wqe, 32,
3679                              (LS_64(info->entry[1].cmd, I40IW_CQPSQ_UPESD_SDCMD) |
3680                                        LS_64(1, I40IW_CQPSQ_UPESD_ENTRY_VALID)));
3681
3682                set_64bit_val(wqe, 40, info->entry[1].data);
3683                /* fallthrough */
3684        case 1:
3685                set_64bit_val(wqe, 0,
3686                              LS_64(info->entry[0].cmd, I40IW_CQPSQ_UPESD_SDCMD));
3687
3688                set_64bit_val(wqe, 8, info->entry[0].data);
3689                break;
3690        default:
3691                break;
3692        }
3693
3694        i40iw_insert_wqe_hdr(wqe, header);
3695
3696        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "UPDATE_PE_SDS WQE",
3697                        wqe, I40IW_CQP_WQE_SIZE * 8);
3698        return 0;
3699}
3700
3701/**
3702 * i40iw_update_pe_sds - cqp wqe for sd
3703 * @dev: ptr to i40iw_dev struct
3704 * @info: sd info for sd's
3705 * @scratch: u64 saved to be used during cqp completion
3706 */
3707static enum i40iw_status_code i40iw_update_pe_sds(struct i40iw_sc_dev *dev,
3708                                                  struct i40iw_update_sds_info *info,
3709                                                  u64 scratch)
3710{
3711        struct i40iw_sc_cqp *cqp = dev->cqp;
3712        enum i40iw_status_code ret_code;
3713
3714        ret_code = cqp_sds_wqe_fill(cqp, info, scratch);
3715        if (!ret_code)
3716                i40iw_sc_cqp_post_sq(cqp);
3717
3718        return ret_code;
3719}
3720
3721/**
3722 * i40iw_update_sds_noccq - update sd before ccq created
3723 * @dev: sc device struct
3724 * @info: sd info for sd's
3725 */
3726enum i40iw_status_code i40iw_update_sds_noccq(struct i40iw_sc_dev *dev,
3727                                              struct i40iw_update_sds_info *info)
3728{
3729        u32 error, val, tail;
3730        struct i40iw_sc_cqp *cqp = dev->cqp;
3731        enum i40iw_status_code ret_code;
3732
3733        ret_code = cqp_sds_wqe_fill(cqp, info, 0);
3734        if (ret_code)
3735                return ret_code;
3736        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
3737        if (error)
3738                return I40IW_ERR_CQP_COMPL_ERROR;
3739
3740        i40iw_sc_cqp_post_sq(cqp);
3741        ret_code = i40iw_cqp_poll_registers(cqp, tail, I40IW_DONE_COUNT);
3742
3743        return ret_code;
3744}
3745
3746/**
3747 * i40iw_sc_suspend_qp - suspend qp for param change
3748 * @cqp: struct for cqp hw
3749 * @qp: sc qp struct
3750 * @scratch: u64 saved to be used during cqp completion
3751 */
3752enum i40iw_status_code i40iw_sc_suspend_qp(struct i40iw_sc_cqp *cqp,
3753                                           struct i40iw_sc_qp *qp,
3754                                           u64 scratch)
3755{
3756        u64 header;
3757        u64 *wqe;
3758
3759        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3760        if (!wqe)
3761                return I40IW_ERR_RING_FULL;
3762        header = LS_64(qp->qp_uk.qp_id, I40IW_CQPSQ_SUSPENDQP_QPID) |
3763                 LS_64(I40IW_CQP_OP_SUSPEND_QP, I40IW_CQPSQ_OPCODE) |
3764                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3765
3766        i40iw_insert_wqe_hdr(wqe, header);
3767
3768        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "SUSPEND_QP WQE",
3769                        wqe, I40IW_CQP_WQE_SIZE * 8);
3770
3771        i40iw_sc_cqp_post_sq(cqp);
3772        return 0;
3773}
3774
3775/**
3776 * i40iw_sc_resume_qp - resume qp after suspend
3777 * @cqp: struct for cqp hw
3778 * @qp: sc qp struct
3779 * @scratch: u64 saved to be used during cqp completion
3780 */
3781enum i40iw_status_code i40iw_sc_resume_qp(struct i40iw_sc_cqp *cqp,
3782                                          struct i40iw_sc_qp *qp,
3783                                          u64 scratch)
3784{
3785        u64 header;
3786        u64 *wqe;
3787
3788        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3789        if (!wqe)
3790                return I40IW_ERR_RING_FULL;
3791        set_64bit_val(wqe,
3792                      16,
3793                        LS_64(qp->qs_handle, I40IW_CQPSQ_RESUMEQP_QSHANDLE));
3794
3795        header = LS_64(qp->qp_uk.qp_id, I40IW_CQPSQ_RESUMEQP_QPID) |
3796                 LS_64(I40IW_CQP_OP_RESUME_QP, I40IW_CQPSQ_OPCODE) |
3797                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3798
3799        i40iw_insert_wqe_hdr(wqe, header);
3800
3801        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "RESUME_QP WQE",
3802                        wqe, I40IW_CQP_WQE_SIZE * 8);
3803
3804        i40iw_sc_cqp_post_sq(cqp);
3805        return 0;
3806}
3807
3808/**
3809 * i40iw_sc_static_hmc_pages_allocated - cqp wqe to allocate hmc pages
3810 * @cqp: struct for cqp hw
3811 * @scratch: u64 saved to be used during cqp completion
3812 * @hmc_fn_id: hmc function id
3813 * @post_sq: flag for cqp db to ring
3814 * @poll_registers: flag to poll register for cqp completion
3815 */
3816enum i40iw_status_code i40iw_sc_static_hmc_pages_allocated(
3817                                        struct i40iw_sc_cqp *cqp,
3818                                        u64 scratch,
3819                                        u8 hmc_fn_id,
3820                                        bool post_sq,
3821                                        bool poll_registers)
3822{
3823        u64 header;
3824        u64 *wqe;
3825        u32 tail, val, error;
3826        enum i40iw_status_code ret_code = 0;
3827
3828        wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
3829        if (!wqe)
3830                return I40IW_ERR_RING_FULL;
3831        set_64bit_val(wqe,
3832                      16,
3833                      LS_64(hmc_fn_id, I40IW_SHMC_PAGE_ALLOCATED_HMC_FN_ID));
3834
3835        header = LS_64(I40IW_CQP_OP_SHMC_PAGES_ALLOCATED, I40IW_CQPSQ_OPCODE) |
3836                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
3837
3838        i40iw_insert_wqe_hdr(wqe, header);
3839
3840        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_WQE, "SHMC_PAGES_ALLOCATED WQE",
3841                        wqe, I40IW_CQP_WQE_SIZE * 8);
3842        i40iw_get_cqp_reg_info(cqp, &val, &tail, &error);
3843        if (error) {
3844                ret_code = I40IW_ERR_CQP_COMPL_ERROR;
3845                return ret_code;
3846        }
3847        if (post_sq) {
3848                i40iw_sc_cqp_post_sq(cqp);
3849                if (poll_registers)
3850                        /* check for cqp sq tail update */
3851                        ret_code = i40iw_cqp_poll_registers(cqp, tail, 1000);
3852                else
3853                        ret_code = i40iw_sc_poll_for_cqp_op_done(cqp,
3854                                                                 I40IW_CQP_OP_SHMC_PAGES_ALLOCATED,
3855                                                                 NULL);
3856        }
3857
3858        return ret_code;
3859}
3860
3861/**
3862 * i40iw_ring_full - check if cqp ring is full
3863 * @cqp: struct for cqp hw
3864 */
3865static bool i40iw_ring_full(struct i40iw_sc_cqp *cqp)
3866{
3867        return I40IW_RING_FULL_ERR(cqp->sq_ring);
3868}
3869
3870/**
3871 * i40iw_est_sd - returns approximate number of SDs for HMC
3872 * @dev: sc device struct
3873 * @hmc_info: hmc structure, size and count for HMC objects
3874 */
3875static u64 i40iw_est_sd(struct i40iw_sc_dev *dev, struct i40iw_hmc_info *hmc_info)
3876{
3877        int i;
3878        u64 size = 0;
3879        u64 sd;
3880
3881        for (i = I40IW_HMC_IW_QP; i < I40IW_HMC_IW_PBLE; i++)
3882                size += hmc_info->hmc_obj[i].cnt * hmc_info->hmc_obj[i].size;
3883
3884        if (dev->is_pf)
3885                size += hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt * hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].size;
3886
3887        if (size & 0x1FFFFF)
3888                sd = (size >> 21) + 1; /* add 1 for remainder */
3889        else
3890                sd = size >> 21;
3891
3892        if (!dev->is_pf) {
3893                /* 2MB alignment for VF PBLE HMC */
3894                size = hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt * hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].size;
3895                if (size & 0x1FFFFF)
3896                        sd += (size >> 21) + 1; /* add 1 for remainder */
3897                else
3898                        sd += size >> 21;
3899        }
3900
3901        return sd;
3902}
3903
3904/**
3905 * i40iw_config_fpm_values - configure HMC objects
3906 * @dev: sc device struct
3907 * @qp_count: desired qp count
3908 */
3909enum i40iw_status_code i40iw_config_fpm_values(struct i40iw_sc_dev *dev, u32 qp_count)
3910{
3911        struct i40iw_virt_mem virt_mem;
3912        u32 i, mem_size;
3913        u32 qpwantedoriginal, qpwanted, mrwanted, pblewanted;
3914        u64 sd_needed;
3915        u32 loop_count = 0;
3916
3917        struct i40iw_hmc_info *hmc_info;
3918        struct i40iw_hmc_fpm_misc *hmc_fpm_misc;
3919        enum i40iw_status_code ret_code = 0;
3920
3921        hmc_info = dev->hmc_info;
3922        hmc_fpm_misc = &dev->hmc_fpm_misc;
3923
3924        ret_code = i40iw_sc_init_iw_hmc(dev, dev->hmc_fn_id);
3925        if (ret_code) {
3926                i40iw_debug(dev, I40IW_DEBUG_HMC,
3927                            "i40iw_sc_init_iw_hmc returned error_code = %d\n",
3928                            ret_code);
3929                return ret_code;
3930        }
3931
3932        for (i = I40IW_HMC_IW_QP; i < I40IW_HMC_IW_MAX; i++)
3933                hmc_info->hmc_obj[i].cnt = hmc_info->hmc_obj[i].max_cnt;
3934        sd_needed = i40iw_est_sd(dev, hmc_info);
3935        i40iw_debug(dev, I40IW_DEBUG_HMC,
3936                    "%s: FW initial max sd_count[%08lld] first_sd_index[%04d]\n",
3937                    __func__, sd_needed, hmc_info->first_sd_index);
3938        i40iw_debug(dev, I40IW_DEBUG_HMC,
3939                    "%s: sd count %d where max sd is %d\n",
3940                    __func__, hmc_info->sd_table.sd_cnt,
3941                    hmc_fpm_misc->max_sds);
3942
3943        qpwanted = min(qp_count, hmc_info->hmc_obj[I40IW_HMC_IW_QP].max_cnt);
3944        qpwantedoriginal = qpwanted;
3945        mrwanted = hmc_info->hmc_obj[I40IW_HMC_IW_MR].max_cnt;
3946        pblewanted = hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].max_cnt;
3947
3948        i40iw_debug(dev, I40IW_DEBUG_HMC,
3949                    "req_qp=%d max_sd=%d, max_qp = %d, max_cq=%d, max_mr=%d, max_pble=%d\n",
3950                    qp_count, hmc_fpm_misc->max_sds,
3951                    hmc_info->hmc_obj[I40IW_HMC_IW_QP].max_cnt,
3952                    hmc_info->hmc_obj[I40IW_HMC_IW_CQ].max_cnt,
3953                    hmc_info->hmc_obj[I40IW_HMC_IW_MR].max_cnt,
3954                    hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].max_cnt);
3955
3956        do {
3957                ++loop_count;
3958                hmc_info->hmc_obj[I40IW_HMC_IW_QP].cnt = qpwanted;
3959                hmc_info->hmc_obj[I40IW_HMC_IW_CQ].cnt =
3960                        min(2 * qpwanted, hmc_info->hmc_obj[I40IW_HMC_IW_CQ].cnt);
3961                hmc_info->hmc_obj[I40IW_HMC_IW_SRQ].cnt = 0x00; /* Reserved */
3962                hmc_info->hmc_obj[I40IW_HMC_IW_HTE].cnt =
3963                                        qpwanted * hmc_fpm_misc->ht_multiplier;
3964                hmc_info->hmc_obj[I40IW_HMC_IW_ARP].cnt =
3965                        hmc_info->hmc_obj[I40IW_HMC_IW_ARP].max_cnt;
3966                hmc_info->hmc_obj[I40IW_HMC_IW_APBVT_ENTRY].cnt = 1;
3967                hmc_info->hmc_obj[I40IW_HMC_IW_MR].cnt = mrwanted;
3968
3969                hmc_info->hmc_obj[I40IW_HMC_IW_XF].cnt =
3970                        roundup_pow_of_two(I40IW_MAX_WQ_ENTRIES * qpwanted);
3971                hmc_info->hmc_obj[I40IW_HMC_IW_Q1].cnt =
3972                        roundup_pow_of_two(2 * I40IW_MAX_IRD_SIZE * qpwanted);
3973                hmc_info->hmc_obj[I40IW_HMC_IW_XFFL].cnt =
3974                        hmc_info->hmc_obj[I40IW_HMC_IW_XF].cnt / hmc_fpm_misc->xf_block_size;
3975                hmc_info->hmc_obj[I40IW_HMC_IW_Q1FL].cnt =
3976                        hmc_info->hmc_obj[I40IW_HMC_IW_Q1].cnt / hmc_fpm_misc->q1_block_size;
3977                hmc_info->hmc_obj[I40IW_HMC_IW_TIMER].cnt =
3978                        ((qpwanted) / 512 + 1) * hmc_fpm_misc->timer_bucket;
3979                hmc_info->hmc_obj[I40IW_HMC_IW_FSIMC].cnt = 0x00;
3980                hmc_info->hmc_obj[I40IW_HMC_IW_FSIAV].cnt = 0x00;
3981                hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt = pblewanted;
3982
3983                /* How much memory is needed for all the objects. */
3984                sd_needed = i40iw_est_sd(dev, hmc_info);
3985                if ((loop_count > 1000) ||
3986                    ((!(loop_count % 10)) &&
3987                    (qpwanted > qpwantedoriginal * 2 / 3))) {
3988                        if (qpwanted > FPM_MULTIPLIER)
3989                                qpwanted = roundup_pow_of_two(qpwanted -
3990                                                              FPM_MULTIPLIER);
3991                        qpwanted >>= 1;
3992                }
3993                if (mrwanted > FPM_MULTIPLIER * 10)
3994                        mrwanted -= FPM_MULTIPLIER * 10;
3995                if (pblewanted > FPM_MULTIPLIER * 1000)
3996                        pblewanted -= FPM_MULTIPLIER * 1000;
3997        } while (sd_needed > hmc_fpm_misc->max_sds && loop_count < 2000);
3998
3999        i40iw_debug(dev, I40IW_DEBUG_HMC,
4000                    "loop_cnt=%d, sd_needed=%lld, qpcnt = %d, cqcnt=%d, mrcnt=%d, pblecnt=%d\n",
4001                    loop_count, sd_needed,
4002                    hmc_info->hmc_obj[I40IW_HMC_IW_QP].cnt,
4003                    hmc_info->hmc_obj[I40IW_HMC_IW_CQ].cnt,
4004                    hmc_info->hmc_obj[I40IW_HMC_IW_MR].cnt,
4005                    hmc_info->hmc_obj[I40IW_HMC_IW_PBLE].cnt);
4006
4007        ret_code = i40iw_sc_configure_iw_fpm(dev, dev->hmc_fn_id);
4008        if (ret_code) {
4009                i40iw_debug(dev, I40IW_DEBUG_HMC,
4010                            "configure_iw_fpm returned error_code[x%08X]\n",
4011                            i40iw_rd32(dev->hw, dev->is_pf ? I40E_PFPE_CQPERRCODES : I40E_VFPE_CQPERRCODES1));
4012                return ret_code;
4013        }
4014
4015        mem_size = sizeof(struct i40iw_hmc_sd_entry) *
4016                   (hmc_info->sd_table.sd_cnt + hmc_info->first_sd_index + 1);
4017        ret_code = i40iw_allocate_virt_mem(dev->hw, &virt_mem, mem_size);
4018        if (ret_code) {
4019                i40iw_debug(dev, I40IW_DEBUG_HMC,
4020                            "%s: failed to allocate memory for sd_entry buffer\n",
4021                            __func__);
4022                return ret_code;
4023        }
4024        hmc_info->sd_table.sd_entry = virt_mem.va;
4025
4026        return ret_code;
4027}
4028
4029/**
4030 * i40iw_exec_cqp_cmd - execute cqp cmd when wqe are available
4031 * @dev: rdma device
4032 * @pcmdinfo: cqp command info
4033 */
4034static enum i40iw_status_code i40iw_exec_cqp_cmd(struct i40iw_sc_dev *dev,
4035                                                 struct cqp_commands_info *pcmdinfo)
4036{
4037        enum i40iw_status_code status;
4038        struct i40iw_dma_mem values_mem;
4039
4040        dev->cqp_cmd_stats[pcmdinfo->cqp_cmd]++;
4041        switch (pcmdinfo->cqp_cmd) {
4042        case OP_DELETE_LOCAL_MAC_IPADDR_ENTRY:
4043                status = i40iw_sc_del_local_mac_ipaddr_entry(
4044                                pcmdinfo->in.u.del_local_mac_ipaddr_entry.cqp,
4045                                pcmdinfo->in.u.del_local_mac_ipaddr_entry.scratch,
4046                                pcmdinfo->in.u.del_local_mac_ipaddr_entry.entry_idx,
4047                                pcmdinfo->in.u.del_local_mac_ipaddr_entry.ignore_ref_count,
4048                                pcmdinfo->post_sq);
4049                break;
4050        case OP_CEQ_DESTROY:
4051                status = i40iw_sc_ceq_destroy(pcmdinfo->in.u.ceq_destroy.ceq,
4052                                              pcmdinfo->in.u.ceq_destroy.scratch,
4053                                              pcmdinfo->post_sq);
4054                break;
4055        case OP_AEQ_DESTROY:
4056                status = i40iw_sc_aeq_destroy(pcmdinfo->in.u.aeq_destroy.aeq,
4057                                              pcmdinfo->in.u.aeq_destroy.scratch,
4058                                              pcmdinfo->post_sq);
4059
4060                break;
4061        case OP_DELETE_ARP_CACHE_ENTRY:
4062                status = i40iw_sc_del_arp_cache_entry(
4063                                pcmdinfo->in.u.del_arp_cache_entry.cqp,
4064                                pcmdinfo->in.u.del_arp_cache_entry.scratch,
4065                                pcmdinfo->in.u.del_arp_cache_entry.arp_index,
4066                                pcmdinfo->post_sq);
4067                break;
4068        case OP_MANAGE_APBVT_ENTRY:
4069                status = i40iw_sc_manage_apbvt_entry(
4070                                pcmdinfo->in.u.manage_apbvt_entry.cqp,
4071                                &pcmdinfo->in.u.manage_apbvt_entry.info,
4072                                pcmdinfo->in.u.manage_apbvt_entry.scratch,
4073                                pcmdinfo->post_sq);
4074                break;
4075        case OP_CEQ_CREATE:
4076                status = i40iw_sc_ceq_create(pcmdinfo->in.u.ceq_create.ceq,
4077                                             pcmdinfo->in.u.ceq_create.scratch,
4078                                             pcmdinfo->post_sq);
4079                break;
4080        case OP_AEQ_CREATE:
4081                status = i40iw_sc_aeq_create(pcmdinfo->in.u.aeq_create.aeq,
4082                                             pcmdinfo->in.u.aeq_create.scratch,
4083                                             pcmdinfo->post_sq);
4084                break;
4085        case OP_ALLOC_LOCAL_MAC_IPADDR_ENTRY:
4086                status = i40iw_sc_alloc_local_mac_ipaddr_entry(
4087                                pcmdinfo->in.u.alloc_local_mac_ipaddr_entry.cqp,
4088                                pcmdinfo->in.u.alloc_local_mac_ipaddr_entry.scratch,
4089                                pcmdinfo->post_sq);
4090                break;
4091        case OP_ADD_LOCAL_MAC_IPADDR_ENTRY:
4092                status = i40iw_sc_add_local_mac_ipaddr_entry(
4093                                pcmdinfo->in.u.add_local_mac_ipaddr_entry.cqp,
4094                                &pcmdinfo->in.u.add_local_mac_ipaddr_entry.info,
4095                                pcmdinfo->in.u.add_local_mac_ipaddr_entry.scratch,
4096                                pcmdinfo->post_sq);
4097                break;
4098        case OP_MANAGE_QHASH_TABLE_ENTRY:
4099                status = i40iw_sc_manage_qhash_table_entry(
4100                                pcmdinfo->in.u.manage_qhash_table_entry.cqp,
4101                                &pcmdinfo->in.u.manage_qhash_table_entry.info,
4102                                pcmdinfo->in.u.manage_qhash_table_entry.scratch,
4103                                pcmdinfo->post_sq);
4104
4105                break;
4106        case OP_QP_MODIFY:
4107                status = i40iw_sc_qp_modify(
4108                                pcmdinfo->in.u.qp_modify.qp,
4109                                &pcmdinfo->in.u.qp_modify.info,
4110                                pcmdinfo->in.u.qp_modify.scratch,
4111                                pcmdinfo->post_sq);
4112
4113                break;
4114        case OP_QP_UPLOAD_CONTEXT:
4115                status = i40iw_sc_qp_upload_context(
4116                                pcmdinfo->in.u.qp_upload_context.dev,
4117                                &pcmdinfo->in.u.qp_upload_context.info,
4118                                pcmdinfo->in.u.qp_upload_context.scratch,
4119                                pcmdinfo->post_sq);
4120
4121                break;
4122        case OP_CQ_CREATE:
4123                status = i40iw_sc_cq_create(
4124                                pcmdinfo->in.u.cq_create.cq,
4125                                pcmdinfo->in.u.cq_create.scratch,
4126                                pcmdinfo->in.u.cq_create.check_overflow,
4127                                pcmdinfo->post_sq);
4128                break;
4129        case OP_CQ_DESTROY:
4130                status = i40iw_sc_cq_destroy(
4131                                pcmdinfo->in.u.cq_destroy.cq,
4132                                pcmdinfo->in.u.cq_destroy.scratch,
4133                                pcmdinfo->post_sq);
4134
4135                break;
4136        case OP_QP_CREATE:
4137                status = i40iw_sc_qp_create(
4138                                pcmdinfo->in.u.qp_create.qp,
4139                                &pcmdinfo->in.u.qp_create.info,
4140                                pcmdinfo->in.u.qp_create.scratch,
4141                                pcmdinfo->post_sq);
4142                break;
4143        case OP_QP_DESTROY:
4144                status = i40iw_sc_qp_destroy(
4145                                pcmdinfo->in.u.qp_destroy.qp,
4146                                pcmdinfo->in.u.qp_destroy.scratch,
4147                                pcmdinfo->in.u.qp_destroy.remove_hash_idx,
4148                                pcmdinfo->in.u.qp_destroy.
4149                                ignore_mw_bnd,
4150                                pcmdinfo->post_sq);
4151
4152                break;
4153        case OP_ALLOC_STAG:
4154                status = i40iw_sc_alloc_stag(
4155                                pcmdinfo->in.u.alloc_stag.dev,
4156                                &pcmdinfo->in.u.alloc_stag.info,
4157                                pcmdinfo->in.u.alloc_stag.scratch,
4158                                pcmdinfo->post_sq);
4159                break;
4160        case OP_MR_REG_NON_SHARED:
4161                status = i40iw_sc_mr_reg_non_shared(
4162                                pcmdinfo->in.u.mr_reg_non_shared.dev,
4163                                &pcmdinfo->in.u.mr_reg_non_shared.info,
4164                                pcmdinfo->in.u.mr_reg_non_shared.scratch,
4165                                pcmdinfo->post_sq);
4166
4167                break;
4168        case OP_DEALLOC_STAG:
4169                status = i40iw_sc_dealloc_stag(
4170                                pcmdinfo->in.u.dealloc_stag.dev,
4171                                &pcmdinfo->in.u.dealloc_stag.info,
4172                                pcmdinfo->in.u.dealloc_stag.scratch,
4173                                pcmdinfo->post_sq);
4174
4175                break;
4176        case OP_MW_ALLOC:
4177                status = i40iw_sc_mw_alloc(
4178                                pcmdinfo->in.u.mw_alloc.dev,
4179                                pcmdinfo->in.u.mw_alloc.scratch,
4180                                pcmdinfo->in.u.mw_alloc.mw_stag_index,
4181                                pcmdinfo->in.u.mw_alloc.pd_id,
4182                                pcmdinfo->post_sq);
4183
4184                break;
4185        case OP_QP_FLUSH_WQES:
4186                status = i40iw_sc_qp_flush_wqes(
4187                                pcmdinfo->in.u.qp_flush_wqes.qp,
4188                                &pcmdinfo->in.u.qp_flush_wqes.info,
4189                                pcmdinfo->in.u.qp_flush_wqes.
4190                                scratch, pcmdinfo->post_sq);
4191                break;
4192        case OP_GEN_AE:
4193                status = i40iw_sc_gen_ae(
4194                                pcmdinfo->in.u.gen_ae.qp,
4195                                &pcmdinfo->in.u.gen_ae.info,
4196                                pcmdinfo->in.u.gen_ae.scratch,
4197                                pcmdinfo->post_sq);
4198                break;
4199        case OP_ADD_ARP_CACHE_ENTRY:
4200                status = i40iw_sc_add_arp_cache_entry(
4201                                pcmdinfo->in.u.add_arp_cache_entry.cqp,
4202                                &pcmdinfo->in.u.add_arp_cache_entry.info,
4203                                pcmdinfo->in.u.add_arp_cache_entry.scratch,
4204                                pcmdinfo->post_sq);
4205                break;
4206        case OP_MANAGE_PUSH_PAGE:
4207                status = i40iw_sc_manage_push_page(
4208                                pcmdinfo->in.u.manage_push_page.cqp,
4209                                &pcmdinfo->in.u.manage_push_page.info,
4210                                pcmdinfo->in.u.manage_push_page.scratch,
4211                                pcmdinfo->post_sq);
4212                break;
4213        case OP_UPDATE_PE_SDS:
4214                /* case I40IW_CQP_OP_UPDATE_PE_SDS */
4215                status = i40iw_update_pe_sds(
4216                                pcmdinfo->in.u.update_pe_sds.dev,
4217                                &pcmdinfo->in.u.update_pe_sds.info,
4218                                pcmdinfo->in.u.update_pe_sds.
4219                                scratch);
4220
4221                break;
4222        case OP_MANAGE_HMC_PM_FUNC_TABLE:
4223                status = i40iw_sc_manage_hmc_pm_func_table(
4224                                pcmdinfo->in.u.manage_hmc_pm.dev->cqp,
4225                                pcmdinfo->in.u.manage_hmc_pm.scratch,
4226                                (u8)pcmdinfo->in.u.manage_hmc_pm.info.vf_id,
4227                                pcmdinfo->in.u.manage_hmc_pm.info.free_fcn,
4228                                true);
4229                break;
4230        case OP_SUSPEND:
4231                status = i40iw_sc_suspend_qp(
4232                                pcmdinfo->in.u.suspend_resume.cqp,
4233                                pcmdinfo->in.u.suspend_resume.qp,
4234                                pcmdinfo->in.u.suspend_resume.scratch);
4235                break;
4236        case OP_RESUME:
4237                status = i40iw_sc_resume_qp(
4238                                pcmdinfo->in.u.suspend_resume.cqp,
4239                                pcmdinfo->in.u.suspend_resume.qp,
4240                                pcmdinfo->in.u.suspend_resume.scratch);
4241                break;
4242        case OP_MANAGE_VF_PBLE_BP:
4243                status = i40iw_manage_vf_pble_bp(
4244                                pcmdinfo->in.u.manage_vf_pble_bp.cqp,
4245                                &pcmdinfo->in.u.manage_vf_pble_bp.info,
4246                                pcmdinfo->in.u.manage_vf_pble_bp.scratch, true);
4247                break;
4248        case OP_QUERY_FPM_VALUES:
4249                values_mem.pa = pcmdinfo->in.u.query_fpm_values.fpm_values_pa;
4250                values_mem.va = pcmdinfo->in.u.query_fpm_values.fpm_values_va;
4251                status = i40iw_sc_query_fpm_values(
4252                                pcmdinfo->in.u.query_fpm_values.cqp,
4253                                pcmdinfo->in.u.query_fpm_values.scratch,
4254                                pcmdinfo->in.u.query_fpm_values.hmc_fn_id,
4255                                &values_mem, true, I40IW_CQP_WAIT_EVENT);
4256                break;
4257        case OP_COMMIT_FPM_VALUES:
4258                values_mem.pa = pcmdinfo->in.u.commit_fpm_values.fpm_values_pa;
4259                values_mem.va = pcmdinfo->in.u.commit_fpm_values.fpm_values_va;
4260                status = i40iw_sc_commit_fpm_values(
4261                                pcmdinfo->in.u.commit_fpm_values.cqp,
4262                                pcmdinfo->in.u.commit_fpm_values.scratch,
4263                                pcmdinfo->in.u.commit_fpm_values.hmc_fn_id,
4264                                &values_mem,
4265                                true,
4266                                I40IW_CQP_WAIT_EVENT);
4267                break;
4268        default:
4269                status = I40IW_NOT_SUPPORTED;
4270                break;
4271        }
4272
4273        return status;
4274}
4275
4276/**
4277 * i40iw_process_cqp_cmd - process all cqp commands
4278 * @dev: sc device struct
4279 * @pcmdinfo: cqp command info
4280 */
4281enum i40iw_status_code i40iw_process_cqp_cmd(struct i40iw_sc_dev *dev,
4282                                             struct cqp_commands_info *pcmdinfo)
4283{
4284        enum i40iw_status_code status = 0;
4285        unsigned long flags;
4286
4287        spin_lock_irqsave(&dev->cqp_lock, flags);
4288        if (list_empty(&dev->cqp_cmd_head) && !i40iw_ring_full(dev->cqp))
4289                status = i40iw_exec_cqp_cmd(dev, pcmdinfo);
4290        else
4291                list_add_tail(&pcmdinfo->cqp_cmd_entry, &dev->cqp_cmd_head);
4292        spin_unlock_irqrestore(&dev->cqp_lock, flags);
4293        return status;
4294}
4295
4296/**
4297 * i40iw_process_bh - called from tasklet for cqp list
4298 * @dev: sc device struct
4299 */
4300enum i40iw_status_code i40iw_process_bh(struct i40iw_sc_dev *dev)
4301{
4302        enum i40iw_status_code status = 0;
4303        struct cqp_commands_info *pcmdinfo;
4304        unsigned long flags;
4305
4306        spin_lock_irqsave(&dev->cqp_lock, flags);
4307        while (!list_empty(&dev->cqp_cmd_head) && !i40iw_ring_full(dev->cqp)) {
4308                pcmdinfo = (struct cqp_commands_info *)i40iw_remove_head(&dev->cqp_cmd_head);
4309
4310                status = i40iw_exec_cqp_cmd(dev, pcmdinfo);
4311                if (status)
4312                        break;
4313        }
4314        spin_unlock_irqrestore(&dev->cqp_lock, flags);
4315        return status;
4316}
4317
4318/**
4319 * i40iw_iwarp_opcode - determine if incoming is rdma layer
4320 * @info: aeq info for the packet
4321 * @pkt: packet for error
4322 */
4323static u32 i40iw_iwarp_opcode(struct i40iw_aeqe_info *info, u8 *pkt)
4324{
4325        __be16 *mpa;
4326        u32 opcode = 0xffffffff;
4327
4328        if (info->q2_data_written) {
4329                mpa = (__be16 *)pkt;
4330                opcode = ntohs(mpa[1]) & 0xf;
4331        }
4332        return opcode;
4333}
4334
4335/**
4336 * i40iw_locate_mpa - return pointer to mpa in the pkt
4337 * @pkt: packet with data
4338 */
4339static u8 *i40iw_locate_mpa(u8 *pkt)
4340{
4341        /* skip over ethernet header */
4342        pkt += I40IW_MAC_HLEN;
4343
4344        /* Skip over IP and TCP headers */
4345        pkt += 4 * (pkt[0] & 0x0f);
4346        pkt += 4 * ((pkt[12] >> 4) & 0x0f);
4347        return pkt;
4348}
4349
4350/**
4351 * i40iw_setup_termhdr - termhdr for terminate pkt
4352 * @qp: sc qp ptr for pkt
4353 * @hdr: term hdr
4354 * @opcode: flush opcode for termhdr
4355 * @layer_etype: error layer + error type
4356 * @err: error cod ein the header
4357 */
4358static void i40iw_setup_termhdr(struct i40iw_sc_qp *qp,
4359                                struct i40iw_terminate_hdr *hdr,
4360                                enum i40iw_flush_opcode opcode,
4361                                u8 layer_etype,
4362                                u8 err)
4363{
4364        qp->flush_code = opcode;
4365        hdr->layer_etype = layer_etype;
4366        hdr->error_code = err;
4367}
4368
4369/**
4370 * i40iw_bld_terminate_hdr - build terminate message header
4371 * @qp: qp associated with received terminate AE
4372 * @info: the struct contiaing AE information
4373 */
4374static int i40iw_bld_terminate_hdr(struct i40iw_sc_qp *qp,
4375                                   struct i40iw_aeqe_info *info)
4376{
4377        u8 *pkt = qp->q2_buf + Q2_BAD_FRAME_OFFSET;
4378        u16 ddp_seg_len;
4379        int copy_len = 0;
4380        u8 is_tagged = 0;
4381        u32 opcode;
4382        struct i40iw_terminate_hdr *termhdr;
4383
4384        termhdr = (struct i40iw_terminate_hdr *)qp->q2_buf;
4385        memset(termhdr, 0, Q2_BAD_FRAME_OFFSET);
4386
4387        if (info->q2_data_written) {
4388                /* Use data from offending packet to fill in ddp & rdma hdrs */
4389                pkt = i40iw_locate_mpa(pkt);
4390                ddp_seg_len = ntohs(*(__be16 *)pkt);
4391                if (ddp_seg_len) {
4392                        copy_len = 2;
4393                        termhdr->hdrct = DDP_LEN_FLAG;
4394                        if (pkt[2] & 0x80) {
4395                                is_tagged = 1;
4396                                if (ddp_seg_len >= TERM_DDP_LEN_TAGGED) {
4397                                        copy_len += TERM_DDP_LEN_TAGGED;
4398                                        termhdr->hdrct |= DDP_HDR_FLAG;
4399                                }
4400                        } else {
4401                                if (ddp_seg_len >= TERM_DDP_LEN_UNTAGGED) {
4402                                        copy_len += TERM_DDP_LEN_UNTAGGED;
4403                                        termhdr->hdrct |= DDP_HDR_FLAG;
4404                                }
4405
4406                                if (ddp_seg_len >= (TERM_DDP_LEN_UNTAGGED + TERM_RDMA_LEN)) {
4407                                        if ((pkt[3] & RDMA_OPCODE_MASK) == RDMA_READ_REQ_OPCODE) {
4408                                                copy_len += TERM_RDMA_LEN;
4409                                                termhdr->hdrct |= RDMA_HDR_FLAG;
4410                                        }
4411                                }
4412                        }
4413                }
4414        }
4415
4416        opcode = i40iw_iwarp_opcode(info, pkt);
4417
4418        switch (info->ae_id) {
4419        case I40IW_AE_AMP_UNALLOCATED_STAG:
4420                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4421                if (opcode == I40IW_OP_TYPE_RDMA_WRITE)
4422                        i40iw_setup_termhdr(qp, termhdr, FLUSH_PROT_ERR,
4423                                            (LAYER_DDP << 4) | DDP_TAGGED_BUFFER, DDP_TAGGED_INV_STAG);
4424                else
4425                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4426                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_INV_STAG);
4427                break;
4428        case I40IW_AE_AMP_BOUNDS_VIOLATION:
4429                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4430                if (info->q2_data_written)
4431                        i40iw_setup_termhdr(qp, termhdr, FLUSH_PROT_ERR,
4432                                            (LAYER_DDP << 4) | DDP_TAGGED_BUFFER, DDP_TAGGED_BOUNDS);
4433                else
4434                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4435                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_INV_BOUNDS);
4436                break;
4437        case I40IW_AE_AMP_BAD_PD:
4438                switch (opcode) {
4439                case I40IW_OP_TYPE_RDMA_WRITE:
4440                        i40iw_setup_termhdr(qp, termhdr, FLUSH_PROT_ERR,
4441                                            (LAYER_DDP << 4) | DDP_TAGGED_BUFFER, DDP_TAGGED_UNASSOC_STAG);
4442                        break;
4443                case I40IW_OP_TYPE_SEND_INV:
4444                case I40IW_OP_TYPE_SEND_SOL_INV:
4445                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4446                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_CANT_INV_STAG);
4447                        break;
4448                default:
4449                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4450                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_UNASSOC_STAG);
4451                }
4452                break;
4453        case I40IW_AE_AMP_INVALID_STAG:
4454                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4455                i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4456                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_INV_STAG);
4457                break;
4458        case I40IW_AE_AMP_BAD_QP:
4459                i40iw_setup_termhdr(qp, termhdr, FLUSH_LOC_QP_OP_ERR,
4460                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_QN);
4461                break;
4462        case I40IW_AE_AMP_BAD_STAG_KEY:
4463        case I40IW_AE_AMP_BAD_STAG_INDEX:
4464                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4465                switch (opcode) {
4466                case I40IW_OP_TYPE_SEND_INV:
4467                case I40IW_OP_TYPE_SEND_SOL_INV:
4468                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_OP_ERR,
4469                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_OP, RDMAP_CANT_INV_STAG);
4470                        break;
4471                default:
4472                        i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4473                                            (LAYER_RDMA << 4) | RDMAP_REMOTE_OP, RDMAP_INV_STAG);
4474                }
4475                break;
4476        case I40IW_AE_AMP_RIGHTS_VIOLATION:
4477        case I40IW_AE_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:
4478        case I40IW_AE_PRIV_OPERATION_DENIED:
4479                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4480                i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4481                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_ACCESS);
4482                break;
4483        case I40IW_AE_AMP_TO_WRAP:
4484                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4485                i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_ACCESS_ERR,
4486                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT, RDMAP_TO_WRAP);
4487                break;
4488        case I40IW_AE_LLP_RECEIVED_MPA_CRC_ERROR:
4489                i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4490                                    (LAYER_MPA << 4) | DDP_LLP, MPA_CRC);
4491                break;
4492        case I40IW_AE_LLP_SEGMENT_TOO_LARGE:
4493        case I40IW_AE_LLP_SEGMENT_TOO_SMALL:
4494                i40iw_setup_termhdr(qp, termhdr, FLUSH_LOC_LEN_ERR,
4495                                    (LAYER_DDP << 4) | DDP_CATASTROPHIC, DDP_CATASTROPHIC_LOCAL);
4496                break;
4497        case I40IW_AE_LCE_QP_CATASTROPHIC:
4498        case I40IW_AE_DDP_NO_L_BIT:
4499                i40iw_setup_termhdr(qp, termhdr, FLUSH_FATAL_ERR,
4500                                    (LAYER_DDP << 4) | DDP_CATASTROPHIC, DDP_CATASTROPHIC_LOCAL);
4501                break;
4502        case I40IW_AE_DDP_INVALID_MSN_GAP_IN_MSN:
4503                i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4504                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_MSN_RANGE);
4505                break;
4506        case I40IW_AE_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
4507                qp->eventtype = TERM_EVENT_QP_ACCESS_ERR;
4508                i40iw_setup_termhdr(qp, termhdr, FLUSH_LOC_LEN_ERR,
4509                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_TOO_LONG);
4510                break;
4511        case I40IW_AE_DDP_UBE_INVALID_DDP_VERSION:
4512                if (is_tagged)
4513                        i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4514                                            (LAYER_DDP << 4) | DDP_TAGGED_BUFFER, DDP_TAGGED_INV_DDP_VER);
4515                else
4516                        i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4517                                            (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_DDP_VER);
4518                break;
4519        case I40IW_AE_DDP_UBE_INVALID_MO:
4520                i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4521                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_MO);
4522                break;
4523        case I40IW_AE_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
4524                i40iw_setup_termhdr(qp, termhdr, FLUSH_REM_OP_ERR,
4525                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_MSN_NO_BUF);
4526                break;
4527        case I40IW_AE_DDP_UBE_INVALID_QN:
4528                i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4529                                    (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER, DDP_UNTAGGED_INV_QN);
4530                break;
4531        case I40IW_AE_RDMAP_ROE_INVALID_RDMAP_VERSION:
4532                i40iw_setup_termhdr(qp, termhdr, FLUSH_GENERAL_ERR,
4533                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_OP, RDMAP_INV_RDMAP_VER);
4534                break;
4535        case I40IW_AE_RDMAP_ROE_UNEXPECTED_OPCODE:
4536                i40iw_setup_termhdr(qp, termhdr, FLUSH_LOC_QP_OP_ERR,
4537                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_OP, RDMAP_UNEXPECTED_OP);
4538                break;
4539        default:
4540                i40iw_setup_termhdr(qp, termhdr, FLUSH_FATAL_ERR,
4541                                    (LAYER_RDMA << 4) | RDMAP_REMOTE_OP, RDMAP_UNSPECIFIED);
4542                break;
4543        }
4544
4545        if (copy_len)
4546                memcpy(termhdr + 1, pkt, copy_len);
4547
4548        return sizeof(struct i40iw_terminate_hdr) + copy_len;
4549}
4550
4551/**
4552 * i40iw_terminate_send_fin() - Send fin for terminate message
4553 * @qp: qp associated with received terminate AE
4554 */
4555void i40iw_terminate_send_fin(struct i40iw_sc_qp *qp)
4556{
4557        /* Send the fin only */
4558        i40iw_term_modify_qp(qp,
4559                             I40IW_QP_STATE_TERMINATE,
4560                             I40IWQP_TERM_SEND_FIN_ONLY,
4561                             0);
4562}
4563
4564/**
4565 * i40iw_terminate_connection() - Bad AE and send terminate to remote QP
4566 * @qp: qp associated with received terminate AE
4567 * @info: the struct contiaing AE information
4568 */
4569void i40iw_terminate_connection(struct i40iw_sc_qp *qp, struct i40iw_aeqe_info *info)
4570{
4571        u8 termlen = 0;
4572
4573        if (qp->term_flags & I40IW_TERM_SENT)
4574                return;         /* Sanity check */
4575
4576        /* Eventtype can change from bld_terminate_hdr */
4577        qp->eventtype = TERM_EVENT_QP_FATAL;
4578        termlen = i40iw_bld_terminate_hdr(qp, info);
4579        i40iw_terminate_start_timer(qp);
4580        qp->term_flags |= I40IW_TERM_SENT;
4581        i40iw_term_modify_qp(qp, I40IW_QP_STATE_TERMINATE,
4582                             I40IWQP_TERM_SEND_TERM_ONLY, termlen);
4583}
4584
4585/**
4586 * i40iw_terminate_received - handle terminate received AE
4587 * @qp: qp associated with received terminate AE
4588 * @info: the struct contiaing AE information
4589 */
4590void i40iw_terminate_received(struct i40iw_sc_qp *qp, struct i40iw_aeqe_info *info)
4591{
4592        u8 *pkt = qp->q2_buf + Q2_BAD_FRAME_OFFSET;
4593        __be32 *mpa;
4594        u8 ddp_ctl;
4595        u8 rdma_ctl;
4596        u16 aeq_id = 0;
4597        struct i40iw_terminate_hdr *termhdr;
4598
4599        mpa = (__be32 *)i40iw_locate_mpa(pkt);
4600        if (info->q2_data_written) {
4601                /* did not validate the frame - do it now */
4602                ddp_ctl = (ntohl(mpa[0]) >> 8) & 0xff;
4603                rdma_ctl = ntohl(mpa[0]) & 0xff;
4604                if ((ddp_ctl & 0xc0) != 0x40)
4605                        aeq_id = I40IW_AE_LCE_QP_CATASTROPHIC;
4606                else if ((ddp_ctl & 0x03) != 1)
4607                        aeq_id = I40IW_AE_DDP_UBE_INVALID_DDP_VERSION;
4608                else if (ntohl(mpa[2]) != 2)
4609                        aeq_id = I40IW_AE_DDP_UBE_INVALID_QN;
4610                else if (ntohl(mpa[3]) != 1)
4611                        aeq_id = I40IW_AE_DDP_INVALID_MSN_GAP_IN_MSN;
4612                else if (ntohl(mpa[4]) != 0)
4613                        aeq_id = I40IW_AE_DDP_UBE_INVALID_MO;
4614                else if ((rdma_ctl & 0xc0) != 0x40)
4615                        aeq_id = I40IW_AE_RDMAP_ROE_INVALID_RDMAP_VERSION;
4616
4617                info->ae_id = aeq_id;
4618                if (info->ae_id) {
4619                        /* Bad terminate recvd - send back a terminate */
4620                        i40iw_terminate_connection(qp, info);
4621                        return;
4622                }
4623        }
4624
4625        qp->term_flags |= I40IW_TERM_RCVD;
4626        qp->eventtype = TERM_EVENT_QP_FATAL;
4627        termhdr = (struct i40iw_terminate_hdr *)&mpa[5];
4628        if (termhdr->layer_etype == RDMAP_REMOTE_PROT ||
4629            termhdr->layer_etype == RDMAP_REMOTE_OP) {
4630                i40iw_terminate_done(qp, 0);
4631        } else {
4632                i40iw_terminate_start_timer(qp);
4633                i40iw_terminate_send_fin(qp);
4634        }
4635}
4636
4637/**
4638 * i40iw_sc_vsi_init - Initialize virtual device
4639 * @vsi: pointer to the vsi structure
4640 * @info: parameters to initialize vsi
4641 **/
4642void i40iw_sc_vsi_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_init_info *info)
4643{
4644        int i;
4645
4646        vsi->dev = info->dev;
4647        vsi->back_vsi = info->back_vsi;
4648        vsi->mtu = info->params->mtu;
4649        vsi->exception_lan_queue = info->exception_lan_queue;
4650        i40iw_fill_qos_list(info->params->qs_handle_list);
4651
4652        for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
4653                vsi->qos[i].qs_handle = info->params->qs_handle_list[i];
4654                i40iw_debug(vsi->dev, I40IW_DEBUG_DCB, "qset[%d]: %d\n", i,
4655                            vsi->qos[i].qs_handle);
4656                spin_lock_init(&vsi->qos[i].lock);
4657                INIT_LIST_HEAD(&vsi->qos[i].qplist);
4658        }
4659}
4660
4661/**
4662 * i40iw_hw_stats_init - Initiliaze HW stats table
4663 * @stats: pestat struct
4664 * @fcn_idx: PCI fn id
4665 * @is_pf: Is it a PF?
4666 *
4667 * Populate the HW stats table with register offset addr for each
4668 * stats. And start the perioidic stats timer.
4669 */
4670void i40iw_hw_stats_init(struct i40iw_vsi_pestat *stats, u8 fcn_idx, bool is_pf)
4671{
4672        u32 stats_reg_offset;
4673        u32 stats_index;
4674        struct i40iw_dev_hw_stats_offsets *stats_table =
4675                &stats->hw_stats_offsets;
4676        struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
4677
4678        if (is_pf) {
4679                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
4680                                I40E_GLPES_PFIP4RXDISCARD(fcn_idx);
4681                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
4682                                I40E_GLPES_PFIP4RXTRUNC(fcn_idx);
4683                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
4684                                I40E_GLPES_PFIP4TXNOROUTE(fcn_idx);
4685                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
4686                                I40E_GLPES_PFIP6RXDISCARD(fcn_idx);
4687                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
4688                                I40E_GLPES_PFIP6RXTRUNC(fcn_idx);
4689                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
4690                                I40E_GLPES_PFIP6TXNOROUTE(fcn_idx);
4691                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
4692                                I40E_GLPES_PFTCPRTXSEG(fcn_idx);
4693                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
4694                                I40E_GLPES_PFTCPRXOPTERR(fcn_idx);
4695                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
4696                                I40E_GLPES_PFTCPRXPROTOERR(fcn_idx);
4697
4698                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
4699                                I40E_GLPES_PFIP4RXOCTSLO(fcn_idx);
4700                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
4701                                I40E_GLPES_PFIP4RXPKTSLO(fcn_idx);
4702                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
4703                                I40E_GLPES_PFIP4RXFRAGSLO(fcn_idx);
4704                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
4705                                I40E_GLPES_PFIP4RXMCPKTSLO(fcn_idx);
4706                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
4707                                I40E_GLPES_PFIP4TXOCTSLO(fcn_idx);
4708                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
4709                                I40E_GLPES_PFIP4TXPKTSLO(fcn_idx);
4710                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
4711                                I40E_GLPES_PFIP4TXFRAGSLO(fcn_idx);
4712                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
4713                                I40E_GLPES_PFIP4TXMCPKTSLO(fcn_idx);
4714                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
4715                                I40E_GLPES_PFIP6RXOCTSLO(fcn_idx);
4716                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
4717                                I40E_GLPES_PFIP6RXPKTSLO(fcn_idx);
4718                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
4719                                I40E_GLPES_PFIP6RXFRAGSLO(fcn_idx);
4720                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
4721                                I40E_GLPES_PFIP6RXMCPKTSLO(fcn_idx);
4722                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
4723                                I40E_GLPES_PFIP6TXOCTSLO(fcn_idx);
4724                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
4725                                I40E_GLPES_PFIP6TXPKTSLO(fcn_idx);
4726                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
4727                                I40E_GLPES_PFIP6TXPKTSLO(fcn_idx);
4728                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
4729                                I40E_GLPES_PFIP6TXFRAGSLO(fcn_idx);
4730                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
4731                                I40E_GLPES_PFTCPRXSEGSLO(fcn_idx);
4732                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
4733                                I40E_GLPES_PFTCPTXSEGLO(fcn_idx);
4734                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
4735                                I40E_GLPES_PFRDMARXRDSLO(fcn_idx);
4736                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
4737                                I40E_GLPES_PFRDMARXSNDSLO(fcn_idx);
4738                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
4739                                I40E_GLPES_PFRDMARXWRSLO(fcn_idx);
4740                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
4741                                I40E_GLPES_PFRDMATXRDSLO(fcn_idx);
4742                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
4743                                I40E_GLPES_PFRDMATXSNDSLO(fcn_idx);
4744                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
4745                                I40E_GLPES_PFRDMATXWRSLO(fcn_idx);
4746                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
4747                                I40E_GLPES_PFRDMAVBNDLO(fcn_idx);
4748                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
4749                                I40E_GLPES_PFRDMAVINVLO(fcn_idx);
4750        } else {
4751                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
4752                                I40E_GLPES_VFIP4RXDISCARD(fcn_idx);
4753                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
4754                                I40E_GLPES_VFIP4RXTRUNC(fcn_idx);
4755                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
4756                                I40E_GLPES_VFIP4TXNOROUTE(fcn_idx);
4757                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
4758                                I40E_GLPES_VFIP6RXDISCARD(fcn_idx);
4759                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
4760                                I40E_GLPES_VFIP6RXTRUNC(fcn_idx);
4761                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
4762                                I40E_GLPES_VFIP6TXNOROUTE(fcn_idx);
4763                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
4764                                I40E_GLPES_VFTCPRTXSEG(fcn_idx);
4765                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
4766                                I40E_GLPES_VFTCPRXOPTERR(fcn_idx);
4767                stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
4768                                I40E_GLPES_VFTCPRXPROTOERR(fcn_idx);
4769
4770                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
4771                                I40E_GLPES_VFIP4RXOCTSLO(fcn_idx);
4772                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
4773                                I40E_GLPES_VFIP4RXPKTSLO(fcn_idx);
4774                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
4775                                I40E_GLPES_VFIP4RXFRAGSLO(fcn_idx);
4776                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
4777                                I40E_GLPES_VFIP4RXMCPKTSLO(fcn_idx);
4778                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
4779                                I40E_GLPES_VFIP4TXOCTSLO(fcn_idx);
4780                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
4781                                I40E_GLPES_VFIP4TXPKTSLO(fcn_idx);
4782                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
4783                                I40E_GLPES_VFIP4TXFRAGSLO(fcn_idx);
4784                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
4785                                I40E_GLPES_VFIP4TXMCPKTSLO(fcn_idx);
4786                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
4787                                I40E_GLPES_VFIP6RXOCTSLO(fcn_idx);
4788                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
4789                                I40E_GLPES_VFIP6RXPKTSLO(fcn_idx);
4790                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
4791                                I40E_GLPES_VFIP6RXFRAGSLO(fcn_idx);
4792                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
4793                                I40E_GLPES_VFIP6RXMCPKTSLO(fcn_idx);
4794                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
4795                                I40E_GLPES_VFIP6TXOCTSLO(fcn_idx);
4796                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
4797                                I40E_GLPES_VFIP6TXPKTSLO(fcn_idx);
4798                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
4799                                I40E_GLPES_VFIP6TXPKTSLO(fcn_idx);
4800                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
4801                                I40E_GLPES_VFIP6TXFRAGSLO(fcn_idx);
4802                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
4803                                I40E_GLPES_VFTCPRXSEGSLO(fcn_idx);
4804                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
4805                                I40E_GLPES_VFTCPTXSEGLO(fcn_idx);
4806                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
4807                                I40E_GLPES_VFRDMARXRDSLO(fcn_idx);
4808                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
4809                                I40E_GLPES_VFRDMARXSNDSLO(fcn_idx);
4810                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
4811                                I40E_GLPES_VFRDMARXWRSLO(fcn_idx);
4812                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
4813                                I40E_GLPES_VFRDMATXRDSLO(fcn_idx);
4814                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
4815                                I40E_GLPES_VFRDMATXSNDSLO(fcn_idx);
4816                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
4817                                I40E_GLPES_VFRDMATXWRSLO(fcn_idx);
4818                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
4819                                I40E_GLPES_VFRDMAVBNDLO(fcn_idx);
4820                stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
4821                                I40E_GLPES_VFRDMAVINVLO(fcn_idx);
4822        }
4823
4824        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
4825             stats_index++) {
4826                stats_reg_offset = stats_table->stats_offset_64[stats_index];
4827                last_rd_stats->stats_value_64[stats_index] =
4828                        readq(stats->hw->hw_addr + stats_reg_offset);
4829        }
4830
4831        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
4832             stats_index++) {
4833                stats_reg_offset = stats_table->stats_offset_32[stats_index];
4834                last_rd_stats->stats_value_32[stats_index] =
4835                        i40iw_rd32(stats->hw, stats_reg_offset);
4836        }
4837}
4838
4839/**
4840 * i40iw_hw_stats_read_32 - Read 32-bit HW stats counters and accommodates for roll-overs.
4841 * @stat: pestat struct
4842 * @index: index in HW stats table which contains offset reg-addr
4843 * @value: hw stats value
4844 */
4845void i40iw_hw_stats_read_32(struct i40iw_vsi_pestat *stats,
4846                            enum i40iw_hw_stats_index_32b index,
4847                            u64 *value)
4848{
4849        struct i40iw_dev_hw_stats_offsets *stats_table =
4850                &stats->hw_stats_offsets;
4851        struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
4852        struct i40iw_dev_hw_stats *hw_stats = &stats->hw_stats;
4853        u64 new_stats_value = 0;
4854        u32 stats_reg_offset = stats_table->stats_offset_32[index];
4855
4856        new_stats_value = i40iw_rd32(stats->hw, stats_reg_offset);
4857        /*roll-over case */
4858        if (new_stats_value < last_rd_stats->stats_value_32[index])
4859                hw_stats->stats_value_32[index] += new_stats_value;
4860        else
4861                hw_stats->stats_value_32[index] +=
4862                        new_stats_value - last_rd_stats->stats_value_32[index];
4863        last_rd_stats->stats_value_32[index] = new_stats_value;
4864        *value = hw_stats->stats_value_32[index];
4865}
4866
4867/**
4868 * i40iw_hw_stats_read_64 - Read HW stats counters (greater than 32-bit) and accommodates for roll-overs.
4869 * @stats: pestat struct
4870 * @index: index in HW stats table which contains offset reg-addr
4871 * @value: hw stats value
4872 */
4873void i40iw_hw_stats_read_64(struct i40iw_vsi_pestat *stats,
4874                            enum i40iw_hw_stats_index_64b index,
4875                            u64 *value)
4876{
4877        struct i40iw_dev_hw_stats_offsets *stats_table =
4878                &stats->hw_stats_offsets;
4879        struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
4880        struct i40iw_dev_hw_stats *hw_stats = &stats->hw_stats;
4881        u64 new_stats_value = 0;
4882        u32 stats_reg_offset = stats_table->stats_offset_64[index];
4883
4884        new_stats_value = readq(stats->hw->hw_addr + stats_reg_offset);
4885        /*roll-over case */
4886        if (new_stats_value < last_rd_stats->stats_value_64[index])
4887                hw_stats->stats_value_64[index] += new_stats_value;
4888        else
4889                hw_stats->stats_value_64[index] +=
4890                        new_stats_value - last_rd_stats->stats_value_64[index];
4891        last_rd_stats->stats_value_64[index] = new_stats_value;
4892        *value = hw_stats->stats_value_64[index];
4893}
4894
4895/**
4896 * i40iw_hw_stats_read_all - read all HW stat counters
4897 * @stats: pestat struct
4898 * @stats_values: hw stats structure
4899 *
4900 * Read all the HW stat counters and populates hw_stats structure
4901 * of passed-in vsi's pestat as well as copy created in stat_values.
4902 */
4903void i40iw_hw_stats_read_all(struct i40iw_vsi_pestat *stats,
4904                             struct i40iw_dev_hw_stats *stats_values)
4905{
4906        u32 stats_index;
4907        unsigned long flags;
4908
4909        spin_lock_irqsave(&stats->lock, flags);
4910
4911        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
4912             stats_index++)
4913                i40iw_hw_stats_read_32(stats, stats_index,
4914                                       &stats_values->stats_value_32[stats_index]);
4915        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
4916             stats_index++)
4917                i40iw_hw_stats_read_64(stats, stats_index,
4918                                       &stats_values->stats_value_64[stats_index]);
4919        spin_unlock_irqrestore(&stats->lock, flags);
4920}
4921
4922/**
4923 * i40iw_hw_stats_refresh_all - Update all HW stats structs
4924 * @stats: pestat struct
4925 *
4926 * Read all the HW stats counters to refresh values in hw_stats structure
4927 * of passed-in dev's pestat
4928 */
4929void i40iw_hw_stats_refresh_all(struct i40iw_vsi_pestat *stats)
4930{
4931        u64 stats_value;
4932        u32 stats_index;
4933        unsigned long flags;
4934
4935        spin_lock_irqsave(&stats->lock, flags);
4936
4937        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
4938             stats_index++)
4939                i40iw_hw_stats_read_32(stats, stats_index, &stats_value);
4940        for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
4941             stats_index++)
4942                i40iw_hw_stats_read_64(stats, stats_index, &stats_value);
4943        spin_unlock_irqrestore(&stats->lock, flags);
4944}
4945
4946/**
4947 * i40iw_get_fcn_id - Return the function id
4948 * @dev: pointer to the device
4949 */
4950static u8 i40iw_get_fcn_id(struct i40iw_sc_dev *dev)
4951{
4952        u8 fcn_id = I40IW_INVALID_FCN_ID;
4953        u8 i;
4954
4955        for (i = I40IW_FIRST_NON_PF_STAT; i < I40IW_MAX_STATS_COUNT; i++)
4956                if (!dev->fcn_id_array[i]) {
4957                        fcn_id = i;
4958                        dev->fcn_id_array[i] = true;
4959                        break;
4960                }
4961        return fcn_id;
4962}
4963
4964/**
4965 * i40iw_vsi_stats_init - Initialize the vsi statistics
4966 * @vsi: pointer to the vsi structure
4967 * @info: The info structure used for initialization
4968 */
4969enum i40iw_status_code i40iw_vsi_stats_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_stats_info *info)
4970{
4971        u8 fcn_id = info->fcn_id;
4972
4973        if (info->alloc_fcn_id)
4974                fcn_id = i40iw_get_fcn_id(vsi->dev);
4975
4976        if (fcn_id == I40IW_INVALID_FCN_ID)
4977                return I40IW_ERR_NOT_READY;
4978
4979        vsi->pestat = info->pestat;
4980        vsi->pestat->hw = vsi->dev->hw;
4981        vsi->pestat->vsi = vsi;
4982
4983        if (info->stats_initialize) {
4984                i40iw_hw_stats_init(vsi->pestat, fcn_id, true);
4985                spin_lock_init(&vsi->pestat->lock);
4986                i40iw_hw_stats_start_timer(vsi);
4987        }
4988        vsi->stats_fcn_id_alloc = info->alloc_fcn_id;
4989        vsi->fcn_id = fcn_id;
4990        return I40IW_SUCCESS;
4991}
4992
4993/**
4994 * i40iw_vsi_stats_free - Free the vsi stats
4995 * @vsi: pointer to the vsi structure
4996 */
4997void i40iw_vsi_stats_free(struct i40iw_sc_vsi *vsi)
4998{
4999        u8 fcn_id = vsi->fcn_id;
5000
5001        if (vsi->stats_fcn_id_alloc && fcn_id < I40IW_MAX_STATS_COUNT)
5002                vsi->dev->fcn_id_array[fcn_id] = false;
5003        i40iw_hw_stats_stop_timer(vsi);
5004}
5005
5006static struct i40iw_cqp_ops iw_cqp_ops = {
5007        .cqp_init = i40iw_sc_cqp_init,
5008        .cqp_create = i40iw_sc_cqp_create,
5009        .cqp_post_sq = i40iw_sc_cqp_post_sq,
5010        .cqp_get_next_send_wqe = i40iw_sc_cqp_get_next_send_wqe,
5011        .cqp_destroy = i40iw_sc_cqp_destroy,
5012        .poll_for_cqp_op_done = i40iw_sc_poll_for_cqp_op_done
5013};
5014
5015static struct i40iw_ccq_ops iw_ccq_ops = {
5016        .ccq_init = i40iw_sc_ccq_init,
5017        .ccq_create = i40iw_sc_ccq_create,
5018        .ccq_destroy = i40iw_sc_ccq_destroy,
5019        .ccq_create_done = i40iw_sc_ccq_create_done,
5020        .ccq_get_cqe_info = i40iw_sc_ccq_get_cqe_info,
5021        .ccq_arm = i40iw_sc_ccq_arm
5022};
5023
5024static struct i40iw_ceq_ops iw_ceq_ops = {
5025        .ceq_init = i40iw_sc_ceq_init,
5026        .ceq_create = i40iw_sc_ceq_create,
5027        .cceq_create_done = i40iw_sc_cceq_create_done,
5028        .cceq_destroy_done = i40iw_sc_cceq_destroy_done,
5029        .cceq_create = i40iw_sc_cceq_create,
5030        .ceq_destroy = i40iw_sc_ceq_destroy,
5031        .process_ceq = i40iw_sc_process_ceq
5032};
5033
5034static struct i40iw_aeq_ops iw_aeq_ops = {
5035        .aeq_init = i40iw_sc_aeq_init,
5036        .aeq_create = i40iw_sc_aeq_create,
5037        .aeq_destroy = i40iw_sc_aeq_destroy,
5038        .get_next_aeqe = i40iw_sc_get_next_aeqe,
5039        .repost_aeq_entries = i40iw_sc_repost_aeq_entries,
5040        .aeq_create_done = i40iw_sc_aeq_create_done,
5041        .aeq_destroy_done = i40iw_sc_aeq_destroy_done
5042};
5043
5044/* iwarp pd ops */
5045static struct i40iw_pd_ops iw_pd_ops = {
5046        .pd_init = i40iw_sc_pd_init,
5047};
5048
5049static struct i40iw_priv_qp_ops iw_priv_qp_ops = {
5050        .qp_init = i40iw_sc_qp_init,
5051        .qp_create = i40iw_sc_qp_create,
5052        .qp_modify = i40iw_sc_qp_modify,
5053        .qp_destroy = i40iw_sc_qp_destroy,
5054        .qp_flush_wqes = i40iw_sc_qp_flush_wqes,
5055        .qp_upload_context = i40iw_sc_qp_upload_context,
5056        .qp_setctx = i40iw_sc_qp_setctx,
5057        .qp_send_lsmm = i40iw_sc_send_lsmm,
5058        .qp_send_lsmm_nostag = i40iw_sc_send_lsmm_nostag,
5059        .qp_send_rtt = i40iw_sc_send_rtt,
5060        .qp_post_wqe0 = i40iw_sc_post_wqe0,
5061        .iw_mr_fast_register = i40iw_sc_mr_fast_register
5062};
5063
5064static struct i40iw_priv_cq_ops iw_priv_cq_ops = {
5065        .cq_init = i40iw_sc_cq_init,
5066        .cq_create = i40iw_sc_cq_create,
5067        .cq_destroy = i40iw_sc_cq_destroy,
5068        .cq_modify = i40iw_sc_cq_modify,
5069};
5070
5071static struct i40iw_mr_ops iw_mr_ops = {
5072        .alloc_stag = i40iw_sc_alloc_stag,
5073        .mr_reg_non_shared = i40iw_sc_mr_reg_non_shared,
5074        .mr_reg_shared = i40iw_sc_mr_reg_shared,
5075        .dealloc_stag = i40iw_sc_dealloc_stag,
5076        .query_stag = i40iw_sc_query_stag,
5077        .mw_alloc = i40iw_sc_mw_alloc
5078};
5079
5080static struct i40iw_cqp_misc_ops iw_cqp_misc_ops = {
5081        .manage_push_page = i40iw_sc_manage_push_page,
5082        .manage_hmc_pm_func_table = i40iw_sc_manage_hmc_pm_func_table,
5083        .set_hmc_resource_profile = i40iw_sc_set_hmc_resource_profile,
5084        .commit_fpm_values = i40iw_sc_commit_fpm_values,
5085        .query_fpm_values = i40iw_sc_query_fpm_values,
5086        .static_hmc_pages_allocated = i40iw_sc_static_hmc_pages_allocated,
5087        .add_arp_cache_entry = i40iw_sc_add_arp_cache_entry,
5088        .del_arp_cache_entry = i40iw_sc_del_arp_cache_entry,
5089        .query_arp_cache_entry = i40iw_sc_query_arp_cache_entry,
5090        .manage_apbvt_entry = i40iw_sc_manage_apbvt_entry,
5091        .manage_qhash_table_entry = i40iw_sc_manage_qhash_table_entry,
5092        .alloc_local_mac_ipaddr_table_entry = i40iw_sc_alloc_local_mac_ipaddr_entry,
5093        .add_local_mac_ipaddr_entry = i40iw_sc_add_local_mac_ipaddr_entry,
5094        .del_local_mac_ipaddr_entry = i40iw_sc_del_local_mac_ipaddr_entry,
5095        .cqp_nop = i40iw_sc_cqp_nop,
5096        .commit_fpm_values_done = i40iw_sc_commit_fpm_values_done,
5097        .query_fpm_values_done = i40iw_sc_query_fpm_values_done,
5098        .manage_hmc_pm_func_table_done = i40iw_sc_manage_hmc_pm_func_table_done,
5099        .update_suspend_qp = i40iw_sc_suspend_qp,
5100        .update_resume_qp = i40iw_sc_resume_qp
5101};
5102
5103static struct i40iw_hmc_ops iw_hmc_ops = {
5104        .init_iw_hmc = i40iw_sc_init_iw_hmc,
5105        .parse_fpm_query_buf = i40iw_sc_parse_fpm_query_buf,
5106        .configure_iw_fpm = i40iw_sc_configure_iw_fpm,
5107        .parse_fpm_commit_buf = i40iw_sc_parse_fpm_commit_buf,
5108        .create_hmc_object = i40iw_sc_create_hmc_obj,
5109        .del_hmc_object = i40iw_sc_del_hmc_obj
5110};
5111
5112/**
5113 * i40iw_device_init - Initialize IWARP device
5114 * @dev: IWARP device pointer
5115 * @info: IWARP init info
5116 */
5117enum i40iw_status_code i40iw_device_init(struct i40iw_sc_dev *dev,
5118                                         struct i40iw_device_init_info *info)
5119{
5120        u32 val;
5121        u32 vchnl_ver = 0;
5122        u16 hmc_fcn = 0;
5123        enum i40iw_status_code ret_code = 0;
5124        u8 db_size;
5125
5126        spin_lock_init(&dev->cqp_lock);
5127
5128        i40iw_device_init_uk(&dev->dev_uk);
5129
5130        dev->debug_mask = info->debug_mask;
5131
5132        dev->hmc_fn_id = info->hmc_fn_id;
5133        dev->is_pf = info->is_pf;
5134
5135        dev->fpm_query_buf_pa = info->fpm_query_buf_pa;
5136        dev->fpm_query_buf = info->fpm_query_buf;
5137
5138        dev->fpm_commit_buf_pa = info->fpm_commit_buf_pa;
5139        dev->fpm_commit_buf = info->fpm_commit_buf;
5140
5141        dev->hw = info->hw;
5142        dev->hw->hw_addr = info->bar0;
5143
5144        if (dev->is_pf) {
5145                val = i40iw_rd32(dev->hw, I40E_GLPCI_DREVID);
5146                dev->hw_rev = (u8)RS_32(val, I40E_GLPCI_DREVID_DEFAULT_REVID);
5147
5148                val = i40iw_rd32(dev->hw, I40E_GLPCI_LBARCTRL);
5149                db_size = (u8)RS_32(val, I40E_GLPCI_LBARCTRL_PE_DB_SIZE);
5150                if ((db_size != I40IW_PE_DB_SIZE_4M) &&
5151                    (db_size != I40IW_PE_DB_SIZE_8M)) {
5152                        i40iw_debug(dev, I40IW_DEBUG_DEV,
5153                                    "%s: PE doorbell is not enabled in CSR val 0x%x\n",
5154                                    __func__, val);
5155                        ret_code = I40IW_ERR_PE_DOORBELL_NOT_ENABLED;
5156                        return ret_code;
5157                }
5158                dev->db_addr = dev->hw->hw_addr + I40IW_DB_ADDR_OFFSET;
5159                dev->vchnl_if.vchnl_recv = i40iw_vchnl_recv_pf;
5160        } else {
5161                dev->db_addr = dev->hw->hw_addr + I40IW_VF_DB_ADDR_OFFSET;
5162        }
5163
5164        dev->cqp_ops = &iw_cqp_ops;
5165        dev->ccq_ops = &iw_ccq_ops;
5166        dev->ceq_ops = &iw_ceq_ops;
5167        dev->aeq_ops = &iw_aeq_ops;
5168        dev->cqp_misc_ops = &iw_cqp_misc_ops;
5169        dev->iw_pd_ops = &iw_pd_ops;
5170        dev->iw_priv_qp_ops = &iw_priv_qp_ops;
5171        dev->iw_priv_cq_ops = &iw_priv_cq_ops;
5172        dev->mr_ops = &iw_mr_ops;
5173        dev->hmc_ops = &iw_hmc_ops;
5174        dev->vchnl_if.vchnl_send = info->vchnl_send;
5175        if (dev->vchnl_if.vchnl_send)
5176                dev->vchnl_up = true;
5177        else
5178                dev->vchnl_up = false;
5179        if (!dev->is_pf) {
5180                dev->vchnl_if.vchnl_recv = i40iw_vchnl_recv_vf;
5181                ret_code = i40iw_vchnl_vf_get_ver(dev, &vchnl_ver);
5182                if (!ret_code) {
5183                        i40iw_debug(dev, I40IW_DEBUG_DEV,
5184                                    "%s: Get Channel version rc = 0x%0x, version is %u\n",
5185                                __func__, ret_code, vchnl_ver);
5186                        ret_code = i40iw_vchnl_vf_get_hmc_fcn(dev, &hmc_fcn);
5187                        if (!ret_code) {
5188                                i40iw_debug(dev, I40IW_DEBUG_DEV,
5189                                            "%s Get HMC function rc = 0x%0x, hmc fcn is %u\n",
5190                                            __func__, ret_code, hmc_fcn);
5191                                dev->hmc_fn_id = (u8)hmc_fcn;
5192                        }
5193                }
5194        }
5195        dev->iw_vf_cqp_ops = &iw_vf_cqp_ops;
5196
5197        return ret_code;
5198}
5199