Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
config INFINIBAND_BNXT_RE
tristate "Broadcom Netxtreme HCA support"
depends on 64BIT
depends on INET && DCB && BNXT
help
This driver supports Broadcom NetXtreme-E 10/25/40/50 gigabit
RoCE HCAs. To compile this driver as a module, choose M here:
the module will be called bnxt_re.
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y := -I $(srctree)/drivers/net/ethernet/broadcom/bnxt
obj-$(CONFIG_INFINIBAND_BNXT_RE) += bnxt_re.o
bnxt_re-y := main.o ib_verbs.o \
qplib_res.o qplib_rcfw.o \
qplib_sp.o qplib_fp.o hw_counters.o \
debugfs.o uapi.o
@@ -0,0 +1,292 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Slow Path Operators (header)
*
*/
#ifndef __BNXT_RE_H__
#define __BNXT_RE_H__
#include <rdma/uverbs_ioctl.h>
#include "hw_counters.h"
#include <linux/hashtable.h>
#define ROCE_DRV_MODULE_NAME "bnxt_re"
#define BNXT_RE_DESC "Broadcom NetXtreme-C/E RoCE Driver"
#define BNXT_RE_PAGE_SHIFT_1G (30)
#define BNXT_RE_PAGE_SIZE_SUPPORTED 0x7FFFF000 /* 4kb - 1G */
#define BNXT_RE_MAX_MR_SIZE_LOW BIT_ULL(BNXT_RE_PAGE_SHIFT_1G)
#define BNXT_RE_MAX_MR_SIZE_HIGH BIT_ULL(39)
#define BNXT_RE_MAX_MR_SIZE BNXT_RE_MAX_MR_SIZE_HIGH
/* Number of MRs to reserve for PF, leaving remainder for VFs */
#define BNXT_RE_RESVD_MR_FOR_PF (32 * 1024)
#define BNXT_RE_MAX_GID_PER_VF 128
/*
* Percentage of resources of each type reserved for PF.
* Remaining resources are divided equally among VFs.
* [0, 100]
*/
#define BNXT_RE_PCT_RSVD_FOR_PF 50
#define BNXT_RE_UD_QP_HW_STALL 0x400000
#define BNXT_RE_RQ_WQE_THRESHOLD 32
/*
* Setting the default ack delay value to 16, which means
* the default timeout is approx. 260ms(4 usec * 2 ^(timeout))
*/
#define BNXT_RE_DEFAULT_ACK_DELAY 16
struct bnxt_re_ring_attr {
dma_addr_t *dma_arr;
int pages;
int type;
u32 depth;
u32 lrid; /* Logical ring id */
u8 mode;
};
/*
* Data structure and defines to handle
* recovery
*/
#define BNXT_RE_PRE_RECOVERY_REMOVE 0x1
#define BNXT_RE_COMPLETE_REMOVE 0x2
#define BNXT_RE_POST_RECOVERY_INIT 0x4
#define BNXT_RE_COMPLETE_INIT 0x8
struct bnxt_re_sqp_entries {
struct bnxt_qplib_sge sge;
u64 wrid;
/* For storing the actual qp1 cqe */
struct bnxt_qplib_cqe cqe;
struct bnxt_re_qp *qp1_qp;
};
#define BNXT_RE_MAX_GSI_SQP_ENTRIES 1024
struct bnxt_re_gsi_context {
struct bnxt_re_qp *gsi_qp;
struct bnxt_re_qp *gsi_sqp;
struct bnxt_re_ah *gsi_sah;
struct bnxt_re_sqp_entries *sqp_tbl;
};
struct bnxt_re_en_dev_info {
struct bnxt_en_dev *en_dev;
struct bnxt_re_dev *rdev;
};
#define BNXT_RE_AEQ_IDX 0
#define BNXT_RE_NQ_IDX 1
#define BNXT_RE_GEN_P5_MAX_VF 64
struct bnxt_re_pacing {
u64 dbr_db_fifo_reg_off;
void *dbr_page;
u64 dbr_bar_addr;
u32 pacing_algo_th;
u32 do_pacing_save;
u32 dbq_pacing_time; /* ms */
u32 dbr_def_do_pacing;
bool dbr_pacing;
struct mutex dbq_lock; /* synchronize db pacing algo */
};
#define BNXT_RE_MAX_DBR_DO_PACING 0xFFFF
#define BNXT_RE_DBR_PACING_TIME 5 /* ms */
#define BNXT_RE_PACING_ALGO_THRESHOLD 250 /* Entries in DB FIFO */
#define BNXT_RE_PACING_ALARM_TH_MULTIPLE 2 /* Multiple of pacing algo threshold */
/* Default do_pacing value when there is no congestion */
#define BNXT_RE_DBR_DO_PACING_NO_CONGESTION 0x7F /* 1 in 512 probability */
#define BNXT_RE_MAX_FIFO_DEPTH_P5 0x2c00
#define BNXT_RE_MAX_FIFO_DEPTH_P7 0x8000
#define BNXT_RE_MAX_FIFO_DEPTH(ctx) \
(bnxt_qplib_is_chip_gen_p7((ctx)) ? \
BNXT_RE_MAX_FIFO_DEPTH_P7 :\
BNXT_RE_MAX_FIFO_DEPTH_P5)
#define BNXT_RE_GRC_FIFO_REG_BASE 0x2000
#define BNXT_RE_MIN_MSIX 2
#define BNXT_RE_MAX_MSIX BNXT_MAX_ROCE_MSIX
struct bnxt_re_nq_record {
struct bnxt_msix_entry msix_entries[BNXT_RE_MAX_MSIX];
struct bnxt_qplib_nq nq[BNXT_RE_MAX_MSIX];
int num_msix;
/* serialize NQ access */
struct mutex load_lock;
};
#define MAX_CQ_HASH_BITS (16)
#define MAX_SRQ_HASH_BITS (16)
static inline bool bnxt_re_chip_gen_p7(u16 chip_num)
{
return (chip_num == CHIP_NUM_58818 ||
chip_num == CHIP_NUM_57608);
}
struct bnxt_re_dev {
struct ib_device ibdev;
struct list_head list;
unsigned long flags;
#define BNXT_RE_FLAG_NETDEV_REGISTERED 0
#define BNXT_RE_FLAG_STATS_CTX3_ALLOC 1
#define BNXT_RE_FLAG_HAVE_L2_REF 3
#define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4
#define BNXT_RE_FLAG_RESOURCES_ALLOCATED 7
#define BNXT_RE_FLAG_RESOURCES_INITIALIZED 8
#define BNXT_RE_FLAG_ERR_DEVICE_DETACHED 17
#define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29
struct net_device *netdev;
struct auxiliary_device *adev;
unsigned int version, major, minor;
struct bnxt_qplib_chip_ctx *chip_ctx;
struct bnxt_en_dev *en_dev;
int id;
/* RCFW Channel */
struct bnxt_qplib_rcfw rcfw;
/* NQ record */
struct bnxt_re_nq_record *nqr;
/* Device Resources */
struct bnxt_qplib_dev_attr *dev_attr;
struct bnxt_qplib_ctx qplib_ctx;
struct bnxt_qplib_res qplib_res;
struct bnxt_qplib_dpi dpi_privileged;
struct bnxt_qplib_cq_coal_param cq_coalescing;
struct mutex qp_lock; /* protect qp list */
struct list_head qp_list;
/* Max of 2 lossless traffic class supported per port */
u16 cosq[2];
/* QP for handling QP1 packets */
struct bnxt_re_gsi_context gsi_ctx;
struct bnxt_re_stats stats;
atomic_t nq_alloc_cnt;
u32 is_virtfn;
u32 num_vfs;
struct bnxt_re_pacing pacing;
struct work_struct dbq_fifo_check_work;
struct delayed_work dbq_pacing_work;
DECLARE_HASHTABLE(cq_hash, MAX_CQ_HASH_BITS);
DECLARE_HASHTABLE(srq_hash, MAX_SRQ_HASH_BITS);
struct dentry *dbg_root;
struct dentry *qp_debugfs;
unsigned long event_bitmap;
struct bnxt_qplib_cc_param cc_param;
struct workqueue_struct *dcb_wq;
struct dentry *cc_config;
struct bnxt_re_dbg_cc_config_params *cc_config_params;
struct dentry *cq_coal_cfg;
struct bnxt_re_dbg_cq_coal_params *cq_coal_cfg_params;
#define BNXT_VPD_FLD_LEN 32
char board_partno[BNXT_VPD_FLD_LEN];
/* RoCE mirror */
u16 mirror_vnic_id;
union ib_gid ugid;
u32 ugid_index;
u8 sniffer_flow_created : 1;
};
#define to_bnxt_re_dev(ptr, member) \
container_of((ptr), struct bnxt_re_dev, member)
#define BNXT_RE_ROCE_V1_PACKET 0
#define BNXT_RE_ROCEV2_IPV4_PACKET 2
#define BNXT_RE_ROCEV2_IPV6_PACKET 3
#define BNXT_RE_CHECK_RC(x) ((x) && ((x) != -ETIMEDOUT))
void bnxt_re_pacing_alert(struct bnxt_re_dev *rdev);
int bnxt_re_assign_pma_port_counters(struct bnxt_re_dev *rdev, struct ib_mad *out_mad);
int bnxt_re_assign_pma_port_ext_counters(struct bnxt_re_dev *rdev,
struct ib_mad *out_mad);
void bnxt_re_hwrm_free_vnic(struct bnxt_re_dev *rdev);
int bnxt_re_hwrm_alloc_vnic(struct bnxt_re_dev *rdev);
int bnxt_re_hwrm_cfg_vnic(struct bnxt_re_dev *rdev, u32 qp_id);
static inline struct device *rdev_to_dev(struct bnxt_re_dev *rdev)
{
if (rdev)
return &rdev->ibdev.dev;
return NULL;
}
extern const struct uapi_definition bnxt_re_uapi_defs[];
static inline void bnxt_re_set_pacing_dev_state(struct bnxt_re_dev *rdev)
{
rdev->qplib_res.pacing_data->dev_err_state =
test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
}
static inline int bnxt_re_read_context_allowed(struct bnxt_re_dev *rdev)
{
if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ||
rdev->rcfw.res->cctx->hwrm_intf_ver < HWRM_VERSION_READ_CTX)
return -EOPNOTSUPP;
return 0;
}
#define BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P5 1088
#define BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P5 128
#define BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P5 128
#define BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P5 192
#define BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P7 1088
#define BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P7 192
#define BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P7 192
#define BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P7 192
#define BNXT_RE_HWRM_CMD_TIMEOUT(rdev) \
((rdev)->chip_ctx->hwrm_cmd_max_timeout * 1000)
#endif
@@ -0,0 +1,536 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* Copyright (c) 2024, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* Description: Debugfs component of the bnxt_re driver
*/
#include <linux/debugfs.h>
#include <linux/pci.h>
#include <linux/seq_file.h>
#include <rdma/ib_addr.h>
#include <linux/bnxt/ulp.h>
#include "roce_hsi.h"
#include "qplib_res.h"
#include "qplib_sp.h"
#include "qplib_fp.h"
#include "qplib_rcfw.h"
#include "bnxt_re.h"
#include "ib_verbs.h"
#include "debugfs.h"
static struct dentry *bnxt_re_debugfs_root;
static const char * const bnxt_re_cq_coal_str[] = {
"buf_maxtime",
"normal_maxbuf",
"during_maxbuf",
"en_ring_idle_mode",
"enable",
};
static const char * const bnxt_re_cc_gen0_name[] = {
"enable_cc",
"run_avg_weight_g",
"num_phase_per_state",
"init_cr",
"init_tr",
"tos_ecn",
"tos_dscp",
"alt_vlan_pcp",
"alt_vlan_dscp",
"rtt",
"cc_mode",
"tcp_cp",
"tx_queue",
"inactivity_cp",
};
static inline const char *bnxt_re_qp_state_str(u8 state)
{
switch (state) {
case CMDQ_MODIFY_QP_NEW_STATE_RESET:
return "RST";
case CMDQ_MODIFY_QP_NEW_STATE_INIT:
return "INIT";
case CMDQ_MODIFY_QP_NEW_STATE_RTR:
return "RTR";
case CMDQ_MODIFY_QP_NEW_STATE_RTS:
return "RTS";
case CMDQ_MODIFY_QP_NEW_STATE_SQE:
return "SQER";
case CMDQ_MODIFY_QP_NEW_STATE_SQD:
return "SQD";
case CMDQ_MODIFY_QP_NEW_STATE_ERR:
return "ERR";
default:
return "Invalid QP state";
}
}
static inline const char *bnxt_re_qp_type_str(u8 type)
{
switch (type) {
case CMDQ_CREATE_QP1_TYPE_GSI: return "QP1";
case CMDQ_CREATE_QP_TYPE_GSI: return "QP1";
case CMDQ_CREATE_QP_TYPE_RC: return "RC";
case CMDQ_CREATE_QP_TYPE_UD: return "UD";
case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE: return "RAW_ETHERTYPE";
default: return "Invalid transport type";
}
}
static ssize_t qp_info_read(struct file *filep,
char __user *buffer,
size_t count, loff_t *ppos)
{
struct bnxt_re_qp *qp = filep->private_data;
struct bnxt_qplib_qp *qplib_qp;
u32 rate_limit = 0;
char *buf;
int len;
if (*ppos)
return 0;
qplib_qp = &qp->qplib_qp;
if (qplib_qp->shaper_allocation_status)
rate_limit = qplib_qp->rate_limit;
buf = kasprintf(GFP_KERNEL,
"QPN\t\t: %d\n"
"transport\t: %s\n"
"state\t\t: %s\n"
"mtu\t\t: %d\n"
"timeout\t\t: %d\n"
"remote QPN\t: %d\n"
"shaper allocated : %d\n"
"rate limit\t: %d kbps\n",
qp->qplib_qp.id,
bnxt_re_qp_type_str(qp->qplib_qp.type),
bnxt_re_qp_state_str(qp->qplib_qp.state),
qp->qplib_qp.mtu,
qp->qplib_qp.timeout,
qp->qplib_qp.dest_qpn,
qplib_qp->shaper_allocation_status,
rate_limit);
if (!buf)
return -ENOMEM;
if (count < strlen(buf)) {
kfree(buf);
return -ENOSPC;
}
len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
kfree(buf);
return len;
}
static const struct file_operations debugfs_qp_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = qp_info_read,
};
void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
{
char resn[32];
sprintf(resn, "0x%x", qp->qplib_qp.id);
qp->dentry = debugfs_create_file(resn, 0400, rdev->qp_debugfs, qp, &debugfs_qp_fops);
}
void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
{
debugfs_remove(qp->dentry);
}
static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param *ccparam, u32 *val)
{
u64 map_offset;
map_offset = BIT(offset);
switch (map_offset) {
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
*val = ccparam->enable;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
*val = ccparam->g;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
*val = ccparam->nph_per_state;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
*val = ccparam->init_cr;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
*val = ccparam->init_tr;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
*val = ccparam->tos_ecn;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
*val = ccparam->tos_dscp;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
*val = ccparam->alt_vlan_pcp;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
*val = ccparam->alt_tos_dscp;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
*val = ccparam->rtt;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
*val = ccparam->cc_mode;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
*val = ccparam->tcp_cp;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
*val = ccparam->inact_th;
break;
default:
return -EINVAL;
}
return 0;
}
static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
size_t usr_buf_len, loff_t *ppos)
{
struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
struct bnxt_qplib_cc_param ccparam = {};
u32 offset = dbg_cc_param->offset;
char buf[16];
u32 val;
int rc;
rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &ccparam);
if (rc)
return rc;
rc = map_cc_config_offset_gen0_ext0(offset, &ccparam, &val);
if (rc)
return rc;
rc = snprintf(buf, sizeof(buf), "%d\n", val);
if (rc < 0)
return rc;
return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
}
static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
{
u32 modify_mask;
modify_mask = BIT(offset);
switch (modify_mask) {
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
ccparam->enable = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
ccparam->g = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
ccparam->nph_per_state = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
ccparam->init_cr = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
ccparam->init_tr = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
ccparam->tos_ecn = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
ccparam->tos_dscp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
ccparam->alt_vlan_pcp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
ccparam->alt_tos_dscp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
ccparam->rtt = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
ccparam->cc_mode = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
ccparam->tcp_cp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
return -EOPNOTSUPP;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
ccparam->inact_th = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
ccparam->time_pph = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_PKTS_PER_PHASE:
ccparam->pkts_pph = val;
break;
}
ccparam->mask = modify_mask;
return 0;
}
static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
{
struct bnxt_qplib_cc_param ccparam = { };
int rc;
if (gen_ext != CC_CONFIG_GEN0_EXT0)
return -EOPNOTSUPP;
rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
if (rc)
return rc;
bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
return 0;
}
static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
u32 offset = dbg_cc_param->offset;
u8 cc_gen = dbg_cc_param->cc_gen;
char buf[16];
u32 val;
int rc;
if (count >= sizeof(buf))
return -EINVAL;
if (copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
if (kstrtou32(buf, 0, &val))
return -EINVAL;
rc = bnxt_re_configure_cc(rdev, cc_gen, offset, val);
return rc ? rc : count;
}
static const struct file_operations bnxt_re_cc_config_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = bnxt_re_cc_config_get,
.write = bnxt_re_cc_config_set,
};
static int info_show(struct seq_file *m, void *unused)
{
struct bnxt_re_dev *rdev = m->private;
struct bnxt_re_res_cntrs *res_s = &rdev->stats.res;
seq_puts(m, "Info:\n");
seq_printf(m, "Device Name\t\t: %s\n", dev_name(&rdev->ibdev.dev));
seq_printf(m, "PD Watermark\t\t: %llu\n", res_s->pd_watermark);
seq_printf(m, "AH Watermark\t\t: %llu\n", res_s->ah_watermark);
seq_printf(m, "QP Watermark\t\t: %llu\n", res_s->qp_watermark);
seq_printf(m, "RC QP Watermark\t\t: %llu\n", res_s->rc_qp_watermark);
seq_printf(m, "UD QP Watermark\t\t: %llu\n", res_s->ud_qp_watermark);
seq_printf(m, "SRQ Watermark\t\t: %llu\n", res_s->srq_watermark);
seq_printf(m, "CQ Watermark\t\t: %llu\n", res_s->cq_watermark);
seq_printf(m, "MR Watermark\t\t: %llu\n", res_s->mr_watermark);
seq_printf(m, "MW Watermark\t\t: %llu\n", res_s->mw_watermark);
seq_printf(m, "CQ Resize Count\t\t: %d\n", atomic_read(&res_s->resize_count));
if (rdev->pacing.dbr_pacing) {
seq_printf(m, "DB Pacing Reschedule\t: %llu\n", rdev->stats.pacing.resched);
seq_printf(m, "DB Pacing Complete\t: %llu\n", rdev->stats.pacing.complete);
seq_printf(m, "DB Pacing Alerts\t: %llu\n", rdev->stats.pacing.alerts);
seq_printf(m, "DB FIFO Register\t: 0x%x\n",
readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off));
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(info);
static void bnxt_re_debugfs_add_info(struct bnxt_re_dev *rdev)
{
debugfs_create_file("info", 0400, rdev->dbg_root, rdev, &info_fops);
}
static ssize_t cq_coal_cfg_write(struct file *file,
const char __user *buf,
size_t count, loff_t *pos)
{
struct seq_file *s = file->private_data;
struct bnxt_re_cq_coal_param *param = s->private;
struct bnxt_re_dev *rdev = param->rdev;
int offset = param->offset;
char lbuf[16] = { };
u32 val;
if (count > sizeof(lbuf))
return -EINVAL;
if (copy_from_user(lbuf, buf, count))
return -EFAULT;
lbuf[sizeof(lbuf) - 1] = '\0';
if (kstrtou32(lbuf, 0, &val))
return -EINVAL;
switch (offset) {
case BNXT_RE_COAL_CQ_BUF_MAXTIME:
if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_BUF_MAXTIME)
return -EINVAL;
rdev->cq_coalescing.buf_maxtime = val;
break;
case BNXT_RE_COAL_CQ_NORMAL_MAXBUF:
if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_NORMAL_MAXBUF)
return -EINVAL;
rdev->cq_coalescing.normal_maxbuf = val;
break;
case BNXT_RE_COAL_CQ_DURING_MAXBUF:
if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_DURING_MAXBUF)
return -EINVAL;
rdev->cq_coalescing.during_maxbuf = val;
break;
case BNXT_RE_COAL_CQ_EN_RING_IDLE_MODE:
if (val > BNXT_QPLIB_CQ_COAL_MAX_EN_RING_IDLE_MODE)
return -EINVAL;
rdev->cq_coalescing.en_ring_idle_mode = val;
break;
case BNXT_RE_COAL_CQ_ENABLE:
if (val > 1)
return -EINVAL;
rdev->cq_coalescing.enable = val;
break;
default:
return -EINVAL;
}
return count;
}
static int cq_coal_cfg_show(struct seq_file *s, void *unused)
{
struct bnxt_re_cq_coal_param *param = s->private;
struct bnxt_re_dev *rdev = param->rdev;
int offset = param->offset;
u32 val = 0;
switch (offset) {
case BNXT_RE_COAL_CQ_BUF_MAXTIME:
val = rdev->cq_coalescing.buf_maxtime;
break;
case BNXT_RE_COAL_CQ_NORMAL_MAXBUF:
val = rdev->cq_coalescing.normal_maxbuf;
break;
case BNXT_RE_COAL_CQ_DURING_MAXBUF:
val = rdev->cq_coalescing.during_maxbuf;
break;
case BNXT_RE_COAL_CQ_EN_RING_IDLE_MODE:
val = rdev->cq_coalescing.en_ring_idle_mode;
break;
case BNXT_RE_COAL_CQ_ENABLE:
val = rdev->cq_coalescing.enable;
break;
default:
return -EINVAL;
}
seq_printf(s, "%u\n", val);
return 0;
}
DEFINE_SHOW_STORE_ATTRIBUTE(cq_coal_cfg);
static void bnxt_re_cleanup_cq_coal_debugfs(struct bnxt_re_dev *rdev)
{
debugfs_remove_recursive(rdev->cq_coal_cfg);
kfree(rdev->cq_coal_cfg_params);
}
static void bnxt_re_init_cq_coal_debugfs(struct bnxt_re_dev *rdev)
{
struct bnxt_re_dbg_cq_coal_params *dbg_cq_coal_params;
int i;
if (!_is_cq_coalescing_supported(rdev->dev_attr->dev_cap_flags2))
return;
dbg_cq_coal_params = kzalloc_obj(*dbg_cq_coal_params);
if (!dbg_cq_coal_params)
return;
rdev->cq_coal_cfg = debugfs_create_dir("cq_coal_cfg", rdev->dbg_root);
rdev->cq_coal_cfg_params = dbg_cq_coal_params;
for (i = 0; i < BNXT_RE_COAL_CQ_MAX; i++) {
dbg_cq_coal_params->params[i].offset = i;
dbg_cq_coal_params->params[i].rdev = rdev;
debugfs_create_file(bnxt_re_cq_coal_str[i],
0600, rdev->cq_coal_cfg,
&dbg_cq_coal_params->params[i],
&cq_coal_cfg_fops);
}
}
void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
{
struct pci_dev *pdev = rdev->en_dev->pdev;
struct bnxt_re_dbg_cc_config_params *cc_params;
int i;
rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
rdev->cc_config = debugfs_create_dir("cc_config", rdev->dbg_root);
bnxt_re_debugfs_add_info(rdev);
rdev->cc_config_params = kzalloc_obj(*cc_params);
if (!rdev->cc_config_params)
return;
for (i = 0; i < BNXT_RE_CC_PARAM_GEN0; i++) {
struct bnxt_re_cc_param *tmp_params = &rdev->cc_config_params->gen0_parms[i];
tmp_params->rdev = rdev;
tmp_params->offset = i;
tmp_params->cc_gen = CC_CONFIG_GEN0_EXT0;
tmp_params->dentry = debugfs_create_file(bnxt_re_cc_gen0_name[i], 0400,
rdev->cc_config, tmp_params,
&bnxt_re_cc_config_ops);
}
bnxt_re_init_cq_coal_debugfs(rdev);
}
void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
{
bnxt_re_cleanup_cq_coal_debugfs(rdev);
debugfs_remove_recursive(rdev->qp_debugfs);
debugfs_remove_recursive(rdev->cc_config);
kfree(rdev->cc_config_params);
debugfs_remove_recursive(rdev->dbg_root);
rdev->dbg_root = NULL;
}
void bnxt_re_register_debugfs(void)
{
bnxt_re_debugfs_root = debugfs_create_dir("bnxt_re", NULL);
}
void bnxt_re_unregister_debugfs(void)
{
debugfs_remove(bnxt_re_debugfs_root);
}
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* Copyright (c) 2024, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* Description: Debugfs header
*/
#ifndef __BNXT_RE_DEBUGFS__
#define __BNXT_RE_DEBUGFS__
void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp);
void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp);
void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev);
void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev);
void bnxt_re_register_debugfs(void);
void bnxt_re_unregister_debugfs(void);
#define CC_CONFIG_GEN_EXT(x, y) (((x) << 16) | (y))
#define CC_CONFIG_GEN0_EXT0 CC_CONFIG_GEN_EXT(0, 0)
#define BNXT_RE_CC_PARAM_GEN0 14
struct bnxt_re_cc_param {
struct bnxt_re_dev *rdev;
struct dentry *dentry;
u32 offset;
u8 cc_gen;
};
struct bnxt_re_dbg_cc_config_params {
struct bnxt_re_cc_param gen0_parms[BNXT_RE_CC_PARAM_GEN0];
};
struct bnxt_re_cq_coal_param {
struct bnxt_re_dev *rdev;
u32 offset;
};
enum bnxt_re_cq_coal_types {
BNXT_RE_COAL_CQ_BUF_MAXTIME,
BNXT_RE_COAL_CQ_NORMAL_MAXBUF,
BNXT_RE_COAL_CQ_DURING_MAXBUF,
BNXT_RE_COAL_CQ_EN_RING_IDLE_MODE,
BNXT_RE_COAL_CQ_ENABLE,
BNXT_RE_COAL_CQ_MAX
};
struct bnxt_re_dbg_cq_coal_params {
struct bnxt_re_cq_coal_param params[BNXT_RE_COAL_CQ_MAX];
};
#endif
@@ -0,0 +1,433 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Statistics
*
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <rdma/ib_mad.h>
#include <rdma/ib_pma.h>
#include "roce_hsi.h"
#include "qplib_res.h"
#include "qplib_sp.h"
#include "qplib_fp.h"
#include "qplib_rcfw.h"
#include "bnxt_re.h"
#include "hw_counters.h"
static const struct rdma_stat_desc bnxt_re_stat_descs[] = {
[BNXT_RE_RX_PKTS].name = "rx_pkts",
[BNXT_RE_RX_BYTES].name = "rx_bytes",
[BNXT_RE_TX_PKTS].name = "tx_pkts",
[BNXT_RE_TX_BYTES].name = "tx_bytes",
[BNXT_RE_RECOVERABLE_ERRORS].name = "recoverable_errors",
[BNXT_RE_TX_ERRORS].name = "tx_roce_errors",
[BNXT_RE_TX_DISCARDS].name = "tx_roce_discards",
[BNXT_RE_RX_ERRORS].name = "rx_roce_errors",
[BNXT_RE_RX_DISCARDS].name = "rx_roce_discards",
[BNXT_RE_TO_RETRANSMITS].name = "local_ack_timeout_err",
[BNXT_RE_SEQ_ERR_NAKS_RCVD].name = "packet_seq_err",
[BNXT_RE_MAX_RETRY_EXCEEDED].name = "max_retry_exceeded",
[BNXT_RE_RNR_NAKS_RCVD].name = "rnr_nak_retry_err",
[BNXT_RE_MISSING_RESP].name = "implied_nak_seq_err",
[BNXT_RE_UNRECOVERABLE_ERR].name = "unrecoverable_err",
[BNXT_RE_BAD_RESP_ERR].name = "bad_resp_err",
[BNXT_RE_LOCAL_QP_OP_ERR].name = "local_qp_op_err",
[BNXT_RE_LOCAL_PROTECTION_ERR].name = "local_protection_err",
[BNXT_RE_MEM_MGMT_OP_ERR].name = "mem_mgmt_op_err",
[BNXT_RE_REMOTE_INVALID_REQ_ERR].name = "req_remote_invalid_request",
[BNXT_RE_REMOTE_ACCESS_ERR].name = "req_remote_access_errors",
[BNXT_RE_REMOTE_OP_ERR].name = "remote_op_err",
[BNXT_RE_DUP_REQ].name = "duplicate_request",
[BNXT_RE_RES_EXCEED_MAX].name = "res_exceed_max",
[BNXT_RE_RES_LENGTH_MISMATCH].name = "resp_local_length_error",
[BNXT_RE_RES_EXCEEDS_WQE].name = "res_exceeds_wqe",
[BNXT_RE_RES_OPCODE_ERR].name = "res_opcode_err",
[BNXT_RE_RES_RX_INVALID_RKEY].name = "res_rx_invalid_rkey",
[BNXT_RE_RES_RX_DOMAIN_ERR].name = "res_rx_domain_err",
[BNXT_RE_RES_RX_NO_PERM].name = "res_rx_no_perm",
[BNXT_RE_RES_RX_RANGE_ERR].name = "res_rx_range_err",
[BNXT_RE_RES_TX_INVALID_RKEY].name = "res_tx_invalid_rkey",
[BNXT_RE_RES_TX_DOMAIN_ERR].name = "res_tx_domain_err",
[BNXT_RE_RES_TX_NO_PERM].name = "res_tx_no_perm",
[BNXT_RE_RES_TX_RANGE_ERR].name = "res_tx_range_err",
[BNXT_RE_RES_IRRQ_OFLOW].name = "res_irrq_oflow",
[BNXT_RE_RES_UNSUP_OPCODE].name = "res_unsup_opcode",
[BNXT_RE_RES_UNALIGNED_ATOMIC].name = "res_unaligned_atomic",
[BNXT_RE_RES_REM_INV_ERR].name = "res_rem_inv_err",
[BNXT_RE_RES_MEM_ERROR].name = "res_mem_err",
[BNXT_RE_RES_SRQ_ERR].name = "res_srq_err",
[BNXT_RE_RES_CMP_ERR].name = "res_cmp_err",
[BNXT_RE_RES_INVALID_DUP_RKEY].name = "res_invalid_dup_rkey",
[BNXT_RE_RES_WQE_FORMAT_ERR].name = "res_wqe_format_err",
[BNXT_RE_RES_CQ_LOAD_ERR].name = "res_cq_load_err",
[BNXT_RE_RES_SRQ_LOAD_ERR].name = "res_srq_load_err",
[BNXT_RE_RES_TX_PCI_ERR].name = "res_tx_pci_err",
[BNXT_RE_RES_RX_PCI_ERR].name = "res_rx_pci_err",
[BNXT_RE_OUT_OF_SEQ_ERR].name = "out_of_sequence",
[BNXT_RE_TX_ATOMIC_REQ].name = "tx_atomic_req",
[BNXT_RE_TX_READ_REQ].name = "tx_read_req",
[BNXT_RE_TX_READ_RES].name = "tx_read_resp",
[BNXT_RE_TX_WRITE_REQ].name = "tx_write_req",
[BNXT_RE_TX_SEND_REQ].name = "tx_send_req",
[BNXT_RE_TX_ROCE_PKTS].name = "tx_roce_only_pkts",
[BNXT_RE_TX_ROCE_BYTES].name = "tx_roce_only_bytes",
[BNXT_RE_RX_ATOMIC_REQ].name = "rx_atomic_requests",
[BNXT_RE_RX_READ_REQ].name = "rx_read_requests",
[BNXT_RE_RX_READ_RESP].name = "rx_read_resp",
[BNXT_RE_RX_WRITE_REQ].name = "rx_write_requests",
[BNXT_RE_RX_SEND_REQ].name = "rx_send_req",
[BNXT_RE_RX_ROCE_PKTS].name = "rx_roce_only_pkts",
[BNXT_RE_RX_ROCE_BYTES].name = "rx_roce_only_bytes",
[BNXT_RE_RX_ROCE_GOOD_PKTS].name = "rx_roce_good_pkts",
[BNXT_RE_RX_ROCE_GOOD_BYTES].name = "rx_roce_good_bytes",
[BNXT_RE_OOB].name = "out_of_buffer",
[BNXT_RE_TX_CNP].name = "np_cnp_pkts",
[BNXT_RE_RX_CNP].name = "rp_cnp_handled",
[BNXT_RE_RX_ECN].name = "np_ecn_marked_roce_packets",
[BNXT_RE_REQ_CQE_ERROR].name = "req_cqe_error",
[BNXT_RE_RESP_CQE_ERROR].name = "resp_cqe_error",
[BNXT_RE_RESP_REMOTE_ACCESS_ERRS].name = "resp_remote_access_errors",
};
static void bnxt_re_copy_ext_stats(struct bnxt_re_dev *rdev,
struct rdma_hw_stats *stats,
struct bnxt_qplib_ext_stat *s)
{
stats->value[BNXT_RE_TX_ATOMIC_REQ] = s->tx_atomic_req;
stats->value[BNXT_RE_TX_READ_REQ] = s->tx_read_req;
stats->value[BNXT_RE_TX_READ_RES] = s->tx_read_res;
stats->value[BNXT_RE_TX_WRITE_REQ] = s->tx_write_req;
stats->value[BNXT_RE_TX_SEND_REQ] = s->tx_send_req;
stats->value[BNXT_RE_TX_ROCE_PKTS] = s->tx_roce_pkts;
stats->value[BNXT_RE_TX_ROCE_BYTES] = s->tx_roce_bytes;
stats->value[BNXT_RE_RX_ATOMIC_REQ] = s->rx_atomic_req;
stats->value[BNXT_RE_RX_READ_REQ] = s->rx_read_req;
stats->value[BNXT_RE_RX_READ_RESP] = s->rx_read_res;
stats->value[BNXT_RE_RX_WRITE_REQ] = s->rx_write_req;
stats->value[BNXT_RE_RX_SEND_REQ] = s->rx_send_req;
stats->value[BNXT_RE_RX_ROCE_PKTS] = s->rx_roce_pkts;
stats->value[BNXT_RE_RX_ROCE_BYTES] = s->rx_roce_bytes;
stats->value[BNXT_RE_RX_ROCE_GOOD_PKTS] = s->rx_roce_good_pkts;
stats->value[BNXT_RE_RX_ROCE_GOOD_BYTES] = s->rx_roce_good_bytes;
stats->value[BNXT_RE_OOB] = s->rx_out_of_buffer;
stats->value[BNXT_RE_TX_CNP] = s->tx_cnp;
stats->value[BNXT_RE_RX_CNP] = s->rx_cnp;
stats->value[BNXT_RE_RX_ECN] = s->rx_ecn_marked;
stats->value[BNXT_RE_OUT_OF_SEQ_ERR] = s->rx_out_of_sequence;
}
static int bnxt_re_get_ext_stat(struct bnxt_re_dev *rdev,
struct rdma_hw_stats *stats)
{
struct bnxt_qplib_ext_stat *estat = &rdev->stats.rstat.ext_stat;
u32 fid;
int rc;
fid = PCI_FUNC(rdev->en_dev->pdev->devfn);
rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, estat);
if (rc)
goto done;
bnxt_re_copy_ext_stats(rdev, stats, estat);
done:
return rc;
}
static void bnxt_re_copy_err_stats(struct bnxt_re_dev *rdev,
struct rdma_hw_stats *stats,
struct bnxt_qplib_roce_stats *err_s)
{
stats->value[BNXT_RE_TO_RETRANSMITS] =
err_s->to_retransmits;
stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] =
err_s->seq_err_naks_rcvd;
stats->value[BNXT_RE_MAX_RETRY_EXCEEDED] =
err_s->max_retry_exceeded;
stats->value[BNXT_RE_RNR_NAKS_RCVD] =
err_s->rnr_naks_rcvd;
stats->value[BNXT_RE_MISSING_RESP] =
err_s->missing_resp;
stats->value[BNXT_RE_UNRECOVERABLE_ERR] =
err_s->unrecoverable_err;
stats->value[BNXT_RE_BAD_RESP_ERR] =
err_s->bad_resp_err;
stats->value[BNXT_RE_LOCAL_QP_OP_ERR] =
err_s->local_qp_op_err;
stats->value[BNXT_RE_LOCAL_PROTECTION_ERR] =
err_s->local_protection_err;
stats->value[BNXT_RE_MEM_MGMT_OP_ERR] =
err_s->mem_mgmt_op_err;
stats->value[BNXT_RE_REMOTE_INVALID_REQ_ERR] =
err_s->remote_invalid_req_err;
stats->value[BNXT_RE_REMOTE_ACCESS_ERR] =
err_s->remote_access_err;
stats->value[BNXT_RE_REMOTE_OP_ERR] =
err_s->remote_op_err;
stats->value[BNXT_RE_DUP_REQ] =
err_s->dup_req;
stats->value[BNXT_RE_RES_EXCEED_MAX] =
err_s->res_exceed_max;
stats->value[BNXT_RE_RES_LENGTH_MISMATCH] =
err_s->res_length_mismatch;
stats->value[BNXT_RE_RES_EXCEEDS_WQE] =
err_s->res_exceeds_wqe;
stats->value[BNXT_RE_RES_OPCODE_ERR] =
err_s->res_opcode_err;
stats->value[BNXT_RE_RES_RX_INVALID_RKEY] =
err_s->res_rx_invalid_rkey;
stats->value[BNXT_RE_RES_RX_DOMAIN_ERR] =
err_s->res_rx_domain_err;
stats->value[BNXT_RE_RES_RX_NO_PERM] =
err_s->res_rx_no_perm;
stats->value[BNXT_RE_RES_RX_RANGE_ERR] =
err_s->res_rx_range_err;
stats->value[BNXT_RE_RES_TX_INVALID_RKEY] =
err_s->res_tx_invalid_rkey;
stats->value[BNXT_RE_RES_TX_DOMAIN_ERR] =
err_s->res_tx_domain_err;
stats->value[BNXT_RE_RES_TX_NO_PERM] =
err_s->res_tx_no_perm;
stats->value[BNXT_RE_RES_TX_RANGE_ERR] =
err_s->res_tx_range_err;
stats->value[BNXT_RE_RES_IRRQ_OFLOW] =
err_s->res_irrq_oflow;
stats->value[BNXT_RE_RES_UNSUP_OPCODE] =
err_s->res_unsup_opcode;
stats->value[BNXT_RE_RES_UNALIGNED_ATOMIC] =
err_s->res_unaligned_atomic;
stats->value[BNXT_RE_RES_REM_INV_ERR] =
err_s->res_rem_inv_err;
stats->value[BNXT_RE_RES_MEM_ERROR] =
err_s->res_mem_error;
stats->value[BNXT_RE_RES_SRQ_ERR] =
err_s->res_srq_err;
stats->value[BNXT_RE_RES_CMP_ERR] =
err_s->res_cmp_err;
stats->value[BNXT_RE_RES_INVALID_DUP_RKEY] =
err_s->res_invalid_dup_rkey;
stats->value[BNXT_RE_RES_WQE_FORMAT_ERR] =
err_s->res_wqe_format_err;
stats->value[BNXT_RE_RES_CQ_LOAD_ERR] =
err_s->res_cq_load_err;
stats->value[BNXT_RE_RES_SRQ_LOAD_ERR] =
err_s->res_srq_load_err;
stats->value[BNXT_RE_RES_TX_PCI_ERR] =
err_s->res_tx_pci_err;
stats->value[BNXT_RE_RES_RX_PCI_ERR] =
err_s->res_rx_pci_err;
stats->value[BNXT_RE_OUT_OF_SEQ_ERR] =
err_s->res_oos_drop_count;
stats->value[BNXT_RE_REQ_CQE_ERROR] =
err_s->bad_resp_err +
err_s->local_qp_op_err +
err_s->local_protection_err +
err_s->mem_mgmt_op_err +
err_s->remote_invalid_req_err +
err_s->remote_access_err +
err_s->remote_op_err;
stats->value[BNXT_RE_RESP_CQE_ERROR] =
err_s->res_cmp_err +
err_s->res_cq_load_err;
stats->value[BNXT_RE_RESP_REMOTE_ACCESS_ERRS] =
err_s->res_rx_no_perm +
err_s->res_tx_no_perm;
}
int bnxt_re_assign_pma_port_ext_counters(struct bnxt_re_dev *rdev, struct ib_mad *out_mad)
{
struct ib_pma_portcounters_ext *pma_cnt_ext;
struct bnxt_qplib_ext_stat *estat = &rdev->stats.rstat.ext_stat;
struct ctx_hw_stats *hw_stats = NULL;
int rc;
hw_stats = rdev->qplib_ctx.stats.dma;
pma_cnt_ext = (struct ib_pma_portcounters_ext *)(out_mad->data + 40);
if (_is_ext_stats_supported(rdev->dev_attr->dev_cap_flags)) {
u32 fid = PCI_FUNC(rdev->en_dev->pdev->devfn);
rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, estat);
if (rc)
return rc;
}
pma_cnt_ext = (struct ib_pma_portcounters_ext *)(out_mad->data + 40);
if ((bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) && rdev->is_virtfn) ||
!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
pma_cnt_ext->port_xmit_data =
cpu_to_be64(le64_to_cpu(hw_stats->tx_ucast_bytes) / 4);
pma_cnt_ext->port_rcv_data =
cpu_to_be64(le64_to_cpu(hw_stats->rx_ucast_bytes) / 4);
pma_cnt_ext->port_xmit_packets =
cpu_to_be64(le64_to_cpu(hw_stats->tx_ucast_pkts));
pma_cnt_ext->port_rcv_packets =
cpu_to_be64(le64_to_cpu(hw_stats->rx_ucast_pkts));
pma_cnt_ext->port_unicast_rcv_packets =
cpu_to_be64(le64_to_cpu(hw_stats->rx_ucast_pkts));
pma_cnt_ext->port_unicast_xmit_packets =
cpu_to_be64(le64_to_cpu(hw_stats->tx_ucast_pkts));
} else {
pma_cnt_ext->port_rcv_packets = cpu_to_be64(estat->rx_roce_good_pkts);
pma_cnt_ext->port_rcv_data = cpu_to_be64(estat->rx_roce_good_bytes / 4);
pma_cnt_ext->port_xmit_packets = cpu_to_be64(estat->tx_roce_pkts);
pma_cnt_ext->port_xmit_data = cpu_to_be64(estat->tx_roce_bytes / 4);
pma_cnt_ext->port_unicast_rcv_packets = cpu_to_be64(estat->rx_roce_good_pkts);
pma_cnt_ext->port_unicast_xmit_packets = cpu_to_be64(estat->tx_roce_pkts);
}
return 0;
}
int bnxt_re_assign_pma_port_counters(struct bnxt_re_dev *rdev, struct ib_mad *out_mad)
{
struct bnxt_qplib_ext_stat *estat = &rdev->stats.rstat.ext_stat;
struct ib_pma_portcounters *pma_cnt;
struct ctx_hw_stats *hw_stats = NULL;
int rc;
hw_stats = rdev->qplib_ctx.stats.dma;
pma_cnt = (struct ib_pma_portcounters *)(out_mad->data + 40);
if (_is_ext_stats_supported(rdev->dev_attr->dev_cap_flags)) {
u32 fid = PCI_FUNC(rdev->en_dev->pdev->devfn);
rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, estat);
if (rc)
return rc;
}
if ((bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) && rdev->is_virtfn) ||
!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) {
pma_cnt->port_rcv_packets =
cpu_to_be32((u32)(le64_to_cpu(hw_stats->rx_ucast_pkts)) & 0xFFFFFFFF);
pma_cnt->port_rcv_data =
cpu_to_be32((u32)((le64_to_cpu(hw_stats->rx_ucast_bytes) &
0xFFFFFFFF) / 4));
pma_cnt->port_xmit_packets =
cpu_to_be32((u32)(le64_to_cpu(hw_stats->tx_ucast_pkts)) & 0xFFFFFFFF);
pma_cnt->port_xmit_data =
cpu_to_be32((u32)((le64_to_cpu(hw_stats->tx_ucast_bytes)
& 0xFFFFFFFF) / 4));
} else {
pma_cnt->port_rcv_packets = cpu_to_be32(estat->rx_roce_good_pkts);
pma_cnt->port_rcv_data = cpu_to_be32((estat->rx_roce_good_bytes / 4));
pma_cnt->port_xmit_packets = cpu_to_be32(estat->tx_roce_pkts);
pma_cnt->port_xmit_data = cpu_to_be32((estat->tx_roce_bytes / 4));
}
pma_cnt->port_rcv_constraint_errors = (u8)(le64_to_cpu(hw_stats->rx_discard_pkts) & 0xFF);
pma_cnt->port_rcv_errors = cpu_to_be16((u16)(le64_to_cpu(hw_stats->rx_error_pkts)
& 0xFFFF));
pma_cnt->port_xmit_constraint_errors = (u8)(le64_to_cpu(hw_stats->tx_error_pkts) & 0xFF);
pma_cnt->port_xmit_discards = cpu_to_be16((u16)(le64_to_cpu(hw_stats->tx_discard_pkts)
& 0xFFFF));
return 0;
}
int bnxt_re_ib_get_hw_stats(struct ib_device *ibdev,
struct rdma_hw_stats *stats,
u32 port, int index)
{
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
struct bnxt_qplib_roce_stats *err_s = NULL;
struct ctx_hw_stats *hw_stats = NULL;
int rc = 0;
hw_stats = rdev->qplib_ctx.stats.dma;
if (!port || !stats)
return -EINVAL;
if (hw_stats) {
stats->value[BNXT_RE_RECOVERABLE_ERRORS] =
le64_to_cpu(hw_stats->tx_bcast_pkts);
stats->value[BNXT_RE_TX_DISCARDS] =
le64_to_cpu(hw_stats->tx_discard_pkts);
stats->value[BNXT_RE_TX_ERRORS] =
le64_to_cpu(hw_stats->tx_error_pkts);
stats->value[BNXT_RE_RX_ERRORS] =
le64_to_cpu(hw_stats->rx_error_pkts);
stats->value[BNXT_RE_RX_DISCARDS] =
le64_to_cpu(hw_stats->rx_discard_pkts);
stats->value[BNXT_RE_RX_PKTS] =
le64_to_cpu(hw_stats->rx_ucast_pkts);
stats->value[BNXT_RE_RX_BYTES] =
le64_to_cpu(hw_stats->rx_ucast_bytes);
stats->value[BNXT_RE_TX_PKTS] =
le64_to_cpu(hw_stats->tx_ucast_pkts);
stats->value[BNXT_RE_TX_BYTES] =
le64_to_cpu(hw_stats->tx_ucast_bytes);
}
err_s = &rdev->stats.rstat.errs;
if (test_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags)) {
rc = bnxt_qplib_get_roce_stats(&rdev->rcfw, err_s);
if (rc) {
clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
&rdev->flags);
goto done;
}
bnxt_re_copy_err_stats(rdev, stats, err_s);
if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags,
rdev->is_virtfn)) {
rc = bnxt_re_get_ext_stat(rdev, stats);
if (rc) {
clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
&rdev->flags);
goto done;
}
}
}
done:
return bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ?
BNXT_RE_NUM_EXT_COUNTERS : BNXT_RE_NUM_STD_COUNTERS;
}
struct rdma_hw_stats *bnxt_re_ib_alloc_hw_port_stats(struct ib_device *ibdev,
u32 port_num)
{
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
int num_counters = 0;
if (bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx))
num_counters = BNXT_RE_NUM_EXT_COUNTERS;
else
num_counters = BNXT_RE_NUM_STD_COUNTERS;
return rdma_alloc_hw_stats_struct(bnxt_re_stat_descs, num_counters,
RDMA_HW_STATS_DEFAULT_LIFESPAN);
}
@@ -0,0 +1,165 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Statistics (header)
*
*/
#ifndef __BNXT_RE_HW_STATS_H__
#define __BNXT_RE_HW_STATS_H__
enum bnxt_re_hw_stats {
BNXT_RE_RX_PKTS,
BNXT_RE_RX_BYTES,
BNXT_RE_TX_PKTS,
BNXT_RE_TX_BYTES,
BNXT_RE_RECOVERABLE_ERRORS,
BNXT_RE_TX_ERRORS,
BNXT_RE_TX_DISCARDS,
BNXT_RE_RX_ERRORS,
BNXT_RE_RX_DISCARDS,
BNXT_RE_TO_RETRANSMITS,
BNXT_RE_SEQ_ERR_NAKS_RCVD,
BNXT_RE_MAX_RETRY_EXCEEDED,
BNXT_RE_RNR_NAKS_RCVD,
BNXT_RE_MISSING_RESP,
BNXT_RE_UNRECOVERABLE_ERR,
BNXT_RE_BAD_RESP_ERR,
BNXT_RE_LOCAL_QP_OP_ERR,
BNXT_RE_LOCAL_PROTECTION_ERR,
BNXT_RE_MEM_MGMT_OP_ERR,
BNXT_RE_REMOTE_INVALID_REQ_ERR,
BNXT_RE_REMOTE_ACCESS_ERR,
BNXT_RE_REMOTE_OP_ERR,
BNXT_RE_DUP_REQ,
BNXT_RE_RES_EXCEED_MAX,
BNXT_RE_RES_LENGTH_MISMATCH,
BNXT_RE_RES_EXCEEDS_WQE,
BNXT_RE_RES_OPCODE_ERR,
BNXT_RE_RES_RX_INVALID_RKEY,
BNXT_RE_RES_RX_DOMAIN_ERR,
BNXT_RE_RES_RX_NO_PERM,
BNXT_RE_RES_RX_RANGE_ERR,
BNXT_RE_RES_TX_INVALID_RKEY,
BNXT_RE_RES_TX_DOMAIN_ERR,
BNXT_RE_RES_TX_NO_PERM,
BNXT_RE_RES_TX_RANGE_ERR,
BNXT_RE_RES_IRRQ_OFLOW,
BNXT_RE_RES_UNSUP_OPCODE,
BNXT_RE_RES_UNALIGNED_ATOMIC,
BNXT_RE_RES_REM_INV_ERR,
BNXT_RE_RES_MEM_ERROR,
BNXT_RE_RES_SRQ_ERR,
BNXT_RE_RES_CMP_ERR,
BNXT_RE_RES_INVALID_DUP_RKEY,
BNXT_RE_RES_WQE_FORMAT_ERR,
BNXT_RE_RES_CQ_LOAD_ERR,
BNXT_RE_RES_SRQ_LOAD_ERR,
BNXT_RE_RES_TX_PCI_ERR,
BNXT_RE_RES_RX_PCI_ERR,
BNXT_RE_REQ_CQE_ERROR,
BNXT_RE_RESP_CQE_ERROR,
BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_OUT_OF_SEQ_ERR,
BNXT_RE_TX_ATOMIC_REQ,
BNXT_RE_TX_READ_REQ,
BNXT_RE_TX_READ_RES,
BNXT_RE_TX_WRITE_REQ,
BNXT_RE_TX_SEND_REQ,
BNXT_RE_TX_ROCE_PKTS,
BNXT_RE_TX_ROCE_BYTES,
BNXT_RE_RX_ATOMIC_REQ,
BNXT_RE_RX_READ_REQ,
BNXT_RE_RX_READ_RESP,
BNXT_RE_RX_WRITE_REQ,
BNXT_RE_RX_SEND_REQ,
BNXT_RE_RX_ROCE_PKTS,
BNXT_RE_RX_ROCE_BYTES,
BNXT_RE_RX_ROCE_GOOD_PKTS,
BNXT_RE_RX_ROCE_GOOD_BYTES,
BNXT_RE_OOB,
BNXT_RE_TX_CNP,
BNXT_RE_RX_CNP,
BNXT_RE_RX_ECN,
BNXT_RE_NUM_EXT_COUNTERS
};
#define BNXT_RE_NUM_STD_COUNTERS (BNXT_RE_OUT_OF_SEQ_ERR + 1)
struct bnxt_re_db_pacing_stats {
u64 resched;
u64 complete;
u64 alerts;
};
struct bnxt_re_res_cntrs {
atomic_t qp_count;
atomic_t rc_qp_count;
atomic_t ud_qp_count;
atomic_t cq_count;
atomic_t srq_count;
atomic_t mr_count;
atomic_t mw_count;
atomic_t ah_count;
atomic_t pd_count;
atomic_t resize_count;
u64 qp_watermark;
u64 rc_qp_watermark;
u64 ud_qp_watermark;
u64 cq_watermark;
u64 srq_watermark;
u64 mr_watermark;
u64 mw_watermark;
u64 ah_watermark;
u64 pd_watermark;
};
struct bnxt_re_rstat {
struct bnxt_qplib_roce_stats errs;
struct bnxt_qplib_ext_stat ext_stat;
};
struct bnxt_re_stats {
struct bnxt_re_rstat rstat;
struct bnxt_re_res_cntrs res;
struct bnxt_re_db_pacing_stats pacing;
};
struct rdma_hw_stats *bnxt_re_ib_alloc_hw_port_stats(struct ib_device *ibdev,
u32 port_num);
int bnxt_re_ib_get_hw_stats(struct ib_device *ibdev,
struct rdma_hw_stats *stats,
u32 port, int index);
#endif /* __BNXT_RE_HW_STATS_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,317 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: IB Verbs interpreter (header)
*/
#ifndef __BNXT_RE_IB_VERBS_H__
#define __BNXT_RE_IB_VERBS_H__
struct bnxt_re_gid_ctx {
u32 idx;
u32 refcnt;
};
#define BNXT_RE_FENCE_BYTES 64
struct bnxt_re_fence_data {
u32 size;
u8 va[BNXT_RE_FENCE_BYTES];
dma_addr_t dma_addr;
struct bnxt_re_mr *mr;
struct ib_mw *mw;
struct bnxt_qplib_swqe bind_wqe;
u32 bind_rkey;
};
struct bnxt_re_pd {
struct ib_pd ib_pd;
struct bnxt_re_dev *rdev;
struct bnxt_qplib_pd qplib_pd;
struct bnxt_re_fence_data fence;
struct rdma_user_mmap_entry *pd_db_mmap;
struct rdma_user_mmap_entry *pd_wcdb_mmap;
};
struct bnxt_re_ah {
struct ib_ah ib_ah;
struct bnxt_re_dev *rdev;
struct bnxt_qplib_ah qplib_ah;
};
struct bnxt_re_srq {
struct ib_srq ib_srq;
struct bnxt_re_dev *rdev;
u32 srq_limit;
struct bnxt_qplib_srq qplib_srq;
struct ib_umem *umem;
spinlock_t lock; /* protect srq */
void *uctx_srq_page;
struct hlist_node hash_entry;
};
struct bnxt_re_qp {
struct ib_qp ib_qp;
struct list_head list;
struct bnxt_re_dev *rdev;
spinlock_t sq_lock; /* protect sq */
spinlock_t rq_lock; /* protect rq */
struct bnxt_qplib_qp qplib_qp;
struct ib_umem *sumem;
struct ib_umem *rumem;
/* QP1 */
u32 send_psn;
struct ib_ud_header qp1_hdr;
struct bnxt_re_cq *scq;
struct bnxt_re_cq *rcq;
struct dentry *dentry;
struct bnxt_re_dbr_obj *dbr_obj; /* doorbell region */
};
struct bnxt_re_cq {
struct ib_cq ib_cq;
struct bnxt_re_dev *rdev;
spinlock_t cq_lock; /* protect cq */
u16 cq_count;
u16 cq_period;
struct bnxt_qplib_cq qplib_cq;
struct bnxt_qplib_cqe *cql;
#define MAX_CQL_PER_POLL 1024
u32 max_cql;
struct ib_umem *umem;
struct ib_umem *resize_umem;
int resize_cqe;
void *uctx_cq_page;
struct hlist_node hash_entry;
};
struct bnxt_re_mr {
struct bnxt_re_dev *rdev;
struct ib_mr ib_mr;
struct ib_umem *ib_umem;
struct bnxt_qplib_mrw qplib_mr;
u32 npages;
u64 *pages;
struct bnxt_qplib_frpl qplib_frpl;
};
struct bnxt_re_frpl {
struct bnxt_re_dev *rdev;
struct bnxt_qplib_frpl qplib_frpl;
u64 *page_list;
};
struct bnxt_re_mw {
struct bnxt_re_dev *rdev;
struct ib_mw ib_mw;
struct bnxt_qplib_mrw qplib_mw;
};
struct bnxt_re_ucontext {
struct ib_ucontext ib_uctx;
struct bnxt_re_dev *rdev;
struct bnxt_qplib_dpi dpi;
struct bnxt_qplib_dpi wcdpi;
struct mutex wcdpi_lock; /* serialises WC DPI alloc/free */
void *shpg;
spinlock_t sh_lock; /* protect shpg */
struct rdma_user_mmap_entry *shpage_mmap;
u64 cmask;
};
enum bnxt_re_mmap_flag {
BNXT_RE_MMAP_SH_PAGE,
BNXT_RE_MMAP_UC_DB,
BNXT_RE_MMAP_WC_DB,
BNXT_RE_MMAP_DBR_PAGE,
BNXT_RE_MMAP_DBR_BAR,
BNXT_RE_MMAP_TOGGLE_PAGE,
};
struct bnxt_re_user_mmap_entry {
struct rdma_user_mmap_entry rdma_entry;
struct bnxt_re_ucontext *uctx;
u64 mem_offset;
u8 mmap_flag;
bool dpi_valid;
struct bnxt_qplib_dpi dpi;
};
struct bnxt_re_dbr_obj {
struct bnxt_re_dev *rdev;
struct bnxt_qplib_dpi dpi;
struct bnxt_re_user_mmap_entry *entry;
struct kref usecnt; /* 1 (uobject) + n (QPs using this dbr) */
};
struct bnxt_re_flow {
struct ib_flow ib_flow;
struct bnxt_re_dev *rdev;
};
static inline u16 bnxt_re_get_swqe_size(int nsge)
{
return sizeof(struct sq_send_hdr) + nsge * sizeof(struct sq_sge);
}
static inline u16 bnxt_re_get_rwqe_size(int nsge)
{
return sizeof(struct rq_wqe_hdr) + (nsge * sizeof(struct sq_sge));
}
enum {
BNXT_RE_UCNTX_CAP_POW2_DISABLED = 0x1ULL,
BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED = 0x2ULL,
};
static inline u32 bnxt_re_init_depth(u32 ent, u32 max,
struct bnxt_re_ucontext *uctx)
{
if (uctx && !(uctx->cmask & BNXT_RE_UCNTX_CAP_POW2_DISABLED))
return min(roundup_pow_of_two(ent), max);
return ent;
}
static inline bool bnxt_re_is_var_size_supported(struct bnxt_re_dev *rdev,
struct bnxt_re_ucontext *uctx)
{
if (uctx)
return uctx->cmask & BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED;
else
return rdev->chip_ctx->modes.wqe_mode;
}
int bnxt_re_query_device(struct ib_device *ibdev,
struct ib_device_attr *ib_attr,
struct ib_udata *udata);
int bnxt_re_modify_device(struct ib_device *ibdev,
int device_modify_mask,
struct ib_device_modify *device_modify);
int bnxt_re_query_port(struct ib_device *ibdev, u32 port_num,
struct ib_port_attr *port_attr);
int bnxt_re_get_port_immutable(struct ib_device *ibdev, u32 port_num,
struct ib_port_immutable *immutable);
void bnxt_re_query_fw_str(struct ib_device *ibdev, char *str);
int bnxt_re_query_pkey(struct ib_device *ibdev, u32 port_num,
u16 index, u16 *pkey);
int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context);
int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context);
int bnxt_re_query_gid(struct ib_device *ibdev, u32 port_num,
int index, union ib_gid *gid);
enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
u32 port_num);
int bnxt_re_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
int bnxt_re_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
int bnxt_re_create_ah(struct ib_ah *ah, struct rdma_ah_init_attr *init_attr,
struct ib_udata *udata);
int bnxt_re_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
int bnxt_re_destroy_ah(struct ib_ah *ah, u32 flags);
int bnxt_re_create_srq(struct ib_srq *srq,
struct ib_srq_init_attr *srq_init_attr,
struct ib_udata *udata);
int bnxt_re_modify_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr,
enum ib_srq_attr_mask srq_attr_mask,
struct ib_udata *udata);
int bnxt_re_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
int bnxt_re_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
int bnxt_re_post_srq_recv(struct ib_srq *srq, const struct ib_recv_wr *recv_wr,
const struct ib_recv_wr **bad_recv_wr);
int bnxt_re_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr,
struct ib_udata *udata);
int bnxt_re_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_udata *udata);
int bnxt_re_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
int bnxt_re_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
int bnxt_re_post_send(struct ib_qp *qp, const struct ib_send_wr *send_wr,
const struct ib_send_wr **bad_send_wr);
int bnxt_re_post_recv(struct ib_qp *qp, const struct ib_recv_wr *recv_wr,
const struct ib_recv_wr **bad_recv_wr);
int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs);
int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs);
int bnxt_re_resize_cq(struct ib_cq *ibcq, unsigned int cqe,
struct ib_udata *udata);
int bnxt_re_destroy_cq(struct ib_cq *cq, struct ib_udata *udata);
int bnxt_re_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc);
int bnxt_re_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *pd, int mr_access_flags);
int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
unsigned int *sg_offset);
struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type,
u32 max_num_sg);
int bnxt_re_dereg_mr(struct ib_mr *mr, struct ib_udata *udata);
struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
struct ib_udata *udata);
int bnxt_re_dealloc_mw(struct ib_mw *mw);
struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int mr_access_flags,
struct ib_dmah *dmah,
struct ib_udata *udata);
struct ib_mr *bnxt_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
u64 length, u64 virt_addr,
int fd, int mr_access_flags,
struct ib_dmah *dmah,
struct uverbs_attr_bundle *attrs);
int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata);
void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
struct ib_flow *bnxt_re_create_flow(struct ib_qp *ib_qp,
struct ib_flow_attr *attr,
struct ib_udata *udata);
int bnxt_re_destroy_flow(struct ib_flow *flow_id);
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
int bnxt_re_process_mad(struct ib_device *device, int process_mad_flags,
u32 port_num, const struct ib_wc *in_wc,
const struct ib_grh *in_grh,
const struct ib_mad *in_mad, struct ib_mad *out_mad,
size_t *out_mad_size, u16 *out_mad_pkey_index);
static inline u32 __to_ib_port_num(u16 port_id)
{
return (u32)port_id + 1;
}
unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp);
void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags);
struct bnxt_re_user_mmap_entry*
bnxt_re_mmap_entry_insert(struct bnxt_re_ucontext *uctx, u64 mem_offset,
enum bnxt_re_mmap_flag mmap_flag, u64 *offset);
void bnxt_re_dbr_kref_release(struct kref *ref);
#endif /* __BNXT_RE_IB_VERBS_H__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,700 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Fast Path Operators (header)
*/
#ifndef __BNXT_QPLIB_FP_H__
#define __BNXT_QPLIB_FP_H__
#include <rdma/bnxt_re-abi.h>
/* Few helper structures temporarily defined here
* should get rid of these when roce_hsi.h is updated
* in original code base
*/
struct sq_ud_ext_hdr {
__le32 dst_qp;
__le32 avid;
__le64 rsvd;
};
struct sq_raw_ext_hdr {
__le32 cfa_meta;
__le32 rsvd0;
__le64 rsvd1;
};
struct sq_rdma_ext_hdr {
__le64 remote_va;
__le32 remote_key;
__le32 rsvd;
};
struct sq_atomic_ext_hdr {
__le64 swap_data;
__le64 cmp_data;
};
struct sq_fr_pmr_ext_hdr {
__le64 pblptr;
__le64 va;
};
struct sq_bind_ext_hdr {
__le64 va;
__le32 length_lo;
__le32 length_hi;
};
struct rq_ext_hdr {
__le64 rsvd1;
__le64 rsvd2;
};
/* Helper structures end */
struct bnxt_qplib_srq {
struct bnxt_qplib_pd *pd;
struct bnxt_qplib_dpi *dpi;
struct bnxt_qplib_db_info dbinfo;
u64 srq_handle;
u32 id;
u16 wqe_size;
u32 max_wqe;
u32 max_sge;
u32 threshold;
bool arm_req;
struct bnxt_qplib_cq *cq;
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_swq *swq;
int start_idx;
int last_idx;
struct bnxt_qplib_sg_info sg_info;
u16 eventq_hw_ring_id;
spinlock_t lock; /* protect SRQE link list */
u8 toggle;
};
struct bnxt_qplib_sge {
u64 addr;
u32 lkey;
u32 size;
};
struct bnxt_qplib_swq {
u64 wr_id;
int next_idx;
u8 type;
u8 flags;
u32 start_psn;
u32 next_psn;
u32 slot_idx;
u8 slots;
struct sq_psn_search *psn_search;
struct sq_psn_search_ext *psn_ext;
};
struct bnxt_qplib_swqe {
/* General */
#define BNXT_QPLIB_FENCE_WRID 0x46454E43 /* "FENC" */
u64 wr_id;
u8 reqs_type;
u8 type;
#define BNXT_QPLIB_SWQE_TYPE_SEND 0
#define BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM 1
#define BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV 2
#define BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE 4
#define BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM 5
#define BNXT_QPLIB_SWQE_TYPE_RDMA_READ 6
#define BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP 8
#define BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD 11
#define BNXT_QPLIB_SWQE_TYPE_LOCAL_INV 12
#define BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR 13
#define BNXT_QPLIB_SWQE_TYPE_REG_MR 13
#define BNXT_QPLIB_SWQE_TYPE_BIND_MW 14
#define BNXT_QPLIB_SWQE_TYPE_RECV 128
#define BNXT_QPLIB_SWQE_TYPE_RECV_RDMA_IMM 129
u8 flags;
#define BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP BIT(0)
#define BNXT_QPLIB_SWQE_FLAGS_RD_ATOMIC_FENCE BIT(1)
#define BNXT_QPLIB_SWQE_FLAGS_UC_FENCE BIT(2)
#define BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT BIT(3)
#define BNXT_QPLIB_SWQE_FLAGS_INLINE BIT(4)
struct bnxt_qplib_sge sg_list[BNXT_VAR_MAX_SGE];
int num_sge;
/* Max inline data is 96 bytes */
u32 inline_len;
#define BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH 96
u8 inline_data[BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH];
union {
/* Send, with imm, inval key */
struct {
union {
u32 imm_data;
u32 inv_key;
};
u32 q_key;
u32 dst_qp;
u32 avid;
} send;
/* Send Raw Ethernet and QP1 */
struct {
u16 lflags;
u16 cfa_action;
u32 cfa_meta;
} rawqp1;
/* RDMA write, with imm, read */
struct {
union {
u32 imm_data;
u32 inv_key;
};
u64 remote_va;
u32 r_key;
} rdma;
/* Atomic cmp/swap, fetch/add */
struct {
u64 remote_va;
u32 r_key;
u64 swap_data;
u64 cmp_data;
} atomic;
/* Local Invalidate */
struct {
u32 inv_l_key;
} local_inv;
/* FR-PMR */
struct {
u8 access_cntl;
u8 pg_sz_log;
bool zero_based;
u32 l_key;
u32 length;
u8 pbl_pg_sz_log;
#define BNXT_QPLIB_SWQE_PAGE_SIZE_4K 0
#define BNXT_QPLIB_SWQE_PAGE_SIZE_8K 1
#define BNXT_QPLIB_SWQE_PAGE_SIZE_64K 4
#define BNXT_QPLIB_SWQE_PAGE_SIZE_256K 6
#define BNXT_QPLIB_SWQE_PAGE_SIZE_1M 8
#define BNXT_QPLIB_SWQE_PAGE_SIZE_2M 9
#define BNXT_QPLIB_SWQE_PAGE_SIZE_4M 10
#define BNXT_QPLIB_SWQE_PAGE_SIZE_1G 18
u8 levels;
#define PAGE_SHIFT_4K 12
__le64 *pbl_ptr;
dma_addr_t pbl_dma_ptr;
u64 *page_list;
u16 page_list_len;
u64 va;
} frmr;
/* Bind */
struct {
u8 access_cntl;
#define BNXT_QPLIB_BIND_SWQE_ACCESS_LOCAL_WRITE BIT(0)
#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_READ BIT(1)
#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_WRITE BIT(2)
#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_ATOMIC BIT(3)
#define BNXT_QPLIB_BIND_SWQE_ACCESS_WINDOW_BIND BIT(4)
bool zero_based;
u8 mw_type;
u32 parent_l_key;
u32 r_key;
u64 va;
u32 length;
} bind;
};
};
struct bnxt_qplib_q {
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_swq *swq;
struct bnxt_qplib_db_info dbinfo;
struct bnxt_qplib_sg_info sg_info;
u32 max_wqe;
u32 max_sw_wqe;
u16 wqe_size;
u16 q_full_delta;
u16 max_sge;
u32 psn;
bool condition;
bool single;
bool send_phantom;
u32 phantom_wqe_cnt;
u32 phantom_cqe_cnt;
u32 next_cq_cons;
bool flushed;
u32 swq_start;
u32 swq_last;
};
struct bnxt_qplib_qp {
struct bnxt_qplib_pd *pd;
struct bnxt_qplib_dpi *dpi;
struct bnxt_qplib_chip_ctx *cctx;
u64 qp_handle;
#define BNXT_QPLIB_QP_ID_INVALID 0xFFFFFFFF
u32 id;
u8 type;
u8 sig_type;
u8 wqe_mode;
u8 state;
u8 cur_qp_state;
u8 is_user;
u64 modify_flags;
u32 ext_modify_flags;
u32 max_inline_data;
u32 mtu;
u8 path_mtu;
bool en_sqd_async_notify;
u16 pkey_index;
u32 qkey;
u32 dest_qp_id;
u8 access;
u8 timeout;
u8 retry_cnt;
u8 rnr_retry;
u64 wqe_cnt;
u32 min_rnr_timer;
u32 max_rd_atomic;
u32 max_dest_rd_atomic;
u32 dest_qpn;
u8 smac[6];
u16 vlan_id;
u16 port_id;
u16 udp_sport;
u8 nw_type;
struct bnxt_qplib_ah ah;
#define BTH_PSN_MASK ((1 << 24) - 1)
/* SQ */
struct bnxt_qplib_q sq;
/* RQ */
struct bnxt_qplib_q rq;
/* SRQ */
struct bnxt_qplib_srq *srq;
/* CQ */
struct bnxt_qplib_cq *scq;
struct bnxt_qplib_cq *rcq;
/* IRRQ and ORRQ */
struct bnxt_qplib_hwq irrq;
struct bnxt_qplib_hwq orrq;
/* Header buffer for QP1 */
int sq_hdr_buf_size;
int rq_hdr_buf_size;
/*
* Buffer space for ETH(14), IP or GRH(40), UDP header(8)
* and ib_bth + ib_deth (20).
* Max required is 82 when RoCE V2 is enabled
*/
#define BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2 86
/* Ethernet header = 14 */
/* ib_grh = 40 (provided by MAD) */
/* ib_bth + ib_deth = 20 */
/* MAD = 256 (provided by MAD) */
/* iCRC = 4 */
#define BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE 14
#define BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2 512
#define BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV4 20
#define BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6 40
#define BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE 20
void *sq_hdr_buf;
dma_addr_t sq_hdr_buf_map;
void *rq_hdr_buf;
dma_addr_t rq_hdr_buf_map;
struct list_head sq_flush;
struct list_head rq_flush;
u32 msn;
u32 msn_tbl_sz;
u32 psn_sz;
bool is_host_msn_tbl;
u8 tos_dscp;
u32 ugid_index;
u16 dev_cap_flags;
u32 rate_limit;
u8 shaper_allocation_status;
};
#define BNXT_RE_MAX_MSG_SIZE 0x80000000
#define BNXT_RE_INVAL_MSG_SIZE 0xFFFFFFFF
#define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base)
#define CQE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_MAX_CQE_ENTRY_SIZE)
#define CQE_MAX_IDX_PER_PG (CQE_CNT_PER_PG - 1)
#define CQE_PG(x) (((x) & ~CQE_MAX_IDX_PER_PG) / CQE_CNT_PER_PG)
#define CQE_IDX(x) ((x) & CQE_MAX_IDX_PER_PG)
#define ROCE_CQE_CMP_V 0
#define CQE_CMP_VALID(hdr, pass) \
(!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \
!((pass) & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK))
static inline u32 __bnxt_qplib_get_avail(struct bnxt_qplib_hwq *hwq)
{
int cons, prod, avail;
cons = hwq->cons;
prod = hwq->prod;
avail = cons - prod;
if (cons <= prod)
avail += hwq->depth;
return avail;
}
static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *que,
u8 slots)
{
struct bnxt_qplib_hwq *hwq;
int avail;
hwq = &que->hwq;
/* False full is possible, retrying post-send makes sense */
avail = hwq->cons - hwq->prod;
if (hwq->cons <= hwq->prod)
avail += hwq->depth;
return avail <= slots;
}
/* CQ coalescing parameters */
struct bnxt_qplib_cq_coal_param {
u16 buf_maxtime;
u8 normal_maxbuf;
u8 during_maxbuf;
u8 en_ring_idle_mode;
u8 enable;
};
#define BNXT_QPLIB_CQ_COAL_DEF_BUF_MAXTIME 0x1
#define BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P7 0x8
#define BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P7 0x8
#define BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P5 0x1
#define BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P5 0x1
#define BNXT_QPLIB_CQ_COAL_DEF_EN_RING_IDLE_MODE 0x1
#define BNXT_QPLIB_CQ_COAL_MAX_BUF_MAXTIME 0x1bf
#define BNXT_QPLIB_CQ_COAL_MAX_NORMAL_MAXBUF 0x1f
#define BNXT_QPLIB_CQ_COAL_MAX_DURING_MAXBUF 0x1f
#define BNXT_QPLIB_CQ_COAL_MAX_EN_RING_IDLE_MODE 0x1
struct bnxt_qplib_cqe {
u8 status;
u8 type;
u8 opcode;
u32 length;
u16 cfa_meta;
u64 wr_id;
union {
u32 immdata;
u32 invrkey;
};
u64 qp_handle;
u64 mr_handle;
u16 flags;
u8 smac[6];
u32 src_qp;
u16 raweth_qp1_flags;
u16 raweth_qp1_errors;
u16 raweth_qp1_cfa_code;
u32 raweth_qp1_flags2;
u32 raweth_qp1_metadata;
u8 raweth_qp1_payload_offset;
u16 pkey_index;
};
#define BNXT_QPLIB_QUEUE_START_PERIOD 0x01
struct bnxt_qplib_cq {
struct bnxt_qplib_dpi *dpi;
struct bnxt_qplib_db_info dbinfo;
u32 max_wqe;
u32 id;
u16 count;
u16 period;
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_hwq resize_hwq;
u32 cnq_hw_ring_id;
struct bnxt_qplib_nq *nq;
bool resize_in_progress;
struct bnxt_qplib_sg_info sg_info;
u64 cq_handle;
u8 toggle;
#define CQ_RESIZE_WAIT_TIME_MS 500
unsigned long flags;
#define CQ_FLAGS_RESIZE_IN_PROG 1
wait_queue_head_t waitq;
struct list_head sqf_head, rqf_head;
atomic_t arm_state;
spinlock_t compl_lock; /* synch CQ handlers */
/* Locking Notes:
* QP can move to error state from modify_qp, async error event or error
* CQE as part of poll_cq. When QP is moved to error state, it gets added
* to two flush lists, one each for SQ and RQ.
* Each flush list is protected by qplib_cq->flush_lock. Both scq and rcq
* flush_locks should be acquired when QP is moved to error. The control path
* operations(modify_qp and async error events) are synchronized with poll_cq
* using upper level CQ locks (bnxt_re_cq->cq_lock) of both SCQ and RCQ.
* The qplib_cq->flush_lock is required to synchronize two instances of poll_cq
* of the same QP while manipulating the flush list.
*/
spinlock_t flush_lock; /* QP flush management */
u16 cnq_events;
struct bnxt_qplib_cq_coal_param *coalescing;
};
#define BNXT_QPLIB_MAX_IRRQE_ENTRY_SIZE sizeof(struct xrrq_irrq)
#define BNXT_QPLIB_MAX_ORRQE_ENTRY_SIZE sizeof(struct xrrq_orrq)
#define IRD_LIMIT_TO_IRRQ_SLOTS(x) (2 * (x) + 2)
#define IRRQ_SLOTS_TO_IRD_LIMIT(s) (((s) >> 1) - 1)
#define ORD_LIMIT_TO_ORRQ_SLOTS(x) ((x) + 1)
#define ORRQ_SLOTS_TO_ORD_LIMIT(s) ((s) - 1)
#define BNXT_QPLIB_MAX_NQE_ENTRY_SIZE sizeof(struct nq_base)
#define NQE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_MAX_NQE_ENTRY_SIZE)
#define NQE_MAX_IDX_PER_PG (NQE_CNT_PER_PG - 1)
#define NQE_PG(x) (((x) & ~NQE_MAX_IDX_PER_PG) / NQE_CNT_PER_PG)
#define NQE_IDX(x) ((x) & NQE_MAX_IDX_PER_PG)
#define NQE_CMP_VALID(hdr, pass) \
(!!(le32_to_cpu((hdr)->info63_v[0]) & NQ_BASE_V) == \
!((pass) & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK))
#define BNXT_QPLIB_NQE_MAX_CNT (128 * 1024)
#define NQ_CONS_PCI_BAR_REGION 2
#define NQ_DB_KEY_CP (0x2 << CMPL_DOORBELL_KEY_SFT)
#define NQ_DB_IDX_VALID CMPL_DOORBELL_IDX_VALID
#define NQ_DB_IRQ_DIS CMPL_DOORBELL_MASK
#define NQ_DB_CP_FLAGS_REARM (NQ_DB_KEY_CP | \
NQ_DB_IDX_VALID)
#define NQ_DB_CP_FLAGS (NQ_DB_KEY_CP | \
NQ_DB_IDX_VALID | \
NQ_DB_IRQ_DIS)
struct bnxt_qplib_nq_db {
struct bnxt_qplib_reg_desc reg;
struct bnxt_qplib_db_info dbinfo;
};
typedef int (*cqn_handler_t)(struct bnxt_qplib_nq *nq,
struct bnxt_qplib_cq *cq);
typedef int (*srqn_handler_t)(struct bnxt_qplib_nq *nq,
struct bnxt_qplib_srq *srq, u8 event);
struct bnxt_qplib_nq {
struct pci_dev *pdev;
struct bnxt_qplib_res *res;
char *name;
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_nq_db nq_db;
u16 ring_id;
int msix_vec;
cpumask_t mask;
struct tasklet_struct nq_tasklet;
bool requested;
int budget;
u32 load;
cqn_handler_t cqn_handler;
srqn_handler_t srqn_handler;
struct workqueue_struct *cqn_wq;
};
struct bnxt_qplib_nq_work {
struct work_struct work;
struct bnxt_qplib_nq *nq;
struct bnxt_qplib_cq *cq;
};
void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill);
void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq);
int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx,
int msix_vector, bool need_init);
int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq,
int nq_idx, int msix_vector, int bar_reg_offset,
cqn_handler_t cqn_handler,
srqn_handler_t srq_handler);
int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
struct bnxt_qplib_srq *srq);
int bnxt_qplib_query_srq(struct bnxt_qplib_res *res,
struct bnxt_qplib_srq *srq);
void bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res,
struct bnxt_qplib_srq *srq);
int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq,
struct bnxt_qplib_swqe *wqe);
int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp);
void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res,
struct bnxt_qplib_qp *qp);
void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_sge *sge);
void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_sge *sge);
u32 bnxt_qplib_get_rq_prod_index(struct bnxt_qplib_qp *qp);
dma_addr_t bnxt_qplib_get_qp_buf_from_index(struct bnxt_qplib_qp *qp,
u32 index);
void bnxt_qplib_post_send_db(struct bnxt_qplib_qp *qp);
int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_swqe *wqe);
void bnxt_qplib_post_recv_db(struct bnxt_qplib_qp *qp);
int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_swqe *wqe);
int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_resize_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq,
int new_cqes);
void bnxt_qplib_resize_cq_complete(struct bnxt_qplib_res *res,
struct bnxt_qplib_cq *cq);
int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
int num, struct bnxt_qplib_qp **qp);
bool bnxt_qplib_is_cq_empty(struct bnxt_qplib_cq *cq);
void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type);
void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq);
int bnxt_qplib_alloc_nq(struct bnxt_qplib_res *res, struct bnxt_qplib_nq *nq);
void bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp);
void bnxt_qplib_acquire_cq_locks(struct bnxt_qplib_qp *qp,
unsigned long *flags);
void bnxt_qplib_release_cq_locks(struct bnxt_qplib_qp *qp,
unsigned long *flags);
int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
struct bnxt_qplib_cqe *cqe,
int num_cqes);
void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq);
static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx)
{
u32 idx;
idx = que->swq_start;
if (swq_idx)
*swq_idx = idx;
return &que->swq[idx];
}
static inline void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx)
{
que->swq_start = que->swq[idx].next_idx;
}
static inline u32 bnxt_qplib_get_stride(void)
{
return sizeof(struct sq_sge);
}
static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq)
{
u32 slots;
/* Queue depth is the number of slots. */
slots = (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge);
/* For variable WQE mode, need to align the slots to 256 */
if (wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE && is_sq)
slots = ALIGN(slots, BNXT_VAR_MAX_SLOT_ALIGN);
return slots;
}
static inline u32 bnxt_qplib_set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode)
{
return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
que->max_wqe : bnxt_qplib_get_depth(que, wqe_mode, true);
}
static inline u32 bnxt_qplib_set_sq_max_slot(u8 wqe_mode)
{
return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
sizeof(struct sq_send) / sizeof(struct sq_sge) : 1;
}
static inline u32 bnxt_qplib_set_rq_max_slot(u32 wqe_size)
{
return (wqe_size / sizeof(struct sq_sge));
}
static inline u16 __xlate_qfd(u16 delta, u16 wqe_bytes)
{
/* For Cu/Wh delta = 128, stride = 16, wqe_bytes = 128
* For Gen-p5 B/C mode delta = 0, stride = 16, wqe_bytes = 128.
* For Gen-p5 delta = 0, stride = 16, 32 <= wqe_bytes <= 512.
* when 8916 is disabled.
*/
return (delta * wqe_bytes) / sizeof(struct sq_sge);
}
static inline u16 bnxt_qplib_calc_ilsize(struct bnxt_qplib_swqe *wqe, u16 max)
{
u16 size = 0;
int indx;
for (indx = 0; indx < wqe->num_sge; indx++)
size += wqe->sg_list[indx].size;
if (size > max)
size = max;
return size;
}
/* MSN table update inlin */
static inline __le64 bnxt_re_update_msn_tbl(u32 st_idx, u32 npsn, u32 start_psn)
{
return cpu_to_le64((((u64)(st_idx) << SQ_MSN_SEARCH_START_IDX_SFT) &
SQ_MSN_SEARCH_START_IDX_MASK) |
(((u64)(npsn) << SQ_MSN_SEARCH_NEXT_PSN_SFT) &
SQ_MSN_SEARCH_NEXT_PSN_MASK) |
(((start_psn) << SQ_MSN_SEARCH_START_PSN_SFT) &
SQ_MSN_SEARCH_START_PSN_MASK));
}
static inline bool __is_var_wqe(struct bnxt_qplib_qp *qp)
{
return (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE);
}
static inline bool __is_err_cqe_for_var_wqe(struct bnxt_qplib_qp *qp, u8 status)
{
return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
}
#endif /* __BNXT_QPLIB_FP_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,294 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: RDMA Controller HW interface (header)
*/
#ifndef __BNXT_QPLIB_RCFW_H__
#define __BNXT_QPLIB_RCFW_H__
#include "qplib_tlv.h"
#define RCFW_CMDQ_TRIG_VAL 1
#define RCFW_COMM_PCI_BAR_REGION 0
#define RCFW_COMM_CONS_PCI_BAR_REGION 2
#define RCFW_COMM_BASE_OFFSET 0x600
#define RCFW_PF_VF_COMM_PROD_OFFSET 0xc
#define RCFW_COMM_TRIG_OFFSET 0x100
#define RCFW_COMM_SIZE 0x104
#define RCFW_DBR_PCI_BAR_REGION 2
#define RCFW_DBR_BASE_PAGE_SHIFT 12
#define RCFW_FW_STALL_MAX_TIMEOUT 40
/* Cmdq contains a fix number of a 16-Byte slots */
struct bnxt_qplib_cmdqe {
u8 data[16];
};
#define BNXT_QPLIB_CMDQE_UNITS sizeof(struct bnxt_qplib_cmdqe)
static inline void bnxt_qplib_rcfw_cmd_prep(struct cmdq_base *req,
u8 opcode, u8 cmd_size)
{
req->opcode = opcode;
req->cmd_size = cmd_size;
}
/* Shadow queue depth for non blocking command */
#define RCFW_CMD_NON_BLOCKING_SHADOW_QD 64
#define RCFW_CMD_WAIT_TIME_MS 20000 /* 20 Seconds timeout */
/* CMDQ elements */
#define BNXT_QPLIB_CMDQE_MAX_CNT 8192
#define BNXT_QPLIB_CMDQE_BYTES(depth) ((depth) * BNXT_QPLIB_CMDQE_UNITS)
static inline u32 bnxt_qplib_cmdqe_npages(u32 depth)
{
u32 npages;
npages = BNXT_QPLIB_CMDQE_BYTES(depth) / PAGE_SIZE;
if (BNXT_QPLIB_CMDQE_BYTES(depth) % PAGE_SIZE)
npages++;
return npages;
}
static inline u32 bnxt_qplib_cmdqe_page_size(u32 depth)
{
return (bnxt_qplib_cmdqe_npages(depth) * PAGE_SIZE);
}
/* Get the number of command units required for the req. The
* function returns correct value only if called before
* setting using bnxt_qplib_set_cmd_slots
*/
static inline u32 bnxt_qplib_get_cmd_slots(struct cmdq_base *req)
{
u32 cmd_units = 0;
if (HAS_TLV_HEADER(req)) {
struct roce_tlv *tlv_req = (struct roce_tlv *)req;
cmd_units = tlv_req->total_size;
} else {
cmd_units = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
BNXT_QPLIB_CMDQE_UNITS;
}
return cmd_units;
}
static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
{
u32 cmd_byte = 0;
if (HAS_TLV_HEADER(req)) {
struct roce_tlv *tlv_req = (struct roce_tlv *)req;
cmd_byte = tlv_req->total_size * BNXT_QPLIB_CMDQE_UNITS;
} else {
cmd_byte = req->cmd_size;
req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
BNXT_QPLIB_CMDQE_UNITS;
}
return cmd_byte;
}
#define RCFW_MAX_COOKIE_VALUE (BNXT_QPLIB_CMDQE_MAX_CNT - 1)
#define RCFW_CMD_IS_BLOCKING 0x8000
#define HWRM_VERSION_DEV_ATTR_MAX_DPI 0x1000A0000000DULL
/* HWRM version 1.10.3.18 */
#define HWRM_VERSION_READ_CTX 0x1000A00030012
/* Crsq buf is 1024-Byte */
struct bnxt_qplib_crsbe {
u8 data[1024];
};
/* CREQ */
/* Allocate 1 per QP for async error notification for now */
#define BNXT_QPLIB_CREQE_MAX_CNT (64 * 1024)
#define BNXT_QPLIB_CREQE_UNITS 16 /* 16-Bytes per prod unit */
#define CREQ_CMP_VALID(hdr, pass) \
(!!((hdr)->v & CREQ_BASE_V) == \
!((pass) & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK))
#define CREQ_ENTRY_POLL_BUDGET 0x100
/* HWQ */
typedef int (*aeq_handler_t)(struct bnxt_qplib_rcfw *, void *, void *);
struct bnxt_qplib_crsqe {
struct creq_qp_event *resp;
u32 req_size;
/* Free slots at the time of submission */
u32 free_slots;
u8 opcode;
bool is_waiter_alive;
bool is_internal_cmd;
bool is_in_used;
};
struct bnxt_qplib_rcfw_sbuf {
void *sb;
dma_addr_t dma_addr;
u32 size;
};
struct bnxt_qplib_qp_node {
u32 qp_id; /* QP id */
void *qp_handle; /* ptr to qplib_qp */
};
#define BNXT_QPLIB_OOS_COUNT_MASK 0xFFFFFFFF
#define FIRMWARE_INITIALIZED_FLAG (0)
#define FIRMWARE_FIRST_FLAG (31)
#define FIRMWARE_STALL_DETECTED (3)
#define ERR_DEVICE_DETACHED (4)
struct bnxt_qplib_cmdq_mbox {
struct bnxt_qplib_reg_desc reg;
void __iomem *prod;
void __iomem *db;
};
struct bnxt_qplib_cmdq_ctx {
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_cmdq_mbox cmdq_mbox;
wait_queue_head_t waitq;
unsigned long flags;
unsigned long last_seen;
u32 seq_num;
};
struct bnxt_qplib_creq_db {
struct bnxt_qplib_reg_desc reg;
struct bnxt_qplib_db_info dbinfo;
};
struct bnxt_qplib_creq_stat {
u64 creq_qp_event_processed;
u64 creq_func_event_processed;
};
struct bnxt_qplib_creq_ctx {
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_creq_db creq_db;
struct bnxt_qplib_creq_stat stats;
struct tasklet_struct creq_tasklet;
aeq_handler_t aeq_handler;
u16 ring_id;
int msix_vec;
bool requested; /*irq handler installed */
char *irq_name;
};
/* RCFW Communication Channels */
struct bnxt_qplib_rcfw {
struct pci_dev *pdev;
struct bnxt_qplib_res *res;
struct bnxt_qplib_cmdq_ctx cmdq;
struct bnxt_qplib_creq_ctx creq;
struct bnxt_qplib_crsqe *crsqe_tbl;
int qp_tbl_size;
struct bnxt_qplib_qp_node *qp_tbl;
/* To synchronize the qp-handle hash table */
spinlock_t tbl_lock;
u64 oos_prev;
u32 init_oos_stats;
u32 cmdq_depth;
atomic_t rcfw_intr_enabled;
struct semaphore rcfw_inflight;
atomic_t timeout_send;
/* cached from chip cctx for quick reference in slow path */
u16 max_timeout;
bool roce_mirror;
};
struct bnxt_qplib_cmdqmsg {
struct cmdq_base *req;
struct creq_base *resp;
void *sb;
u32 req_sz;
u32 res_sz;
u8 block;
};
static inline void bnxt_qplib_fill_cmdqmsg(struct bnxt_qplib_cmdqmsg *msg,
void *req, void *resp, void *sb,
u32 req_sz, u32 res_sz, u8 block)
{
msg->req = req;
msg->resp = resp;
msg->sb = sb;
msg->req_sz = req_sz;
msg->res_sz = res_sz;
msg->block = block;
}
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx);
void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill);
void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector,
bool need_init);
int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
int msix_vector,
int cp_bar_reg_off,
aeq_handler_t aeq_handler);
struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
struct bnxt_qplib_rcfw *rcfw,
u32 size);
void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_rcfw_sbuf *sbuf);
int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_cmdqmsg *msg);
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx, int is_virtfn);
void bnxt_qplib_mark_qp_error(void *qp_handle);
static inline u32 map_qp_id_to_tbl_indx(u32 qid, struct bnxt_qplib_rcfw *rcfw)
{
/* Last index of the qp_tbl is for QP1 ie. qp_tbl_size - 1*/
return (qid == 1) ? rcfw->qp_tbl_size - 1 : (qid % (rcfw->qp_tbl_size - 2));
}
#endif /* __BNXT_QPLIB_RCFW_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,642 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: QPLib resource manager (header)
*/
#ifndef __BNXT_QPLIB_RES_H__
#define __BNXT_QPLIB_RES_H__
#include <linux/bnxt/ulp.h>
extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
#define CHIP_NUM_57508 0x1750
#define CHIP_NUM_57504 0x1751
#define CHIP_NUM_57502 0x1752
#define CHIP_NUM_58818 0xd818
#define CHIP_NUM_57608 0x1760
#define BNXT_RE_MAX_QPC_COUNT (64 * 1024)
#define BNXT_RE_MAX_MRW_COUNT (64 * 1024)
#define BNXT_RE_MAX_SRQC_COUNT (64 * 1024)
#define BNXT_RE_MAX_CQ_COUNT (64 * 1024)
#define BNXT_RE_MAX_MRW_COUNT_64K (64 * 1024)
#define BNXT_RE_MAX_MRW_COUNT_256K (256 * 1024)
#define BNXT_QPLIB_DBR_VALID (0x1UL << 26)
#define BNXT_QPLIB_DBR_EPOCH_SHIFT 24
#define BNXT_QPLIB_DBR_TOGGLE_SHIFT 25
struct bnxt_qplib_drv_modes {
u8 wqe_mode;
bool db_push;
bool dbr_pacing;
u32 toggle_bits;
u8 roce_mirror;
};
enum bnxt_re_toggle_modes {
BNXT_QPLIB_CQ_TOGGLE_BIT = 0x1,
BNXT_QPLIB_SRQ_TOGGLE_BIT = 0x2,
};
struct bnxt_qplib_chip_ctx {
u16 chip_num;
u8 chip_rev;
u8 chip_metal;
u16 hw_stats_size;
u16 hwrm_cmd_max_timeout;
struct bnxt_qplib_drv_modes modes;
u64 hwrm_intf_ver;
u32 dbr_stat_db_fifo;
};
struct bnxt_qplib_db_pacing_data {
u32 do_pacing;
u32 pacing_th;
u32 alarm_th;
u32 fifo_max_depth;
u32 fifo_room_mask;
u32 fifo_room_shift;
u32 grc_reg_offset;
u32 dev_err_state;
};
#define BNXT_QPLIB_DBR_PF_DB_OFFSET 0x10000
#define BNXT_QPLIB_DBR_VF_DB_OFFSET 0x4000
#define PTR_CNT_PER_PG (PAGE_SIZE / sizeof(void *))
#define PTR_MAX_IDX_PER_PG (PTR_CNT_PER_PG - 1)
#define PTR_PG(x) (((x) & ~PTR_MAX_IDX_PER_PG) / PTR_CNT_PER_PG)
#define PTR_IDX(x) ((x) & PTR_MAX_IDX_PER_PG)
#define HWQ_CMP(idx, hwq) ((idx) & ((hwq)->max_elements - 1))
#define HWQ_FREE_SLOTS(hwq) (hwq->max_elements - \
((HWQ_CMP(hwq->prod, hwq)\
- HWQ_CMP(hwq->cons, hwq))\
& (hwq->max_elements - 1)))
enum bnxt_qplib_hwq_type {
HWQ_TYPE_CTX,
HWQ_TYPE_QUEUE,
HWQ_TYPE_L2_CMPL,
HWQ_TYPE_MR
};
#define MAX_PBL_LVL_0_PGS 1
#define MAX_PBL_LVL_1_PGS 512
#define MAX_PBL_LVL_1_PGS_SHIFT 9
#define MAX_PBL_LVL_1_PGS_FOR_LVL_2 256
#define MAX_PBL_LVL_2_PGS (256 * 512)
#define MAX_PDL_LVL_SHIFT 9
enum bnxt_qplib_pbl_lvl {
PBL_LVL_0,
PBL_LVL_1,
PBL_LVL_2,
PBL_LVL_MAX
};
#define ROCE_PG_SIZE_4K (4 * 1024)
#define ROCE_PG_SIZE_8K (8 * 1024)
#define ROCE_PG_SIZE_64K (64 * 1024)
#define ROCE_PG_SIZE_2M (2 * 1024 * 1024)
#define ROCE_PG_SIZE_8M (8 * 1024 * 1024)
#define ROCE_PG_SIZE_1G (1024 * 1024 * 1024)
enum bnxt_qplib_hwrm_pg_size {
BNXT_QPLIB_HWRM_PG_SIZE_4K = 0,
BNXT_QPLIB_HWRM_PG_SIZE_8K = 1,
BNXT_QPLIB_HWRM_PG_SIZE_64K = 2,
BNXT_QPLIB_HWRM_PG_SIZE_2M = 3,
BNXT_QPLIB_HWRM_PG_SIZE_8M = 4,
BNXT_QPLIB_HWRM_PG_SIZE_1G = 5,
};
struct bnxt_qplib_reg_desc {
u8 bar_id;
resource_size_t bar_base;
unsigned long offset;
void __iomem *bar_reg;
size_t len;
};
struct bnxt_qplib_pbl {
u32 pg_count;
u32 pg_size;
void **pg_arr;
dma_addr_t *pg_map_arr;
};
struct bnxt_qplib_sg_info {
struct ib_umem *umem;
u32 npages;
u32 pgshft;
u32 pgsize;
bool nopte;
};
struct bnxt_qplib_hwq_attr {
struct bnxt_qplib_res *res;
struct bnxt_qplib_sg_info *sginfo;
enum bnxt_qplib_hwq_type type;
u32 depth;
u32 stride;
u32 aux_stride;
u32 aux_depth;
};
struct bnxt_qplib_hwq {
struct pci_dev *pdev;
/* lock to protect qplib_hwq */
spinlock_t lock;
struct bnxt_qplib_pbl pbl[PBL_LVL_MAX + 1];
enum bnxt_qplib_pbl_lvl level; /* 0, 1, or 2 */
/* ptr for easy access to the PBL entries */
void **pbl_ptr;
/* ptr for easy access to the dma_addr */
dma_addr_t *pbl_dma_ptr;
u32 max_elements;
u32 depth;
u16 element_size; /* Size of each entry */
u16 qe_ppg; /* queue entry per page */
u32 prod; /* raw */
u32 cons; /* raw */
u8 cp_bit;
u8 is_user;
u8 pg_sz_lvl;
u64 *pad_pg;
u32 pad_stride;
u32 pad_pgofft;
};
struct bnxt_qplib_db_info {
void __iomem *db;
void __iomem *priv_db;
struct bnxt_qplib_hwq *hwq;
u32 xid;
u32 max_slot;
u32 flags;
u8 toggle;
};
enum bnxt_qplib_db_info_flags_mask {
BNXT_QPLIB_FLAG_EPOCH_CONS_SHIFT = 0x0UL,
BNXT_QPLIB_FLAG_EPOCH_PROD_SHIFT = 0x1UL,
BNXT_QPLIB_FLAG_EPOCH_CONS_MASK = 0x1UL,
BNXT_QPLIB_FLAG_EPOCH_PROD_MASK = 0x2UL,
};
enum bnxt_qplib_db_epoch_flag_shift {
BNXT_QPLIB_DB_EPOCH_CONS_SHIFT = BNXT_QPLIB_DBR_EPOCH_SHIFT,
BNXT_QPLIB_DB_EPOCH_PROD_SHIFT = (BNXT_QPLIB_DBR_EPOCH_SHIFT - 1),
};
/* Tables */
struct bnxt_qplib_pd_tbl {
unsigned long *tbl;
u32 max;
};
struct bnxt_qplib_sgid_tbl {
struct bnxt_qplib_gid_info *tbl;
u16 *hw_id;
u16 max;
u16 active;
void *ctx;
u8 *vlan;
};
enum {
BNXT_QPLIB_DPI_TYPE_KERNEL = 0,
BNXT_QPLIB_DPI_TYPE_UC = 1,
BNXT_QPLIB_DPI_TYPE_WC = 2
};
struct bnxt_qplib_dpi {
u32 dpi;
u32 bit;
void __iomem *dbr;
u64 umdbr;
u8 type;
};
struct bnxt_qplib_dpi_tbl {
void **app_tbl;
unsigned long *tbl;
u16 max;
struct bnxt_qplib_reg_desc ucreg; /* Hold entire DB bar. */
struct bnxt_qplib_reg_desc wcreg;
void __iomem *priv_db;
};
struct bnxt_qplib_stats {
dma_addr_t dma_map;
void *dma;
u32 size;
u32 fw_id;
};
struct bnxt_qplib_vf_res {
u32 max_qp_per_vf;
u32 max_mrw_per_vf;
u32 max_srq_per_vf;
u32 max_cq_per_vf;
u32 max_gid_per_vf;
};
#define BNXT_QPLIB_MAX_QP_CTX_ENTRY_SIZE 448
#define BNXT_QPLIB_MAX_SRQ_CTX_ENTRY_SIZE 64
#define BNXT_QPLIB_MAX_CQ_CTX_ENTRY_SIZE 64
#define BNXT_QPLIB_MAX_MRW_CTX_ENTRY_SIZE 128
#define MAX_TQM_ALLOC_REQ 48
#define MAX_TQM_ALLOC_BLK_SIZE 8
struct bnxt_qplib_tqm_ctx {
struct bnxt_qplib_hwq pde;
u8 pde_level; /* Original level */
struct bnxt_qplib_hwq qtbl[MAX_TQM_ALLOC_REQ];
u8 qcount[MAX_TQM_ALLOC_REQ];
};
struct bnxt_qplib_ctx {
u32 qpc_count;
struct bnxt_qplib_hwq qpc_tbl;
u32 mrw_count;
struct bnxt_qplib_hwq mrw_tbl;
u32 srqc_count;
struct bnxt_qplib_hwq srqc_tbl;
u32 cq_count;
struct bnxt_qplib_hwq cq_tbl;
struct bnxt_qplib_hwq tim_tbl;
struct bnxt_qplib_tqm_ctx tqm_ctx;
struct bnxt_qplib_stats stats;
struct bnxt_qplib_stats stats3;
struct bnxt_qplib_vf_res vf_res;
};
struct bnxt_qplib_res {
struct pci_dev *pdev;
struct bnxt_qplib_chip_ctx *cctx;
struct bnxt_qplib_dev_attr *dattr;
struct net_device *netdev;
struct bnxt_en_dev *en_dev;
struct bnxt_qplib_rcfw *rcfw;
struct bnxt_qplib_pd_tbl pd_tbl;
/* To protect the pd table bit map */
struct mutex pd_tbl_lock;
struct bnxt_qplib_sgid_tbl sgid_tbl;
struct bnxt_qplib_dpi_tbl dpi_tbl;
/* To protect the dpi table bit map */
struct mutex dpi_tbl_lock;
bool prio;
bool is_vf;
struct bnxt_qplib_db_pacing_data *pacing_data;
};
static inline bool bnxt_qplib_is_chip_gen_p7(struct bnxt_qplib_chip_ctx *cctx)
{
return (cctx->chip_num == CHIP_NUM_58818 ||
cctx->chip_num == CHIP_NUM_57608);
}
static inline bool bnxt_qplib_is_chip_gen_p5(struct bnxt_qplib_chip_ctx *cctx)
{
return (cctx->chip_num == CHIP_NUM_57508 ||
cctx->chip_num == CHIP_NUM_57504 ||
cctx->chip_num == CHIP_NUM_57502);
}
static inline bool bnxt_qplib_is_chip_gen_p5_p7(struct bnxt_qplib_chip_ctx *cctx)
{
return bnxt_qplib_is_chip_gen_p5(cctx) || bnxt_qplib_is_chip_gen_p7(cctx);
}
static inline u8 bnxt_qplib_get_hwq_type(struct bnxt_qplib_res *res)
{
return bnxt_qplib_is_chip_gen_p5_p7(res->cctx) ?
HWQ_TYPE_QUEUE : HWQ_TYPE_L2_CMPL;
}
static inline u8 bnxt_qplib_get_ring_type(struct bnxt_qplib_chip_ctx *cctx)
{
return bnxt_qplib_is_chip_gen_p5_p7(cctx) ?
RING_ALLOC_REQ_RING_TYPE_NQ :
RING_ALLOC_REQ_RING_TYPE_ROCE_CMPL;
}
static inline u64 bnxt_qplib_get_base_addr(struct bnxt_qplib_hwq *hwq)
{
return hwq->pbl[PBL_LVL_0].pg_map_arr[0];
}
static inline u8 bnxt_qplib_base_pg_size(struct bnxt_qplib_hwq *hwq)
{
u8 pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K;
struct bnxt_qplib_pbl *pbl;
pbl = &hwq->pbl[PBL_LVL_0];
switch (pbl->pg_size) {
case ROCE_PG_SIZE_4K:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K;
break;
case ROCE_PG_SIZE_8K:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8K;
break;
case ROCE_PG_SIZE_64K:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_64K;
break;
case ROCE_PG_SIZE_2M:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_2M;
break;
case ROCE_PG_SIZE_8M:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8M;
break;
case ROCE_PG_SIZE_1G:
pg_size = BNXT_QPLIB_HWRM_PG_SIZE_1G;
break;
default:
break;
}
return pg_size;
}
static inline void *bnxt_qplib_get_qe(struct bnxt_qplib_hwq *hwq,
u32 indx, u64 *pg)
{
u32 pg_num, pg_idx;
pg_num = (indx / hwq->qe_ppg);
pg_idx = (indx % hwq->qe_ppg);
if (pg)
*pg = (u64)&hwq->pbl_ptr[pg_num];
return (void *)(hwq->pbl_ptr[pg_num] + hwq->element_size * pg_idx);
}
static inline void *bnxt_qplib_get_prod_qe(struct bnxt_qplib_hwq *hwq, u32 idx)
{
idx += hwq->prod;
if (idx >= hwq->depth)
idx -= hwq->depth;
return bnxt_qplib_get_qe(hwq, idx, NULL);
}
#define to_bnxt_qplib(ptr, type, member) \
container_of(ptr, type, member)
struct bnxt_qplib_pd;
struct bnxt_qplib_dev_attr;
void bnxt_qplib_free_hwq(struct bnxt_qplib_res *res,
struct bnxt_qplib_hwq *hwq);
int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
struct bnxt_qplib_hwq_attr *hwq_attr);
int bnxt_qplib_alloc_pd(struct bnxt_qplib_res *res,
struct bnxt_qplib_pd *pd);
int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res,
struct bnxt_qplib_pd_tbl *pd_tbl,
struct bnxt_qplib_pd *pd);
int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
struct bnxt_qplib_dpi *dpi,
void *app, u8 type);
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
struct bnxt_qplib_dpi *dpi);
int bnxt_qplib_alloc_uc_dpi(struct bnxt_qplib_res *res,
struct bnxt_qplib_dpi *dpi);
int bnxt_qplib_free_uc_dpi(struct bnxt_qplib_res *res,
struct bnxt_qplib_dpi *dpi);
void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res);
int bnxt_qplib_init_res(struct bnxt_qplib_res *res);
void bnxt_qplib_free_res(struct bnxt_qplib_res *res);
int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct net_device *netdev);
void bnxt_qplib_free_hwctx(struct bnxt_qplib_res *res,
struct bnxt_qplib_ctx *ctx);
int bnxt_qplib_alloc_hwctx(struct bnxt_qplib_res *res,
struct bnxt_qplib_ctx *ctx);
int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res);
void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res);
int bnxt_qplib_determine_atomics(struct pci_dev *dev);
int bnxt_qplib_alloc_stats_ctx(struct pci_dev *pdev,
struct bnxt_qplib_chip_ctx *cctx,
struct bnxt_qplib_stats *stats);
void bnxt_qplib_free_stats_ctx(struct pci_dev *pdev,
struct bnxt_qplib_stats *stats);
static inline void bnxt_qplib_hwq_incr_prod(struct bnxt_qplib_db_info *dbinfo,
struct bnxt_qplib_hwq *hwq, u32 cnt)
{
/* move prod and update toggle/epoch if wrap around */
hwq->prod += cnt;
if (hwq->prod >= hwq->depth) {
hwq->prod %= hwq->depth;
dbinfo->flags ^= 1UL << BNXT_QPLIB_FLAG_EPOCH_PROD_SHIFT;
}
}
static inline void bnxt_qplib_hwq_incr_cons(u32 max_elements, u32 *cons, u32 cnt,
u32 *dbinfo_flags)
{
/* move cons and update toggle/epoch if wrap around */
*cons += cnt;
if (*cons >= max_elements) {
*cons %= max_elements;
*dbinfo_flags ^= 1UL << BNXT_QPLIB_FLAG_EPOCH_CONS_SHIFT;
}
}
static inline void bnxt_qplib_ring_db32(struct bnxt_qplib_db_info *info,
bool arm)
{
u32 key = 0;
key |= info->hwq->cons | (CMPL_DOORBELL_IDX_VALID |
(CMPL_DOORBELL_KEY_CMPL & CMPL_DOORBELL_KEY_MASK));
if (!arm)
key |= CMPL_DOORBELL_MASK;
writel(key, info->db);
}
#define BNXT_QPLIB_INIT_DBHDR(xid, type, indx, toggle) \
(((u64)(((xid) & DBC_DBC_XID_MASK) | DBC_DBC_PATH_ROCE | \
(type) | BNXT_QPLIB_DBR_VALID) << 32) | (indx) | \
(((u32)(toggle)) << (BNXT_QPLIB_DBR_TOGGLE_SHIFT)))
static inline void bnxt_qplib_ring_db(struct bnxt_qplib_db_info *info,
u32 type)
{
u64 key = 0;
u32 indx;
u8 toggle = 0;
if (type == DBC_DBC_TYPE_CQ_ARMALL ||
type == DBC_DBC_TYPE_CQ_ARMSE)
toggle = info->toggle;
indx = (info->hwq->cons & DBC_DBC_INDEX_MASK) |
((info->flags & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK) <<
BNXT_QPLIB_DB_EPOCH_CONS_SHIFT);
key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, indx, toggle);
writeq(key, info->db);
}
static inline void bnxt_qplib_ring_prod_db(struct bnxt_qplib_db_info *info,
u32 type)
{
u64 key = 0;
u32 indx;
indx = (((info->hwq->prod / info->max_slot) & DBC_DBC_INDEX_MASK) |
((info->flags & BNXT_QPLIB_FLAG_EPOCH_PROD_MASK) <<
BNXT_QPLIB_DB_EPOCH_PROD_SHIFT));
key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, indx, 0);
writeq(key, info->db);
}
static inline void bnxt_qplib_armen_db(struct bnxt_qplib_db_info *info,
u32 type)
{
u64 key = 0;
u8 toggle = 0;
if (type == DBC_DBC_TYPE_CQ_ARMENA || type == DBC_DBC_TYPE_SRQ_ARMENA)
toggle = info->toggle;
/* Index always at 0 */
key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, 0, toggle);
writeq(key, info->priv_db);
}
static inline void bnxt_qplib_srq_arm_db(struct bnxt_qplib_db_info *info,
u32 th)
{
u64 key = 0;
key = BNXT_QPLIB_INIT_DBHDR(info->xid, DBC_DBC_TYPE_SRQ_ARM, th, info->toggle);
writeq(key, info->priv_db);
}
static inline void bnxt_qplib_ring_nq_db(struct bnxt_qplib_db_info *info,
struct bnxt_qplib_chip_ctx *cctx,
bool arm)
{
u32 type;
type = arm ? DBC_DBC_TYPE_NQ_ARM : DBC_DBC_TYPE_NQ;
if (bnxt_qplib_is_chip_gen_p5_p7(cctx))
bnxt_qplib_ring_db(info, type);
else
bnxt_qplib_ring_db32(info, arm);
}
static inline bool _is_ext_stats_supported(u16 dev_cap_flags)
{
return dev_cap_flags &
CREQ_QUERY_FUNC_RESP_SB_EXT_STATS;
}
static inline int bnxt_ext_stats_supported(struct bnxt_qplib_chip_ctx *ctx,
u16 flags, bool virtfn)
{
/* ext stats supported if cap flag is set AND is a PF OR a Thor2 VF */
return (_is_ext_stats_supported(flags) &&
((virtfn && bnxt_qplib_is_chip_gen_p7(ctx)) || (!virtfn)));
}
static inline bool _is_hw_retx_supported(u16 dev_cap_flags)
{
return dev_cap_flags &
(CREQ_QUERY_FUNC_RESP_SB_HW_REQUESTER_RETX_ENABLED |
CREQ_QUERY_FUNC_RESP_SB_HW_RESPONDER_RETX_ENABLED);
}
#define BNXT_RE_HW_RETX(a) _is_hw_retx_supported((a))
static inline bool _is_host_msn_table(u16 dev_cap_ext_flags2)
{
return (dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK) ==
CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE;
}
static inline u8 bnxt_qplib_dbr_pacing_en(struct bnxt_qplib_chip_ctx *cctx)
{
return cctx->modes.dbr_pacing;
}
static inline u8 bnxt_qplib_roce_mirror_supported(struct bnxt_qplib_chip_ctx *cctx)
{
return cctx->modes.roce_mirror;
}
static inline bool _is_alloc_mr_unified(u16 dev_cap_flags)
{
return dev_cap_flags & CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC;
}
static inline bool _is_relaxed_ordering_supported(u16 dev_cap_ext_flags2)
{
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED;
}
static inline bool _is_optimize_modify_qp_supported(u16 dev_cap_ext_flags2)
{
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED;
}
static inline bool _is_min_rnr_in_rtr_rts_mandatory(u16 dev_cap_ext_flags2)
{
return !!(dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MIN_RNR_RTR_RTS_OPT_SUPPORTED);
}
static inline bool _is_cq_coalescing_supported(u16 dev_cap_ext_flags2)
{
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED;
}
static inline bool _is_max_srq_ext_supported(u16 dev_cap_ext_flags_2)
{
return !!(dev_cap_ext_flags_2 & CREQ_QUERY_FUNC_RESP_SB_MAX_SRQ_EXTENDED);
}
static inline bool _is_modify_qp_rate_limit_supported(u16 dev_cap_ext_flags2)
{
return dev_cap_ext_flags2 &
CREQ_QUERY_FUNC_RESP_SB_MODIFY_QP_RATE_LIMIT_SUPPORTED;
}
#endif /* __BNXT_QPLIB_RES_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,376 @@
/*
* Broadcom NetXtreme-E RoCE driver.
*
* Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Slow Path Operators (header)
*
*/
#ifndef __BNXT_QPLIB_SP_H__
#define __BNXT_QPLIB_SP_H__
#include <rdma/bnxt_re-abi.h>
#define BNXT_QPLIB_RESERVED_QP_WRS 128
struct bnxt_qplib_dev_attr {
#define FW_VER_ARR_LEN 4
u8 fw_ver[FW_VER_ARR_LEN];
#define BNXT_QPLIB_NUM_GIDS_SUPPORTED 256
u16 max_sgid;
u16 max_mrw;
u32 max_qp;
#define BNXT_QPLIB_MAX_OUT_RD_ATOM 126
u32 max_qp_rd_atom;
u32 max_qp_init_rd_atom;
u32 max_qp_wqes;
u32 max_qp_sges;
u32 max_cq;
#define BNXT_QPLIB_MAX_CQ_WQES 0xfffff
u32 max_cq_wqes;
u32 max_cq_sges;
u32 max_mr;
u64 max_mr_size;
u32 max_pd;
u32 max_mw;
u32 max_raw_ethy_qp;
u32 max_ah;
u32 max_srq;
u32 max_srq_wqes;
u32 max_srq_sges;
u32 max_pkey;
u32 max_inline_data;
u32 l2_db_size;
u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ];
bool is_atomic;
u16 dev_cap_flags;
u16 dev_cap_flags2;
u32 max_dpi;
u16 rate_limit_min;
u32 rate_limit_max;
};
struct bnxt_qplib_pd {
u32 id;
};
struct bnxt_qplib_gid {
u8 data[16];
};
struct bnxt_qplib_gid_info {
struct bnxt_qplib_gid gid;
u16 vlan_id;
};
struct bnxt_qplib_ah {
struct bnxt_qplib_gid dgid;
struct bnxt_qplib_pd *pd;
u32 id;
u8 sgid_index;
/* For Query AH if the hw table and SW table are differnt */
u8 host_sgid_index;
u8 traffic_class;
u32 flow_label;
u8 hop_limit;
u8 sl;
u8 dmac[6];
u16 vlan_id;
u8 nw_type;
};
struct bnxt_qplib_mrw {
struct bnxt_qplib_pd *pd;
int type;
u32 access_flags;
#define BNXT_QPLIB_MR_ACCESS_MASK 0xFF
#define BNXT_QPLIB_FR_PMR 0x80000000
u32 lkey;
u32 rkey;
#define BNXT_QPLIB_RSVD_LKEY 0xFFFFFFFF
u64 va;
u64 total_size;
u32 npages;
u16 flags;
u64 mr_handle;
struct bnxt_qplib_hwq hwq;
};
struct bnxt_qplib_frpl {
int max_pg_ptrs;
struct bnxt_qplib_hwq hwq;
};
#define BNXT_QPLIB_ACCESS_LOCAL_WRITE BIT(0)
#define BNXT_QPLIB_ACCESS_REMOTE_READ BIT(1)
#define BNXT_QPLIB_ACCESS_REMOTE_WRITE BIT(2)
#define BNXT_QPLIB_ACCESS_REMOTE_ATOMIC BIT(3)
#define BNXT_QPLIB_ACCESS_MW_BIND BIT(4)
#define BNXT_QPLIB_ACCESS_ZERO_BASED BIT(5)
#define BNXT_QPLIB_ACCESS_ON_DEMAND BIT(6)
struct bnxt_qplib_roce_stats {
u64 to_retransmits;
u64 seq_err_naks_rcvd;
/* seq_err_naks_rcvd is 64 b */
u64 max_retry_exceeded;
/* max_retry_exceeded is 64 b */
u64 rnr_naks_rcvd;
/* rnr_naks_rcvd is 64 b */
u64 missing_resp;
u64 unrecoverable_err;
/* unrecoverable_err is 64 b */
u64 bad_resp_err;
/* bad_resp_err is 64 b */
u64 local_qp_op_err;
/* local_qp_op_err is 64 b */
u64 local_protection_err;
/* local_protection_err is 64 b */
u64 mem_mgmt_op_err;
/* mem_mgmt_op_err is 64 b */
u64 remote_invalid_req_err;
/* remote_invalid_req_err is 64 b */
u64 remote_access_err;
/* remote_access_err is 64 b */
u64 remote_op_err;
/* remote_op_err is 64 b */
u64 dup_req;
/* dup_req is 64 b */
u64 res_exceed_max;
/* res_exceed_max is 64 b */
u64 res_length_mismatch;
/* res_length_mismatch is 64 b */
u64 res_exceeds_wqe;
/* res_exceeds_wqe is 64 b */
u64 res_opcode_err;
/* res_opcode_err is 64 b */
u64 res_rx_invalid_rkey;
/* res_rx_invalid_rkey is 64 b */
u64 res_rx_domain_err;
/* res_rx_domain_err is 64 b */
u64 res_rx_no_perm;
/* res_rx_no_perm is 64 b */
u64 res_rx_range_err;
/* res_rx_range_err is 64 b */
u64 res_tx_invalid_rkey;
/* res_tx_invalid_rkey is 64 b */
u64 res_tx_domain_err;
/* res_tx_domain_err is 64 b */
u64 res_tx_no_perm;
/* res_tx_no_perm is 64 b */
u64 res_tx_range_err;
/* res_tx_range_err is 64 b */
u64 res_irrq_oflow;
/* res_irrq_oflow is 64 b */
u64 res_unsup_opcode;
/* res_unsup_opcode is 64 b */
u64 res_unaligned_atomic;
/* res_unaligned_atomic is 64 b */
u64 res_rem_inv_err;
/* res_rem_inv_err is 64 b */
u64 res_mem_error;
/* res_mem_error is 64 b */
u64 res_srq_err;
/* res_srq_err is 64 b */
u64 res_cmp_err;
/* res_cmp_err is 64 b */
u64 res_invalid_dup_rkey;
/* res_invalid_dup_rkey is 64 b */
u64 res_wqe_format_err;
/* res_wqe_format_err is 64 b */
u64 res_cq_load_err;
/* res_cq_load_err is 64 b */
u64 res_srq_load_err;
/* res_srq_load_err is 64 b */
u64 res_tx_pci_err;
/* res_tx_pci_err is 64 b */
u64 res_rx_pci_err;
/* res_rx_pci_err is 64 b */
u64 res_oos_drop_count;
/* res_oos_drop_count */
u64 active_qp_count_p0;
/* port 0 active qps */
u64 active_qp_count_p1;
/* port 1 active qps */
u64 active_qp_count_p2;
/* port 2 active qps */
u64 active_qp_count_p3;
/* port 3 active qps */
};
struct bnxt_qplib_ext_stat {
u64 tx_atomic_req;
u64 tx_read_req;
u64 tx_read_res;
u64 tx_write_req;
u64 tx_send_req;
u64 tx_roce_pkts;
u64 tx_roce_bytes;
u64 rx_atomic_req;
u64 rx_read_req;
u64 rx_read_res;
u64 rx_write_req;
u64 rx_send_req;
u64 rx_roce_pkts;
u64 rx_roce_bytes;
u64 rx_roce_good_pkts;
u64 rx_roce_good_bytes;
u64 rx_out_of_buffer;
u64 rx_out_of_sequence;
u64 tx_cnp;
u64 rx_cnp;
u64 rx_ecn_marked;
};
struct bnxt_qplib_cc_param_ext {
u64 ext_mask;
u16 inact_th_hi;
u16 min_delta_cnp;
u16 init_cp;
u8 tr_update_mode;
u8 tr_update_cyls;
u8 fr_rtt;
u8 ai_rate_incr;
u16 rr_rtt_th;
u16 ar_cr_th;
u16 cr_min_th;
u8 bw_avg_weight;
u8 cr_factor;
u16 cr_th_max_cp;
u8 cp_bias_en;
u8 cp_bias;
u8 cnp_ecn;
u8 rtt_jitter_en;
u16 bytes_per_usec;
u16 cc_cr_reset_th;
u8 cr_width;
u8 min_quota;
u8 max_quota;
u8 abs_max_quota;
u16 tr_lb;
u8 cr_prob_fac;
u8 tr_prob_fac;
u16 fair_cr_th;
u8 red_div;
u8 cnp_ratio_th;
u16 ai_ext_rtt;
u8 exp_crcp_ratio;
u8 low_rate_en;
u16 cpcr_update_th;
u16 ai_rtt_th1;
u16 ai_rtt_th2;
u16 cf_rtt_th;
u16 sc_cr_th1; /* severe congestion cr threshold 1 */
u16 sc_cr_th2; /* severe congestion cr threshold 2 */
u32 l64B_per_rtt;
u8 cc_ack_bytes;
u16 reduce_cf_rtt_th;
};
struct bnxt_qplib_cc_param {
u8 alt_vlan_pcp;
u8 qp1_tos_dscp;
u16 alt_tos_dscp;
u8 cc_mode;
u8 enable;
u16 inact_th;
u16 init_cr;
u16 init_tr;
u16 rtt;
u8 g;
u8 nph_per_state;
u8 time_pph;
u8 pkts_pph;
u8 tos_ecn;
u8 tos_dscp;
u16 tcp_cp;
struct bnxt_qplib_cc_param_ext cc_ext;
u32 mask;
};
int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
struct bnxt_qplib_gid *gid);
int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, u16 vlan_id, bool update);
int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, const u8 *mac, u16 vlan_id,
bool update, u32 *index,
bool is_ugid, u32 stats_ctx_id);
int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, u16 gid_idx,
const u8 *smac);
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx);
int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
bool block);
int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
bool block);
int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res,
struct bnxt_qplib_mrw *mrw);
int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
bool block);
int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
struct ib_umem *umem, int num_pbls, u32 buf_pg_size, bool unified_mr);
int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr);
int bnxt_qplib_alloc_fast_reg_mr(struct bnxt_qplib_res *res,
struct bnxt_qplib_mrw *mr, int max);
int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res,
struct bnxt_qplib_frpl *frpl, int max);
int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res,
struct bnxt_qplib_frpl *frpl);
int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_roce_stats *stats);
int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
struct bnxt_qplib_ext_stat *estat);
int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res,
struct bnxt_qplib_cc_param *cc_param);
int bnxt_qplib_read_context(struct bnxt_qplib_rcfw *rcfw, u8 type, u32 xid,
u32 resp_size, void *resp_va);
int bnxt_qplib_query_cc_param(struct bnxt_qplib_res *res,
struct bnxt_qplib_cc_param *cc_param);
void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_create_flow(struct bnxt_qplib_res *res);
int bnxt_qplib_destroy_flow(struct bnxt_qplib_res *res);
#define BNXT_VAR_MAX_WQE 4352
#define BNXT_VAR_MAX_SLOT_ALIGN 256
#define BNXT_VAR_MAX_SGE 13
#define BNXT_RE_MAX_RQ_WQES 65536
#define BNXT_RE_MAX_SQ_SLOTS 65536
#define BNXT_STATIC_MAX_SGE 6
#endif /* __BNXT_QPLIB_SP_H__*/
@@ -0,0 +1,162 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
#ifndef __QPLIB_TLV_H__
#define __QPLIB_TLV_H__
struct roce_tlv {
struct tlv tlv;
u8 total_size; // in units of 16 byte chunks
u8 unused[7]; // for 16 byte alignment
};
#define CHUNK_SIZE 16
#define CHUNKS(x) (((x) + CHUNK_SIZE - 1) / CHUNK_SIZE)
static inline void __roce_1st_tlv_prep(struct roce_tlv *rtlv, u8 tot_chunks,
u16 content_bytes, u8 flags)
{
rtlv->tlv.cmd_discr = cpu_to_le16(CMD_DISCR_TLV_ENCAP);
rtlv->tlv.tlv_type = cpu_to_le16(TLV_TYPE_ROCE_SP_COMMAND);
rtlv->tlv.length = cpu_to_le16(content_bytes);
rtlv->tlv.flags = TLV_FLAGS_REQUIRED;
rtlv->tlv.flags |= flags ? TLV_FLAGS_MORE : 0;
rtlv->total_size = (tot_chunks);
}
static inline void __roce_ext_tlv_prep(struct roce_tlv *rtlv, u16 tlv_type,
u16 content_bytes, u8 more, u8 flags)
{
rtlv->tlv.cmd_discr = cpu_to_le16(CMD_DISCR_TLV_ENCAP);
rtlv->tlv.tlv_type = cpu_to_le16(tlv_type);
rtlv->tlv.length = cpu_to_le16(content_bytes);
rtlv->tlv.flags |= more ? TLV_FLAGS_MORE : 0;
rtlv->tlv.flags |= flags ? TLV_FLAGS_REQUIRED : 0;
}
/*
* TLV size in units of 16 byte chunks
*/
#define TLV_SIZE ((sizeof(struct roce_tlv) + 15) / 16)
/*
* TLV length in bytes
*/
#define TLV_BYTES (TLV_SIZE * 16)
#define HAS_TLV_HEADER(msg) (le16_to_cpu(((struct tlv *)(msg))->cmd_discr) == CMD_DISCR_TLV_ENCAP)
#define GET_TLV_DATA(tlv) ((void *)&((uint8_t *)(tlv))[TLV_BYTES])
static inline u8 __get_cmdq_base_opcode(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct cmdq_base *)GET_TLV_DATA(req))->opcode;
else
return req->opcode;
}
static inline void __set_cmdq_base_opcode(struct cmdq_base *req,
u32 size, u8 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->opcode = val;
else
req->opcode = val;
}
static inline __le16 __get_cmdq_base_cookie(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct cmdq_base *)GET_TLV_DATA(req))->cookie;
else
return req->cookie;
}
static inline void __set_cmdq_base_cookie(struct cmdq_base *req,
u32 size, __le16 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->cookie = val;
else
req->cookie = val;
}
static inline __le64 __get_cmdq_base_resp_addr(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct cmdq_base *)GET_TLV_DATA(req))->resp_addr;
else
return req->resp_addr;
}
static inline void __set_cmdq_base_resp_addr(struct cmdq_base *req,
u32 size, __le64 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->resp_addr = val;
else
req->resp_addr = val;
}
static inline u8 __get_cmdq_base_resp_size(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct cmdq_base *)GET_TLV_DATA(req))->resp_size;
else
return req->resp_size;
}
static inline void __set_cmdq_base_resp_size(struct cmdq_base *req,
u32 size, u8 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->resp_size = val;
else
req->resp_size = val;
}
static inline u8 __get_cmdq_base_cmd_size(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct roce_tlv *)(req))->total_size;
else
return req->cmd_size;
}
static inline void __set_cmdq_base_cmd_size(struct cmdq_base *req,
u32 size, u8 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->cmd_size = val;
else
req->cmd_size = val;
}
static inline __le16 __get_cmdq_base_flags(struct cmdq_base *req, u32 size)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
return ((struct cmdq_base *)GET_TLV_DATA(req))->flags;
else
return req->flags;
}
static inline void __set_cmdq_base_flags(struct cmdq_base *req,
u32 size, __le16 val)
{
if (HAS_TLV_HEADER(req) && size > TLV_BYTES)
((struct cmdq_base *)GET_TLV_DATA(req))->flags = val;
else
req->flags = val;
}
struct bnxt_qplib_tlv_modify_cc_req {
struct roce_tlv tlv_hdr;
struct cmdq_modify_roce_cc base_req;
__le64 tlvpad;
struct cmdq_modify_roce_cc_gen1_tlv ext_req;
};
struct bnxt_qplib_tlv_query_rcc_sb {
struct roce_tlv tlv_hdr;
struct creq_query_roce_cc_resp_sb base_sb;
struct creq_query_roce_cc_gen1_resp_sb_tlv gen1_sb;
};
#endif /* __QPLIB_TLV_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,541 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* Copyright (c) 2025, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* Description: uapi interpreter
*/
#include <rdma/ib_addr.h>
#include <rdma/uverbs_types.h>
#include <rdma/uverbs_std_types.h>
#include <rdma/ib_user_ioctl_cmds.h>
#define UVERBS_MODULE_NAME bnxt_re
#include <rdma/uverbs_named_ioctl.h>
#include <rdma/bnxt_re-abi.h>
#include "roce_hsi.h"
#include "qplib_res.h"
#include "qplib_sp.h"
#include "qplib_fp.h"
#include "qplib_rcfw.h"
#include "bnxt_re.h"
#include "ib_verbs.h"
static struct bnxt_re_cq *bnxt_re_search_for_cq(struct bnxt_re_dev *rdev, u32 cq_id)
{
struct bnxt_re_cq *cq = NULL, *tmp_cq;
hash_for_each_possible(rdev->cq_hash, tmp_cq, hash_entry, cq_id) {
if (tmp_cq->qplib_cq.id == cq_id) {
cq = tmp_cq;
break;
}
}
return cq;
}
static struct bnxt_re_srq *bnxt_re_search_for_srq(struct bnxt_re_dev *rdev, u32 srq_id)
{
struct bnxt_re_srq *srq = NULL, *tmp_srq;
hash_for_each_possible(rdev->srq_hash, tmp_srq, hash_entry, srq_id) {
if (tmp_srq->qplib_srq.id == srq_id) {
srq = tmp_srq;
break;
}
}
return srq;
}
static int UVERBS_HANDLER(BNXT_RE_METHOD_NOTIFY_DRV)(struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_ucontext *uctx;
struct ib_ucontext *ib_uctx;
ib_uctx = ib_uverbs_get_ucontext(attrs);
if (IS_ERR(ib_uctx))
return PTR_ERR(ib_uctx);
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
if (IS_ERR(uctx))
return PTR_ERR(uctx);
bnxt_re_pacing_alert(uctx->rdev);
return 0;
}
static int UVERBS_HANDLER(BNXT_RE_METHOD_ALLOC_PAGE)(struct uverbs_attr_bundle *attrs)
{
struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
enum bnxt_re_alloc_page_type alloc_type;
struct bnxt_re_user_mmap_entry *entry;
enum bnxt_re_mmap_flag mmap_flag;
struct bnxt_qplib_chip_ctx *cctx;
struct bnxt_re_ucontext *uctx;
struct ib_ucontext *ib_uctx;
struct bnxt_re_dev *rdev;
u64 mmap_offset;
u32 dpi = 0;
u32 length;
u64 addr;
int err;
ib_uctx = ib_uverbs_get_ucontext(attrs);
if (IS_ERR(ib_uctx))
return PTR_ERR(ib_uctx);
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
if (IS_ERR(uctx))
return PTR_ERR(uctx);
err = uverbs_get_const(&alloc_type, attrs, BNXT_RE_ALLOC_PAGE_TYPE);
if (err)
return err;
rdev = uctx->rdev;
cctx = rdev->chip_ctx;
switch (alloc_type) {
case BNXT_RE_ALLOC_WC_PAGE:
if (cctx->modes.db_push) {
mutex_lock(&uctx->wcdpi_lock);
/* already allocated — one WC page per context */
if (uctx->wcdpi.dbr) {
mutex_unlock(&uctx->wcdpi_lock);
return -EEXIST;
}
if (bnxt_qplib_alloc_dpi(&rdev->qplib_res, &uctx->wcdpi,
uctx, BNXT_QPLIB_DPI_TYPE_WC)) {
mutex_unlock(&uctx->wcdpi_lock);
return -ENOMEM;
}
length = PAGE_SIZE;
dpi = uctx->wcdpi.dpi;
addr = (u64)uctx->wcdpi.umdbr;
mmap_flag = BNXT_RE_MMAP_WC_DB;
mutex_unlock(&uctx->wcdpi_lock);
} else {
return -EINVAL;
}
break;
case BNXT_RE_ALLOC_DBR_BAR_PAGE:
if (!rdev->pacing.dbr_pacing)
return -EOPNOTSUPP;
length = PAGE_SIZE;
addr = (u64)rdev->pacing.dbr_bar_addr;
mmap_flag = BNXT_RE_MMAP_DBR_BAR;
break;
case BNXT_RE_ALLOC_DBR_PAGE:
if (!rdev->pacing.dbr_pacing)
return -EOPNOTSUPP;
length = PAGE_SIZE;
addr = (u64)rdev->pacing.dbr_page;
mmap_flag = BNXT_RE_MMAP_DBR_PAGE;
break;
default:
return -EOPNOTSUPP;
}
entry = bnxt_re_mmap_entry_insert(uctx, addr, mmap_flag, &mmap_offset);
if (!entry) {
if (mmap_flag == BNXT_RE_MMAP_WC_DB) {
mutex_lock(&uctx->wcdpi_lock);
bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->wcdpi);
uctx->wcdpi.dbr = NULL;
mutex_unlock(&uctx->wcdpi_lock);
}
return -ENOMEM;
}
uobj->object = entry;
uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
&mmap_offset, sizeof(mmap_offset));
if (err)
return err;
err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
&length, sizeof(length));
if (err)
return err;
err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_DPI,
&dpi, sizeof(dpi));
if (err)
return err;
return 0;
}
static int alloc_page_obj_cleanup(struct ib_uobject *uobject,
enum rdma_remove_reason why,
struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_user_mmap_entry *entry = uobject->object;
struct bnxt_re_ucontext *uctx = entry->uctx;
switch (entry->mmap_flag) {
case BNXT_RE_MMAP_WC_DB:
if (uctx) {
struct bnxt_re_dev *rdev = uctx->rdev;
mutex_lock(&uctx->wcdpi_lock);
if (uctx->wcdpi.dbr) {
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
&uctx->wcdpi);
uctx->wcdpi.dbr = NULL;
}
mutex_unlock(&uctx->wcdpi_lock);
}
break;
case BNXT_RE_MMAP_DBR_BAR:
case BNXT_RE_MMAP_DBR_PAGE:
break;
default:
goto exit;
}
rdma_user_mmap_entry_remove(&entry->rdma_entry);
exit:
return 0;
}
DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_ALLOC_PAGE,
UVERBS_ATTR_IDR(BNXT_RE_ALLOC_PAGE_HANDLE,
BNXT_RE_OBJECT_ALLOC_PAGE,
UVERBS_ACCESS_NEW,
UA_MANDATORY),
UVERBS_ATTR_CONST_IN(BNXT_RE_ALLOC_PAGE_TYPE,
enum bnxt_re_alloc_page_type,
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
UVERBS_ATTR_TYPE(u64),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_DPI,
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY));
DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DESTROY_PAGE,
UVERBS_ATTR_IDR(BNXT_RE_DESTROY_PAGE_HANDLE,
BNXT_RE_OBJECT_ALLOC_PAGE,
UVERBS_ACCESS_DESTROY,
UA_MANDATORY));
DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_ALLOC_PAGE,
UVERBS_TYPE_ALLOC_IDR(alloc_page_obj_cleanup),
&UVERBS_METHOD(BNXT_RE_METHOD_ALLOC_PAGE),
&UVERBS_METHOD(BNXT_RE_METHOD_DESTROY_PAGE));
DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_NOTIFY_DRV);
DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_NOTIFY_DRV,
&UVERBS_METHOD(BNXT_RE_METHOD_NOTIFY_DRV));
/* Toggle MEM */
static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bundle *attrs)
{
struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_TOGGLE_MEM_HANDLE);
enum bnxt_re_mmap_flag mmap_flag = BNXT_RE_MMAP_TOGGLE_PAGE;
enum bnxt_re_get_toggle_mem_type res_type;
struct bnxt_re_user_mmap_entry *entry;
struct bnxt_re_ucontext *uctx;
struct ib_ucontext *ib_uctx;
struct bnxt_re_dev *rdev;
struct bnxt_re_srq *srq;
u32 length = PAGE_SIZE;
struct bnxt_re_cq *cq;
u64 mem_offset;
u32 offset = 0;
u64 addr = 0;
u32 res_id;
int err;
ib_uctx = ib_uverbs_get_ucontext(attrs);
if (IS_ERR(ib_uctx))
return PTR_ERR(ib_uctx);
err = uverbs_get_const(&res_type, attrs, BNXT_RE_TOGGLE_MEM_TYPE);
if (err)
return err;
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
rdev = uctx->rdev;
err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
if (err)
return err;
switch (res_type) {
case BNXT_RE_CQ_TOGGLE_MEM:
cq = bnxt_re_search_for_cq(rdev, res_id);
if (!cq)
return -EINVAL;
addr = (u64)cq->uctx_cq_page;
if (!addr)
return -EOPNOTSUPP;
break;
case BNXT_RE_SRQ_TOGGLE_MEM:
srq = bnxt_re_search_for_srq(rdev, res_id);
if (!srq)
return -EINVAL;
addr = (u64)srq->uctx_srq_page;
if (!addr)
return -EOPNOTSUPP;
break;
default:
return -EOPNOTSUPP;
}
entry = bnxt_re_mmap_entry_insert(uctx, addr, mmap_flag, &mem_offset);
if (!entry)
return -ENOMEM;
uobj->object = entry;
uverbs_finalize_uobj_create(attrs, BNXT_RE_TOGGLE_MEM_HANDLE);
err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
&mem_offset, sizeof(mem_offset));
if (err)
return err;
err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
&length, sizeof(length));
if (err)
return err;
err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
&offset, sizeof(offset));
if (err)
return err;
return 0;
}
static int get_toggle_mem_obj_cleanup(struct ib_uobject *uobject,
enum rdma_remove_reason why,
struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_user_mmap_entry *entry = uobject->object;
rdma_user_mmap_entry_remove(&entry->rdma_entry);
return 0;
}
DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM,
UVERBS_ATTR_IDR(BNXT_RE_TOGGLE_MEM_HANDLE,
BNXT_RE_OBJECT_GET_TOGGLE_MEM,
UVERBS_ACCESS_NEW,
UA_MANDATORY),
UVERBS_ATTR_CONST_IN(BNXT_RE_TOGGLE_MEM_TYPE,
enum bnxt_re_get_toggle_mem_type,
UA_MANDATORY),
UVERBS_ATTR_PTR_IN(BNXT_RE_TOGGLE_MEM_RES_ID,
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_PAGE,
UVERBS_ATTR_TYPE(u64),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_TOGGLE_MEM_MMAP_LENGTH,
UVERBS_ATTR_TYPE(u32),
UA_MANDATORY));
DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM,
UVERBS_ATTR_IDR(BNXT_RE_RELEASE_TOGGLE_MEM_HANDLE,
BNXT_RE_OBJECT_GET_TOGGLE_MEM,
UVERBS_ACCESS_DESTROY,
UA_MANDATORY));
DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_GET_TOGGLE_MEM,
UVERBS_TYPE_ALLOC_IDR(get_toggle_mem_obj_cleanup),
&UVERBS_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM),
&UVERBS_METHOD(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM));
static int UVERBS_HANDLER(BNXT_RE_METHOD_DBR_ALLOC)(struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_db_region dbr = {};
struct bnxt_re_ucontext *uctx;
struct bnxt_re_dbr_obj *obj;
struct ib_ucontext *ib_uctx;
struct bnxt_qplib_dpi *dpi;
struct bnxt_re_dev *rdev;
struct ib_uobject *uobj;
u64 mmap_offset;
int ret;
ib_uctx = ib_uverbs_get_ucontext(attrs);
if (IS_ERR(ib_uctx))
return PTR_ERR(ib_uctx);
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
rdev = uctx->rdev;
uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_DBR_HANDLE);
obj = kzalloc_obj(*obj);
if (!obj)
return -ENOMEM;
dpi = &obj->dpi;
ret = bnxt_qplib_alloc_uc_dpi(&rdev->qplib_res, dpi);
if (ret)
goto free_mem;
obj->entry = bnxt_re_mmap_entry_insert(uctx, dpi->umdbr,
BNXT_RE_MMAP_UC_DB,
&mmap_offset);
if (!obj->entry) {
ret = -ENOMEM;
goto free_dpi;
}
/* Save DPI info to the mmap entry so that bnxt_re_mmap_free()
* can free the DPI slot only after the last reference to the
* mmap entry is released.
*/
obj->entry->dpi = *dpi;
obj->entry->dpi_valid = true;
obj->rdev = rdev;
kref_init(&obj->usecnt);
uobj->object = obj;
uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_DBR_HANDLE);
dbr.umdbr = dpi->umdbr;
dbr.dpi = dpi->dpi;
ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_ALLOC_DBR_ATTR,
&dbr, sizeof(dbr));
if (ret)
return ret;
ret = uverbs_copy_to(attrs, BNXT_RE_ALLOC_DBR_OFFSET,
&mmap_offset, sizeof(mmap_offset));
if (ret)
return ret;
return 0;
free_dpi:
bnxt_qplib_free_uc_dpi(&rdev->qplib_res, dpi);
free_mem:
kfree(obj);
return ret;
}
void bnxt_re_dbr_kref_release(struct kref *ref)
{
struct bnxt_re_dbr_obj *obj =
container_of(ref, struct bnxt_re_dbr_obj, usecnt);
/* Drop the driver's reference to the mmap entry (_remove()).
* The DPI slot gets freed from bnxt_re_mmap_free() only
* when there's no VMA mapping reference to it.
*/
rdma_user_mmap_entry_remove(&obj->entry->rdma_entry);
kfree(obj);
}
static int bnxt_re_dbr_cleanup(struct ib_uobject *uobject,
enum rdma_remove_reason why,
struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_dbr_obj *obj = uobject->object;
/* If it is being destroyed explicitly while QPs still hold a
* reference (> 1), reject it with EBUSY. If no QP references
* or implicit teardown (process exit, driver removal), drop
* the uobject reference unconditionally. The object gets freed
* (bnxt_re_dbr_kref_release) when the usecnt goes to zero.
*/
if (why == RDMA_REMOVE_DESTROY && kref_read(&obj->usecnt) > 1)
return -EBUSY;
kref_put(&obj->usecnt, bnxt_re_dbr_kref_release);
return 0;
}
static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_DEFAULT_DBR)(struct uverbs_attr_bundle *attrs)
{
struct bnxt_re_db_region dpi = {};
struct bnxt_re_ucontext *uctx;
struct ib_ucontext *ib_uctx;
int ret;
ib_uctx = ib_uverbs_get_ucontext(attrs);
if (IS_ERR(ib_uctx))
return PTR_ERR(ib_uctx);
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
dpi.umdbr = uctx->dpi.umdbr;
dpi.dpi = uctx->dpi.dpi;
ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_DEFAULT_DBR_ATTR,
&dpi, sizeof(dpi));
if (ret)
return ret;
return 0;
}
DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_DBR_ALLOC,
UVERBS_ATTR_IDR(BNXT_RE_ALLOC_DBR_HANDLE,
BNXT_RE_OBJECT_DBR,
UVERBS_ACCESS_NEW,
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_ATTR,
UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
umdbr),
UA_MANDATORY),
UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_OFFSET,
UVERBS_ATTR_TYPE(u64),
UA_MANDATORY));
DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DBR_FREE,
UVERBS_ATTR_IDR(BNXT_RE_FREE_DBR_HANDLE,
BNXT_RE_OBJECT_DBR,
UVERBS_ACCESS_DESTROY,
UA_MANDATORY));
DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_DBR,
UVERBS_TYPE_ALLOC_IDR(bnxt_re_dbr_cleanup),
&UVERBS_METHOD(BNXT_RE_METHOD_DBR_ALLOC),
&UVERBS_METHOD(BNXT_RE_METHOD_DBR_FREE));
DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_DEFAULT_DBR,
UVERBS_ATTR_PTR_OUT(BNXT_RE_DEFAULT_DBR_ATTR,
UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
umdbr),
UA_MANDATORY));
DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_DEFAULT_DBR,
&UVERBS_METHOD(BNXT_RE_METHOD_GET_DEFAULT_DBR));
ADD_UVERBS_ATTRIBUTES_SIMPLE(
bnxt_re_qp_create,
UVERBS_OBJECT_QP,
UVERBS_METHOD_QP_CREATE,
UVERBS_ATTR_IDR(BNXT_RE_CREATE_QP_ATTR_DBR_HANDLE,
BNXT_RE_OBJECT_DBR,
UVERBS_ACCESS_READ,
UA_OPTIONAL));
const struct uapi_definition bnxt_re_create_qp_defs[] = {
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_QP, &bnxt_re_qp_create),
{},
};
const struct uapi_definition bnxt_re_uapi_defs[] = {
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_ALLOC_PAGE),
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_NOTIFY_DRV),
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_GET_TOGGLE_MEM),
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_DBR),
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_DEFAULT_DBR),
UAPI_DEF_CHAIN(bnxt_re_create_qp_defs),
{}
};