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_OCRDMA
tristate "Emulex One Connect HCA support"
depends on ETHERNET && NETDEVICES && PCI && INET
select NET_VENDOR_EMULEX
select BE2NET
help
This driver provides low-level InfiniBand over Ethernet
support for Emulex One Connect host channel adapters (HCAs).
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
ccflags-y := -I $(srctree)/drivers/net/ethernet/emulex/benet
obj-$(CONFIG_INFINIBAND_OCRDMA) += ocrdma.o
ocrdma-y := ocrdma_main.o ocrdma_verbs.o ocrdma_hw.o ocrdma_ah.o ocrdma_stats.o
@@ -0,0 +1,605 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef __OCRDMA_H__
#define __OCRDMA_H__
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
#include <rdma/ib_addr.h>
#include <be_roce.h>
#include "ocrdma_sli.h"
#define OCRDMA_ROCE_DRV_VERSION "11.0.0.0"
#define OCRDMA_ROCE_DRV_DESC "Emulex OneConnect RoCE Driver"
#define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA"
#define OC_NAME_SH OCRDMA_NODE_DESC "(Skyhawk)"
#define OC_NAME_UNKNOWN OCRDMA_NODE_DESC "(Unknown)"
#define OC_SKH_DEVICE_PF 0x720
#define OC_SKH_DEVICE_VF 0x728
#define OCRDMA_MAX_AH 512
#define convert_to_64bit(lo, hi) ((u64)hi << 32 | (u64)lo)
#define EQ_INTR_PER_SEC_THRSH_HI 150000
#define EQ_INTR_PER_SEC_THRSH_LOW 100000
#define EQ_AIC_MAX_EQD 20
#define EQ_AIC_MIN_EQD 0
void ocrdma_eqd_set_task(struct work_struct *work);
struct ocrdma_dev_attr {
u8 fw_ver[32];
u32 vendor_id;
u32 device_id;
u16 max_pd;
u16 max_dpp_pds;
u16 max_cq;
u16 max_cqe;
u16 max_qp;
u16 max_wqe;
u16 max_rqe;
u16 max_srq;
u32 max_inline_data;
int max_send_sge;
int max_recv_sge;
int max_srq_sge;
int max_rdma_sge;
int max_mr;
u64 max_mr_size;
u32 max_num_mr_pbl;
int max_mw;
int max_map_per_fmr;
int max_pages_per_frmr;
u16 max_ord_per_qp;
u16 max_ird_per_qp;
int device_cap_flags;
u8 cq_overflow_detect;
u8 srq_supported;
u32 wqe_size;
u32 rqe_size;
u32 ird_page_size;
u8 local_ca_ack_delay;
u8 ird;
u8 num_ird_pages;
u8 udp_encap;
};
struct ocrdma_dma_mem {
void *va;
dma_addr_t pa;
u32 size;
};
struct ocrdma_pbl {
void *va;
dma_addr_t pa;
};
struct ocrdma_queue_info {
void *va;
dma_addr_t dma;
u32 size;
u16 len;
u16 entry_size; /* Size of an element in the queue */
u16 id; /* qid, where to ring the doorbell. */
u16 head, tail;
bool created;
};
struct ocrdma_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
u32 prev_eqd;
u64 eq_intr_cnt;
u64 prev_eq_intr_cnt;
};
struct ocrdma_eq {
struct ocrdma_queue_info q;
u32 vector;
int cq_cnt;
struct ocrdma_dev *dev;
char irq_name[32];
struct ocrdma_aic_obj aic_obj;
};
struct ocrdma_mq {
struct ocrdma_queue_info sq;
struct ocrdma_queue_info cq;
bool rearm_cq;
};
struct mqe_ctx {
struct mutex lock; /* for serializing mailbox commands on MQ */
wait_queue_head_t cmd_wait;
u32 tag;
u16 cqe_status;
u16 ext_status;
bool cmd_done;
bool fw_error_state;
};
struct ocrdma_hw_mr {
u32 lkey;
u8 fr_mr;
u8 remote_atomic;
u8 remote_rd;
u8 remote_wr;
u8 local_rd;
u8 local_wr;
u8 mw_bind;
u8 rsvd;
u64 len;
struct ocrdma_pbl *pbl_table;
u32 num_pbls;
u32 num_pbes;
u32 pbl_size;
u32 pbe_size;
u64 va;
};
struct ocrdma_mr {
struct ib_mr ibmr;
struct ib_umem *umem;
struct ocrdma_hw_mr hwmr;
u32 npages;
u64 pages[];
};
struct ocrdma_stats {
u8 type;
struct ocrdma_dev *dev;
};
struct ocrdma_pd_resource_mgr {
u32 pd_norm_start;
u16 pd_norm_count;
u16 pd_norm_thrsh;
u16 max_normal_pd;
u32 pd_dpp_start;
u16 pd_dpp_count;
u16 pd_dpp_thrsh;
u16 max_dpp_pd;
u16 dpp_page_index;
unsigned long *pd_norm_bitmap;
unsigned long *pd_dpp_bitmap;
bool pd_prealloc_valid;
};
struct stats_mem {
struct ocrdma_mqe mqe;
void *va;
dma_addr_t pa;
u32 size;
char *debugfs_mem;
};
struct phy_info {
u16 auto_speeds_supported;
u16 fixed_speeds_supported;
u16 phy_type;
u16 interface_type;
};
enum ocrdma_flags {
OCRDMA_FLAGS_LINK_STATUS_INIT = 0x01
};
struct ocrdma_dev {
struct ib_device ibdev;
struct ocrdma_dev_attr attr;
struct mutex dev_lock; /* provides syncronise access to device data */
spinlock_t flush_q_lock ____cacheline_aligned;
struct ocrdma_cq **cq_tbl;
struct ocrdma_qp **qp_tbl;
struct ocrdma_eq *eq_tbl;
int eq_cnt;
struct delayed_work eqd_work;
u16 base_eqid;
u16 max_eq;
/* provided synchronization to sgid table for
* updating gid entries triggered by notifier.
*/
spinlock_t sgid_lock;
int gsi_qp_created;
struct ocrdma_cq *gsi_sqcq;
struct ocrdma_cq *gsi_rqcq;
struct {
struct ocrdma_av *va;
dma_addr_t pa;
u32 size;
u32 num_ah;
/* provide synchronization for av
* entry allocations.
*/
spinlock_t lock;
u32 ahid;
struct ocrdma_pbl pbl;
} av_tbl;
void *mbx_cmd;
struct ocrdma_mq mq;
struct mqe_ctx mqe_ctx;
struct be_dev_info nic_info;
struct phy_info phy;
char model_number[32];
u32 hba_port_num;
struct list_head entry;
int id;
u64 *stag_arr;
u8 sl; /* service level */
bool pfc_state;
atomic_t update_sl;
u16 pvid;
u32 asic_id;
u32 flags;
ulong last_stats_time;
struct mutex stats_lock; /* provide synch for debugfs operations */
struct stats_mem stats_mem;
struct ocrdma_stats rsrc_stats;
struct ocrdma_stats rx_stats;
struct ocrdma_stats wqe_stats;
struct ocrdma_stats tx_stats;
struct ocrdma_stats db_err_stats;
struct ocrdma_stats tx_qp_err_stats;
struct ocrdma_stats rx_qp_err_stats;
struct ocrdma_stats tx_dbg_stats;
struct ocrdma_stats rx_dbg_stats;
struct ocrdma_stats driver_stats;
struct ocrdma_stats reset_stats;
struct dentry *dir;
atomic_t async_err_stats[OCRDMA_MAX_ASYNC_ERRORS];
atomic_t cqe_err_stats[OCRDMA_MAX_CQE_ERR];
struct ocrdma_pd_resource_mgr *pd_mgr;
};
struct ocrdma_cq {
struct ib_cq ibcq;
struct ocrdma_cqe *va;
u32 phase;
u32 getp; /* pointer to pending wrs to
* return to stack, wrap arounds
* at max_hw_cqe
*/
u32 max_hw_cqe;
bool phase_change;
spinlock_t cq_lock ____cacheline_aligned; /* provide synchronization
* to cq polling
*/
/* syncronizes cq completion handler invoked from multiple context */
spinlock_t comp_handler_lock ____cacheline_aligned;
u16 id;
u16 eqn;
struct ocrdma_ucontext *ucontext;
dma_addr_t pa;
u32 len;
u32 cqe_cnt;
/* head of all qp's sq and rq for which cqes need to be flushed
* by the software.
*/
struct list_head sq_head, rq_head;
};
struct ocrdma_pd {
struct ib_pd ibpd;
struct ocrdma_ucontext *uctx;
u32 id;
int num_dpp_qp;
u32 dpp_page;
bool dpp_enabled;
};
struct ocrdma_ah {
struct ib_ah ibah;
struct ocrdma_av *av;
u16 sgid_index;
u32 id;
u8 hdr_type;
};
struct ocrdma_qp_hwq_info {
u8 *va; /* virtual address */
u32 max_sges;
u32 head, tail;
u32 entry_size;
u32 max_cnt;
u32 max_wqe_idx;
u16 dbid; /* qid, where to ring the doorbell. */
u32 len;
dma_addr_t pa;
};
struct ocrdma_srq {
struct ib_srq ibsrq;
u8 __iomem *db;
struct ocrdma_qp_hwq_info rq;
u64 *rqe_wr_id_tbl;
u32 *idx_bit_fields;
u32 bit_fields_len;
/* provide synchronization to multiple context(s) posting rqe */
spinlock_t q_lock ____cacheline_aligned;
struct ocrdma_pd *pd;
u32 id;
};
struct ocrdma_qp {
struct ib_qp ibqp;
u8 __iomem *sq_db;
struct ocrdma_qp_hwq_info sq;
struct {
uint64_t wrid;
uint16_t dpp_wqe_idx;
uint16_t dpp_wqe;
uint8_t signaled;
uint8_t rsvd[3];
} *wqe_wr_id_tbl;
u32 max_inline_data;
/* provide synchronization to multiple context(s) posting wqe, rqe */
spinlock_t q_lock ____cacheline_aligned;
struct ocrdma_cq *sq_cq;
/* list maintained per CQ to flush SQ errors */
struct list_head sq_entry;
u8 __iomem *rq_db;
struct ocrdma_qp_hwq_info rq;
u64 *rqe_wr_id_tbl;
struct ocrdma_cq *rq_cq;
struct ocrdma_srq *srq;
/* list maintained per CQ to flush RQ errors */
struct list_head rq_entry;
enum ocrdma_qp_state state; /* QP state */
int cap_flags;
u32 max_ord, max_ird;
u32 id;
struct ocrdma_pd *pd;
enum ib_qp_type qp_type;
int sgid_idx;
u32 qkey;
bool dpp_enabled;
u8 *ird_q_va;
bool signaled;
};
struct ocrdma_ucontext {
struct ib_ucontext ibucontext;
struct list_head mm_head;
struct mutex mm_list_lock; /* protects list entries of mm type */
struct ocrdma_pd *cntxt_pd;
int pd_in_use;
struct {
u32 *va;
dma_addr_t pa;
u32 len;
} ah_tbl;
};
struct ocrdma_mm {
struct {
u64 phy_addr;
unsigned long len;
} key;
struct list_head entry;
};
static inline struct ocrdma_dev *get_ocrdma_dev(struct ib_device *ibdev)
{
return container_of(ibdev, struct ocrdma_dev, ibdev);
}
static inline struct ocrdma_ucontext *get_ocrdma_ucontext(struct ib_ucontext
*ibucontext)
{
return container_of(ibucontext, struct ocrdma_ucontext, ibucontext);
}
static inline struct ocrdma_pd *get_ocrdma_pd(struct ib_pd *ibpd)
{
return container_of(ibpd, struct ocrdma_pd, ibpd);
}
static inline struct ocrdma_cq *get_ocrdma_cq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct ocrdma_cq, ibcq);
}
static inline struct ocrdma_qp *get_ocrdma_qp(struct ib_qp *ibqp)
{
return container_of(ibqp, struct ocrdma_qp, ibqp);
}
static inline struct ocrdma_mr *get_ocrdma_mr(struct ib_mr *ibmr)
{
return container_of(ibmr, struct ocrdma_mr, ibmr);
}
static inline struct ocrdma_ah *get_ocrdma_ah(struct ib_ah *ibah)
{
return container_of(ibah, struct ocrdma_ah, ibah);
}
static inline struct ocrdma_srq *get_ocrdma_srq(struct ib_srq *ibsrq)
{
return container_of(ibsrq, struct ocrdma_srq, ibsrq);
}
static inline int is_cqe_valid(struct ocrdma_cq *cq, struct ocrdma_cqe *cqe)
{
int cqe_valid;
cqe_valid = le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_VALID;
return (cqe_valid == cq->phase);
}
static inline int is_cqe_for_sq(struct ocrdma_cqe *cqe)
{
return (le32_to_cpu(cqe->flags_status_srcqpn) &
OCRDMA_CQE_QTYPE) ? 0 : 1;
}
static inline int is_cqe_invalidated(struct ocrdma_cqe *cqe)
{
return (le32_to_cpu(cqe->flags_status_srcqpn) &
OCRDMA_CQE_INVALIDATE) ? 1 : 0;
}
static inline int is_cqe_imm(struct ocrdma_cqe *cqe)
{
return (le32_to_cpu(cqe->flags_status_srcqpn) &
OCRDMA_CQE_IMM) ? 1 : 0;
}
static inline int is_cqe_wr_imm(struct ocrdma_cqe *cqe)
{
return (le32_to_cpu(cqe->flags_status_srcqpn) &
OCRDMA_CQE_WRITE_IMM) ? 1 : 0;
}
static inline int ocrdma_resolve_dmac(struct ocrdma_dev *dev,
struct rdma_ah_attr *ah_attr, u8 *mac_addr)
{
struct in6_addr in6;
memcpy(&in6, rdma_ah_read_grh(ah_attr)->dgid.raw, sizeof(in6));
if (rdma_is_multicast_addr(&in6))
rdma_get_mcast_mac(&in6, mac_addr);
else if (rdma_link_local_addr(&in6))
rdma_get_ll_mac(&in6, mac_addr);
else
memcpy(mac_addr, ah_attr->roce.dmac, ETH_ALEN);
return 0;
}
static inline char *hca_name(struct ocrdma_dev *dev)
{
switch (dev->nic_info.pdev->device) {
case OC_SKH_DEVICE_PF:
case OC_SKH_DEVICE_VF:
return OC_NAME_SH;
default:
return OC_NAME_UNKNOWN;
}
}
static inline int ocrdma_get_eq_table_index(struct ocrdma_dev *dev,
int eqid)
{
int indx;
for (indx = 0; indx < dev->eq_cnt; indx++) {
if (dev->eq_tbl[indx].q.id == eqid)
return indx;
}
return -EINVAL;
}
static inline u8 ocrdma_get_asic_type(struct ocrdma_dev *dev)
{
if (dev->nic_info.dev_family == 0xF && !dev->asic_id) {
pci_read_config_dword(
dev->nic_info.pdev,
OCRDMA_SLI_ASIC_ID_OFFSET, &dev->asic_id);
}
return (dev->asic_id & OCRDMA_SLI_ASIC_GEN_NUM_MASK) >>
OCRDMA_SLI_ASIC_GEN_NUM_SHIFT;
}
static inline u8 ocrdma_get_pfc_prio(u8 *pfc, u8 prio)
{
return *(pfc + prio);
}
static inline u8 ocrdma_get_app_prio(u8 *app_prio, u8 prio)
{
return *(app_prio + prio);
}
static inline u8 ocrdma_is_enabled_and_synced(u32 state)
{ /* May also be used to interpret TC-state, QCN-state
* Appl-state and Logical-link-state in future.
*/
return (state & OCRDMA_STATE_FLAG_ENABLED) &&
(state & OCRDMA_STATE_FLAG_SYNC);
}
static inline u8 ocrdma_get_ae_link_state(u32 ae_state)
{
return ((ae_state & OCRDMA_AE_LSC_LS_MASK) >> OCRDMA_AE_LSC_LS_SHIFT);
}
static inline bool ocrdma_is_udp_encap_supported(struct ocrdma_dev *dev)
{
return (dev->attr.udp_encap & OCRDMA_L3_TYPE_IPV4) ||
(dev->attr.udp_encap & OCRDMA_L3_TYPE_IPV6);
}
#endif
@@ -0,0 +1,268 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include <net/neighbour.h>
#include <net/netevent.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_mad.h>
#include <rdma/ib_cache.h>
#include "ocrdma.h"
#include "ocrdma_verbs.h"
#include "ocrdma_ah.h"
#include "ocrdma_hw.h"
#include "ocrdma_stats.h"
#define OCRDMA_VID_PCP_SHIFT 0xD
static u16 ocrdma_hdr_type_to_proto_num(int devid, u8 hdr_type)
{
switch (hdr_type) {
case OCRDMA_L3_TYPE_IB_GRH:
return (u16)ETH_P_IBOE;
case OCRDMA_L3_TYPE_IPV4:
return (u16)0x0800;
case OCRDMA_L3_TYPE_IPV6:
return (u16)0x86dd;
default:
pr_err("ocrdma%d: Invalid network header\n", devid);
return 0;
}
}
static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
struct rdma_ah_attr *attr, const union ib_gid *sgid,
int pdid, bool *isvlan, u16 vlan_tag)
{
int status;
struct ocrdma_eth_vlan eth;
struct ocrdma_grh grh;
int eth_sz;
u16 proto_num = 0;
u8 nxthdr = 0x11;
struct iphdr ipv4;
const struct ib_global_route *ib_grh;
union {
struct sockaddr_in _sockaddr_in;
struct sockaddr_in6 _sockaddr_in6;
} sgid_addr, dgid_addr;
memset(&eth, 0, sizeof(eth));
memset(&grh, 0, sizeof(grh));
/* Protocol Number */
proto_num = ocrdma_hdr_type_to_proto_num(dev->id, ah->hdr_type);
if (!proto_num)
return -EINVAL;
nxthdr = (proto_num == ETH_P_IBOE) ? 0x1b : 0x11;
/* VLAN */
if (!vlan_tag || (vlan_tag > 0xFFF))
vlan_tag = dev->pvid;
if (vlan_tag || dev->pfc_state) {
if (!vlan_tag) {
pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
dev->id);
pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
dev->id);
}
eth.eth_type = cpu_to_be16(0x8100);
eth.roce_eth_type = cpu_to_be16(proto_num);
vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
eth.vlan_tag = cpu_to_be16(vlan_tag);
eth_sz = sizeof(struct ocrdma_eth_vlan);
*isvlan = true;
} else {
eth.eth_type = cpu_to_be16(proto_num);
eth_sz = sizeof(struct ocrdma_eth_basic);
}
/* MAC */
memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
status = ocrdma_resolve_dmac(dev, attr, &eth.dmac[0]);
if (status)
return status;
ib_grh = rdma_ah_read_grh(attr);
ah->sgid_index = ib_grh->sgid_index;
/* Eth HDR */
memcpy(&ah->av->eth_hdr, &eth, eth_sz);
if (ah->hdr_type == RDMA_NETWORK_IPV4) {
*((__be16 *)&ipv4) = htons((4 << 12) | (5 << 8) |
ib_grh->traffic_class);
ipv4.id = cpu_to_be16(pdid);
ipv4.frag_off = htons(IP_DF);
ipv4.tot_len = htons(0);
ipv4.ttl = ib_grh->hop_limit;
ipv4.protocol = nxthdr;
rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
ipv4.saddr = sgid_addr._sockaddr_in.sin_addr.s_addr;
rdma_gid2ip((struct sockaddr*)&dgid_addr, &ib_grh->dgid);
ipv4.daddr = dgid_addr._sockaddr_in.sin_addr.s_addr;
memcpy((u8 *)ah->av + eth_sz, &ipv4, sizeof(struct iphdr));
} else {
memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
grh.tclass_flow = cpu_to_be32((6 << 28) |
(ib_grh->traffic_class << 24) |
ib_grh->flow_label);
memcpy(&grh.dgid[0], ib_grh->dgid.raw,
sizeof(ib_grh->dgid.raw));
grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
(nxthdr << 8) |
ib_grh->hop_limit);
memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
}
if (*isvlan)
ah->av->valid |= OCRDMA_AV_VLAN_VALID;
ah->av->valid = cpu_to_le32(ah->av->valid);
return status;
}
int ocrdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
struct ib_udata *udata)
{
u32 *ahid_addr;
int status;
struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
bool isvlan = false;
u16 vlan_tag = 0xffff;
const struct ib_gid_attr *sgid_attr;
struct ocrdma_pd *pd = get_ocrdma_pd(ibah->pd);
struct rdma_ah_attr *attr = init_attr->ah_attr;
struct ocrdma_dev *dev = get_ocrdma_dev(ibah->device);
if ((attr->type != RDMA_AH_ATTR_TYPE_ROCE) ||
!(rdma_ah_get_ah_flags(attr) & IB_AH_GRH))
return -EINVAL;
if (atomic_cmpxchg(&dev->update_sl, 1, 0))
ocrdma_init_service_level(dev);
sgid_attr = attr->grh.sgid_attr;
status = rdma_read_gid_l2_fields(sgid_attr, &vlan_tag, NULL);
if (status)
return status;
status = ocrdma_alloc_av(dev, ah);
if (status)
goto av_err;
/* Get network header type for this GID */
ah->hdr_type = rdma_gid_attr_network_type(sgid_attr);
status = set_av_attr(dev, ah, attr, &sgid_attr->gid, pd->id,
&isvlan, vlan_tag);
if (status)
goto av_conf_err;
/* if pd is for the user process, pass the ah_id to user space */
if ((pd->uctx) && (pd->uctx->ah_tbl.va)) {
ahid_addr = pd->uctx->ah_tbl.va + rdma_ah_get_dlid(attr);
*ahid_addr = 0;
*ahid_addr |= ah->id & OCRDMA_AH_ID_MASK;
if (ocrdma_is_udp_encap_supported(dev)) {
*ahid_addr |= ((u32)ah->hdr_type &
OCRDMA_AH_L3_TYPE_MASK) <<
OCRDMA_AH_L3_TYPE_SHIFT;
}
if (isvlan)
*ahid_addr |= (OCRDMA_AH_VLAN_VALID_MASK <<
OCRDMA_AH_VLAN_VALID_SHIFT);
}
return 0;
av_conf_err:
ocrdma_free_av(dev, ah);
av_err:
return status;
}
int ocrdma_destroy_ah(struct ib_ah *ibah, u32 flags)
{
struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
struct ocrdma_dev *dev = get_ocrdma_dev(ibah->device);
ocrdma_free_av(dev, ah);
return 0;
}
int ocrdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr)
{
struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
struct ocrdma_av *av = ah->av;
struct ocrdma_grh *grh;
attr->type = ibah->type;
if (ah->av->valid & OCRDMA_AV_VALID) {
grh = (struct ocrdma_grh *)((u8 *)ah->av +
sizeof(struct ocrdma_eth_vlan));
rdma_ah_set_sl(attr, be16_to_cpu(av->eth_hdr.vlan_tag) >> 13);
} else {
grh = (struct ocrdma_grh *)((u8 *)ah->av +
sizeof(struct ocrdma_eth_basic));
rdma_ah_set_sl(attr, 0);
}
rdma_ah_set_grh(attr, NULL,
be32_to_cpu(grh->tclass_flow) & 0xffffffff,
ah->sgid_index,
be32_to_cpu(grh->pdid_hoplimit) & 0xff,
be32_to_cpu(grh->tclass_flow) >> 24);
rdma_ah_set_dgid_raw(attr, &grh->dgid[0]);
return 0;
}
int ocrdma_process_mad(struct ib_device *ibdev, int process_mad_flags,
u32 port_num, const struct ib_wc *in_wc,
const struct ib_grh *in_grh, const struct ib_mad *in,
struct ib_mad *out, size_t *out_mad_size,
u16 *out_mad_pkey_index)
{
int status = IB_MAD_RESULT_SUCCESS;
struct ocrdma_dev *dev;
if (in->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
dev = get_ocrdma_dev(ibdev);
ocrdma_pma_counters(dev, out);
status |= IB_MAD_RESULT_REPLY;
}
return status;
}
@@ -0,0 +1,64 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef __OCRDMA_AH_H__
#define __OCRDMA_AH_H__
enum {
OCRDMA_AH_ID_MASK = 0x3FF,
OCRDMA_AH_VLAN_VALID_MASK = 0x01,
OCRDMA_AH_VLAN_VALID_SHIFT = 0x1F,
OCRDMA_AH_L3_TYPE_MASK = 0x03,
OCRDMA_AH_L3_TYPE_SHIFT = 0x1D /* 29 bits */
};
int ocrdma_create_ah(struct ib_ah *ah, struct rdma_ah_init_attr *init_attr,
struct ib_udata *udata);
int ocrdma_destroy_ah(struct ib_ah *ah, u32 flags);
int ocrdma_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
int ocrdma_process_mad(struct ib_device *dev, int process_mad_flags,
u32 port_num, const struct ib_wc *in_wc,
const struct ib_grh *in_grh, const struct ib_mad *in,
struct ib_mad *out, size_t *out_mad_size,
u16 *out_mad_pkey_index);
#endif /* __OCRDMA_AH_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,159 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef __OCRDMA_HW_H__
#define __OCRDMA_HW_H__
#include "ocrdma_sli.h"
static inline void ocrdma_cpu_to_le32(void *dst, u32 len)
{
#ifdef __BIG_ENDIAN
int i = 0;
u32 *src_ptr = dst;
u32 *dst_ptr = dst;
for (; i < (len / 4); i++)
*(dst_ptr + i) = cpu_to_le32p(src_ptr + i);
#endif
}
static inline void ocrdma_le32_to_cpu(void *dst, u32 len)
{
#ifdef __BIG_ENDIAN
int i = 0;
u32 *src_ptr = dst;
u32 *dst_ptr = dst;
for (; i < (len / sizeof(u32)); i++)
*(dst_ptr + i) = le32_to_cpu(*(src_ptr + i));
#endif
}
static inline void ocrdma_copy_cpu_to_le32(void *dst, void *src, u32 len)
{
#ifdef __BIG_ENDIAN
int i = 0;
u32 *src_ptr = src;
u32 *dst_ptr = dst;
for (; i < (len / sizeof(u32)); i++)
*(dst_ptr + i) = cpu_to_le32p(src_ptr + i);
#else
memcpy(dst, src, len);
#endif
}
static inline void ocrdma_copy_le32_to_cpu(void *dst, void *src, u32 len)
{
#ifdef __BIG_ENDIAN
int i = 0;
u32 *src_ptr = src;
u32 *dst_ptr = dst;
for (; i < len / sizeof(u32); i++)
*(dst_ptr + i) = le32_to_cpu(*(src_ptr + i));
#else
memcpy(dst, src, len);
#endif
}
static inline u64 ocrdma_get_db_addr(struct ocrdma_dev *dev, u32 pdid)
{
return dev->nic_info.unmapped_db + (pdid * dev->nic_info.db_page_size);
}
int ocrdma_init_hw(struct ocrdma_dev *);
void ocrdma_cleanup_hw(struct ocrdma_dev *);
enum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps);
void ocrdma_ring_cq_db(struct ocrdma_dev *, u16 cq_id, bool armed,
bool solicited, u16 cqe_popped);
/* verbs specific mailbox commands */
int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed,
u8 *lnk_st);
int ocrdma_query_config(struct ocrdma_dev *,
struct ocrdma_mbx_query_config *config);
int ocrdma_mbx_alloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
int ocrdma_mbx_dealloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
int ocrdma_mbx_alloc_lkey(struct ocrdma_dev *, struct ocrdma_hw_mr *hwmr,
u32 pd_id, int addr_check);
int ocrdma_mbx_dealloc_lkey(struct ocrdma_dev *, int fmr, u32 lkey);
int ocrdma_reg_mr(struct ocrdma_dev *, struct ocrdma_hw_mr *hwmr,
u32 pd_id, int acc);
int ocrdma_mbx_create_cq(struct ocrdma_dev *, struct ocrdma_cq *,
int entries, int dpp_cq, u16 pd_id);
void ocrdma_mbx_destroy_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq);
int ocrdma_mbx_create_qp(struct ocrdma_qp *, struct ib_qp_init_attr *attrs,
u8 enable_dpp_cq, u16 dpp_cq_id, u16 *dpp_offset,
u16 *dpp_credit_lmt);
int ocrdma_mbx_modify_qp(struct ocrdma_dev *, struct ocrdma_qp *,
struct ib_qp_attr *attrs, int attr_mask);
int ocrdma_mbx_query_qp(struct ocrdma_dev *, struct ocrdma_qp *,
struct ocrdma_qp_params *param);
int ocrdma_mbx_destroy_qp(struct ocrdma_dev *, struct ocrdma_qp *);
int ocrdma_mbx_create_srq(struct ocrdma_dev *, struct ocrdma_srq *,
struct ib_srq_init_attr *,
struct ocrdma_pd *);
int ocrdma_mbx_modify_srq(struct ocrdma_srq *, struct ib_srq_attr *);
int ocrdma_mbx_query_srq(struct ocrdma_srq *, struct ib_srq_attr *);
void ocrdma_mbx_destroy_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq);
int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah);
void ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah);
int ocrdma_qp_state_change(struct ocrdma_qp *, enum ib_qp_state new_state,
enum ib_qp_state *old_ib_state);
bool ocrdma_is_qp_in_sq_flushlist(struct ocrdma_cq *, struct ocrdma_qp *);
bool ocrdma_is_qp_in_rq_flushlist(struct ocrdma_cq *, struct ocrdma_qp *);
void ocrdma_flush_qp(struct ocrdma_qp *);
int ocrdma_get_irq(struct ocrdma_dev *dev, struct ocrdma_eq *eq);
int ocrdma_mbx_rdma_stats(struct ocrdma_dev *, bool reset);
char *port_speed_string(struct ocrdma_dev *dev);
void ocrdma_init_service_level(struct ocrdma_dev *);
void ocrdma_alloc_pd_pool(struct ocrdma_dev *dev);
void ocrdma_free_pd_range(struct ocrdma_dev *dev);
void ocrdma_update_link_state(struct ocrdma_dev *dev, u8 lstate);
#endif /* __OCRDMA_HW_H__ */
@@ -0,0 +1,429 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include <linux/module.h>
#include <linux/idr.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_mad.h>
#include <linux/netdevice.h>
#include <net/addrconf.h>
#include "ocrdma.h"
#include "ocrdma_verbs.h"
#include "ocrdma_ah.h"
#include "be_roce.h"
#include "ocrdma_hw.h"
#include "ocrdma_stats.h"
#include <rdma/ocrdma-abi.h>
MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION);
MODULE_AUTHOR("Emulex Corporation");
MODULE_LICENSE("Dual BSD/GPL");
static enum rdma_link_layer ocrdma_link_layer(struct ib_device *device,
u32 port_num)
{
return IB_LINK_LAYER_ETHERNET;
}
static int ocrdma_port_immutable(struct ib_device *ibdev, u32 port_num,
struct ib_port_immutable *immutable)
{
struct ib_port_attr attr;
struct ocrdma_dev *dev;
int err;
dev = get_ocrdma_dev(ibdev);
immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
if (ocrdma_is_udp_encap_supported(dev))
immutable->core_cap_flags |= RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP;
err = ib_query_port(ibdev, port_num, &attr);
if (err)
return err;
immutable->pkey_tbl_len = attr.pkey_tbl_len;
immutable->gid_tbl_len = attr.gid_tbl_len;
immutable->max_mad_size = IB_MGMT_MAD_SIZE;
return 0;
}
static void get_dev_fw_str(struct ib_device *device, char *str)
{
struct ocrdma_dev *dev = get_ocrdma_dev(device);
snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", &dev->attr.fw_ver[0]);
}
/* OCRDMA sysfs interface */
static ssize_t hw_rev_show(struct device *device,
struct device_attribute *attr, char *buf)
{
struct ocrdma_dev *dev =
rdma_device_to_drv_device(device, struct ocrdma_dev, ibdev);
return sysfs_emit(buf, "0x%x\n", dev->nic_info.pdev->vendor);
}
static DEVICE_ATTR_RO(hw_rev);
static ssize_t hca_type_show(struct device *device,
struct device_attribute *attr, char *buf)
{
struct ocrdma_dev *dev =
rdma_device_to_drv_device(device, struct ocrdma_dev, ibdev);
return sysfs_emit(buf, "%s\n", &dev->model_number[0]);
}
static DEVICE_ATTR_RO(hca_type);
static struct attribute *ocrdma_attributes[] = {
&dev_attr_hw_rev.attr,
&dev_attr_hca_type.attr,
NULL
};
static const struct attribute_group ocrdma_attr_group = {
.attrs = ocrdma_attributes,
};
static const struct ib_device_ops ocrdma_dev_ops = {
.owner = THIS_MODULE,
.driver_id = RDMA_DRIVER_OCRDMA,
.uverbs_abi_ver = OCRDMA_ABI_VERSION,
.alloc_mr = ocrdma_alloc_mr,
.alloc_pd = ocrdma_alloc_pd,
.alloc_ucontext = ocrdma_alloc_ucontext,
.create_ah = ocrdma_create_ah,
.create_cq = ocrdma_create_cq,
.create_qp = ocrdma_create_qp,
.create_user_ah = ocrdma_create_ah,
.dealloc_pd = ocrdma_dealloc_pd,
.dealloc_ucontext = ocrdma_dealloc_ucontext,
.dereg_mr = ocrdma_dereg_mr,
.destroy_ah = ocrdma_destroy_ah,
.destroy_cq = ocrdma_destroy_cq,
.destroy_qp = ocrdma_destroy_qp,
.device_group = &ocrdma_attr_group,
.get_dev_fw_str = get_dev_fw_str,
.get_dma_mr = ocrdma_get_dma_mr,
.get_link_layer = ocrdma_link_layer,
.get_port_immutable = ocrdma_port_immutable,
.map_mr_sg = ocrdma_map_mr_sg,
.mmap = ocrdma_mmap,
.modify_qp = ocrdma_modify_qp,
.poll_cq = ocrdma_poll_cq,
.post_recv = ocrdma_post_recv,
.post_send = ocrdma_post_send,
.process_mad = ocrdma_process_mad,
.query_ah = ocrdma_query_ah,
.query_device = ocrdma_query_device,
.query_pkey = ocrdma_query_pkey,
.query_port = ocrdma_query_port,
.query_qp = ocrdma_query_qp,
.reg_user_mr = ocrdma_reg_user_mr,
.req_notify_cq = ocrdma_arm_cq,
.resize_user_cq = ocrdma_resize_cq,
INIT_RDMA_OBJ_SIZE(ib_ah, ocrdma_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, ocrdma_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, ocrdma_pd, ibpd),
INIT_RDMA_OBJ_SIZE(ib_qp, ocrdma_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, ocrdma_ucontext, ibucontext),
};
static const struct ib_device_ops ocrdma_dev_srq_ops = {
.create_srq = ocrdma_create_srq,
.destroy_srq = ocrdma_destroy_srq,
.modify_srq = ocrdma_modify_srq,
.post_srq_recv = ocrdma_post_srq_recv,
.query_srq = ocrdma_query_srq,
INIT_RDMA_OBJ_SIZE(ib_srq, ocrdma_srq, ibsrq),
};
static int ocrdma_register_device(struct ocrdma_dev *dev)
{
int ret;
addrconf_addr_eui48((u8 *)&dev->ibdev.node_guid,
dev->nic_info.mac_addr);
BUILD_BUG_ON(sizeof(OCRDMA_NODE_DESC) > IB_DEVICE_NODE_DESC_MAX);
memcpy(dev->ibdev.node_desc, OCRDMA_NODE_DESC,
sizeof(OCRDMA_NODE_DESC));
dev->ibdev.node_type = RDMA_NODE_IB_CA;
dev->ibdev.phys_port_cnt = 1;
dev->ibdev.num_comp_vectors = dev->eq_cnt;
/* mandatory to support user space verbs consumer. */
dev->ibdev.dev.parent = &dev->nic_info.pdev->dev;
ib_set_device_ops(&dev->ibdev, &ocrdma_dev_ops);
if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R)
ib_set_device_ops(&dev->ibdev, &ocrdma_dev_srq_ops);
ret = ib_device_set_netdev(&dev->ibdev, dev->nic_info.netdev, 1);
if (ret)
return ret;
dma_set_max_seg_size(&dev->nic_info.pdev->dev, UINT_MAX);
return ib_register_device(&dev->ibdev, "ocrdma%d",
&dev->nic_info.pdev->dev);
}
static int ocrdma_alloc_resources(struct ocrdma_dev *dev)
{
mutex_init(&dev->dev_lock);
dev->cq_tbl = kzalloc_objs(struct ocrdma_cq *, OCRDMA_MAX_CQ);
if (!dev->cq_tbl)
goto alloc_err;
if (dev->attr.max_qp) {
dev->qp_tbl = kzalloc_objs(struct ocrdma_qp *, OCRDMA_MAX_QP);
if (!dev->qp_tbl)
goto alloc_err;
}
dev->stag_arr = kcalloc(OCRDMA_MAX_STAG, sizeof(u64), GFP_KERNEL);
if (dev->stag_arr == NULL)
goto alloc_err;
ocrdma_alloc_pd_pool(dev);
if (!ocrdma_alloc_stats_resources(dev)) {
pr_err("%s: stats resource allocation failed\n", __func__);
goto alloc_err;
}
spin_lock_init(&dev->av_tbl.lock);
spin_lock_init(&dev->flush_q_lock);
return 0;
alloc_err:
pr_err("%s(%d) error.\n", __func__, dev->id);
return -ENOMEM;
}
static void ocrdma_free_resources(struct ocrdma_dev *dev)
{
ocrdma_release_stats_resources(dev);
kfree(dev->stag_arr);
kfree(dev->qp_tbl);
kfree(dev->cq_tbl);
}
static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
{
int status = 0;
u8 lstate = 0;
struct ocrdma_dev *dev;
dev = ib_alloc_device(ocrdma_dev, ibdev);
if (!dev) {
pr_err("Unable to allocate ib device\n");
return NULL;
}
dev->mbx_cmd = kzalloc_obj(struct ocrdma_mqe_emb_cmd);
if (!dev->mbx_cmd)
goto init_err;
memcpy(&dev->nic_info, dev_info, sizeof(*dev_info));
dev->id = PCI_FUNC(dev->nic_info.pdev->devfn);
status = ocrdma_init_hw(dev);
if (status)
goto init_err;
status = ocrdma_alloc_resources(dev);
if (status)
goto alloc_err;
ocrdma_init_service_level(dev);
status = ocrdma_register_device(dev);
if (status)
goto alloc_err;
/* Query Link state and update */
status = ocrdma_mbx_get_link_speed(dev, NULL, &lstate);
if (!status)
ocrdma_update_link_state(dev, lstate);
/* Init stats */
ocrdma_add_port_stats(dev);
/* Interrupt Moderation */
INIT_DELAYED_WORK(&dev->eqd_work, ocrdma_eqd_set_task);
schedule_delayed_work(&dev->eqd_work, msecs_to_jiffies(1000));
pr_info("%s %s: %s \"%s\" port %d\n",
dev_name(&dev->nic_info.pdev->dev), hca_name(dev),
port_speed_string(dev), dev->model_number,
dev->hba_port_num);
pr_info("%s ocrdma%d driver loaded successfully\n",
dev_name(&dev->nic_info.pdev->dev), dev->id);
return dev;
alloc_err:
ocrdma_free_resources(dev);
ocrdma_cleanup_hw(dev);
init_err:
kfree(dev->mbx_cmd);
ib_dealloc_device(&dev->ibdev);
pr_err("%s() leaving. ret=%d\n", __func__, status);
return NULL;
}
static void ocrdma_remove_free(struct ocrdma_dev *dev)
{
kfree(dev->mbx_cmd);
ib_dealloc_device(&dev->ibdev);
}
static void ocrdma_remove(struct ocrdma_dev *dev)
{
/* first unregister with stack to stop all the active traffic
* of the registered clients.
*/
cancel_delayed_work_sync(&dev->eqd_work);
ib_unregister_device(&dev->ibdev);
ocrdma_rem_port_stats(dev);
ocrdma_free_resources(dev);
ocrdma_cleanup_hw(dev);
ocrdma_remove_free(dev);
}
static int ocrdma_dispatch_port_active(struct ocrdma_dev *dev)
{
struct ib_event port_event;
port_event.event = IB_EVENT_PORT_ACTIVE;
port_event.element.port_num = 1;
port_event.device = &dev->ibdev;
ib_dispatch_event(&port_event);
return 0;
}
static int ocrdma_dispatch_port_error(struct ocrdma_dev *dev)
{
struct ib_event err_event;
err_event.event = IB_EVENT_PORT_ERR;
err_event.element.port_num = 1;
err_event.device = &dev->ibdev;
ib_dispatch_event(&err_event);
return 0;
}
static void ocrdma_shutdown(struct ocrdma_dev *dev)
{
ocrdma_dispatch_port_error(dev);
ocrdma_remove(dev);
}
/* event handling via NIC driver ensures that all the NIC specific
* initialization done before RoCE driver notifies
* event to stack.
*/
static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
{
switch (event) {
case BE_DEV_SHUTDOWN:
ocrdma_shutdown(dev);
break;
default:
break;
}
}
void ocrdma_update_link_state(struct ocrdma_dev *dev, u8 lstate)
{
if (!(dev->flags & OCRDMA_FLAGS_LINK_STATUS_INIT)) {
dev->flags |= OCRDMA_FLAGS_LINK_STATUS_INIT;
if (!lstate)
return;
}
if (!lstate)
ocrdma_dispatch_port_error(dev);
else
ocrdma_dispatch_port_active(dev);
}
static struct ocrdma_driver ocrdma_drv = {
.name = "ocrdma_driver",
.add = ocrdma_add,
.remove = ocrdma_remove,
.state_change_handler = ocrdma_event_handler,
.be_abi_version = OCRDMA_BE_ROCE_ABI_VERSION,
};
static int __init ocrdma_init_module(void)
{
int status;
ocrdma_init_debugfs();
status = be_roce_register_driver(&ocrdma_drv);
if (status)
goto err_be_reg;
return 0;
err_be_reg:
return status;
}
static void __exit ocrdma_exit_module(void)
{
be_roce_unregister_driver(&ocrdma_drv);
ocrdma_rem_debugfs();
}
module_init(ocrdma_init_module);
module_exit(ocrdma_exit_module);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,838 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include <rdma/ib_addr.h>
#include <rdma/ib_pma.h>
#include "ocrdma_stats.h"
static struct dentry *ocrdma_dbgfs_dir;
static noinline_for_stack int ocrdma_add_stat(char *start, char *pcur,
char *name, u64 count)
{
char buff[128] = {0};
int cpy_len = 0;
snprintf(buff, 128, "%s: %llu\n", name, count);
cpy_len = strlen(buff);
if (pcur + cpy_len > start + OCRDMA_MAX_DBGFS_MEM) {
pr_err("%s: No space in stats buff\n", __func__);
return 0;
}
memcpy(pcur, buff, cpy_len);
return cpy_len;
}
bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev)
{
struct stats_mem *mem = &dev->stats_mem;
mutex_init(&dev->stats_lock);
/* Alloc mbox command mem*/
mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req),
sizeof(struct ocrdma_rdma_stats_resp));
mem->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, mem->size,
&mem->pa, GFP_KERNEL);
if (!mem->va) {
pr_err("%s: stats mbox allocation failed\n", __func__);
return false;
}
/* Alloc debugfs mem */
mem->debugfs_mem = kzalloc(OCRDMA_MAX_DBGFS_MEM, GFP_KERNEL);
if (!mem->debugfs_mem)
return false;
return true;
}
void ocrdma_release_stats_resources(struct ocrdma_dev *dev)
{
struct stats_mem *mem = &dev->stats_mem;
if (mem->va)
dma_free_coherent(&dev->nic_info.pdev->dev, mem->size,
mem->va, mem->pa);
mem->va = NULL;
kfree(mem->debugfs_mem);
}
static noinline_for_stack char *ocrdma_resource_stats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rsrc_stats *rsrc_stats = &rdma_stats->act_rsrc_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "active_dpp_pds",
(u64)rsrc_stats->dpp_pds);
pcur += ocrdma_add_stat(stats, pcur, "active_non_dpp_pds",
(u64)rsrc_stats->non_dpp_pds);
pcur += ocrdma_add_stat(stats, pcur, "active_rc_dpp_qps",
(u64)rsrc_stats->rc_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_uc_dpp_qps",
(u64)rsrc_stats->uc_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_ud_dpp_qps",
(u64)rsrc_stats->ud_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_rc_non_dpp_qps",
(u64)rsrc_stats->rc_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_uc_non_dpp_qps",
(u64)rsrc_stats->uc_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_ud_non_dpp_qps",
(u64)rsrc_stats->ud_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_srqs",
(u64)rsrc_stats->srqs);
pcur += ocrdma_add_stat(stats, pcur, "active_rbqs",
(u64)rsrc_stats->rbqs);
pcur += ocrdma_add_stat(stats, pcur, "active_64K_nsmr",
(u64)rsrc_stats->r64K_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_64K_to_2M_nsmr",
(u64)rsrc_stats->r64K_to_2M_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_2M_to_44M_nsmr",
(u64)rsrc_stats->r2M_to_44M_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_44M_to_1G_nsmr",
(u64)rsrc_stats->r44M_to_1G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_1G_to_4G_nsmr",
(u64)rsrc_stats->r1G_to_4G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_nsmr_count_4G_to_32G",
(u64)rsrc_stats->nsmr_count_4G_to_32G);
pcur += ocrdma_add_stat(stats, pcur, "active_32G_to_64G_nsmr",
(u64)rsrc_stats->r32G_to_64G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_64G_to_128G_nsmr",
(u64)rsrc_stats->r64G_to_128G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_128G_to_higher_nsmr",
(u64)rsrc_stats->r128G_to_higher_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_embedded_nsmr",
(u64)rsrc_stats->embedded_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "active_frmr",
(u64)rsrc_stats->frmr);
pcur += ocrdma_add_stat(stats, pcur, "active_prefetch_qps",
(u64)rsrc_stats->prefetch_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_ondemand_qps",
(u64)rsrc_stats->ondemand_qps);
pcur += ocrdma_add_stat(stats, pcur, "active_phy_mr",
(u64)rsrc_stats->phy_mr);
pcur += ocrdma_add_stat(stats, pcur, "active_mw",
(u64)rsrc_stats->mw);
/* Print the threshold stats */
rsrc_stats = &rdma_stats->th_rsrc_stats;
pcur += ocrdma_add_stat(stats, pcur, "threshold_dpp_pds",
(u64)rsrc_stats->dpp_pds);
pcur += ocrdma_add_stat(stats, pcur, "threshold_non_dpp_pds",
(u64)rsrc_stats->non_dpp_pds);
pcur += ocrdma_add_stat(stats, pcur, "threshold_rc_dpp_qps",
(u64)rsrc_stats->rc_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_uc_dpp_qps",
(u64)rsrc_stats->uc_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_ud_dpp_qps",
(u64)rsrc_stats->ud_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_rc_non_dpp_qps",
(u64)rsrc_stats->rc_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_uc_non_dpp_qps",
(u64)rsrc_stats->uc_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_ud_non_dpp_qps",
(u64)rsrc_stats->ud_non_dpp_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_srqs",
(u64)rsrc_stats->srqs);
pcur += ocrdma_add_stat(stats, pcur, "threshold_rbqs",
(u64)rsrc_stats->rbqs);
pcur += ocrdma_add_stat(stats, pcur, "threshold_64K_nsmr",
(u64)rsrc_stats->r64K_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_64K_to_2M_nsmr",
(u64)rsrc_stats->r64K_to_2M_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_2M_to_44M_nsmr",
(u64)rsrc_stats->r2M_to_44M_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_44M_to_1G_nsmr",
(u64)rsrc_stats->r44M_to_1G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_1G_to_4G_nsmr",
(u64)rsrc_stats->r1G_to_4G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_nsmr_count_4G_to_32G",
(u64)rsrc_stats->nsmr_count_4G_to_32G);
pcur += ocrdma_add_stat(stats, pcur, "threshold_32G_to_64G_nsmr",
(u64)rsrc_stats->r32G_to_64G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_64G_to_128G_nsmr",
(u64)rsrc_stats->r64G_to_128G_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_128G_to_higher_nsmr",
(u64)rsrc_stats->r128G_to_higher_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_embedded_nsmr",
(u64)rsrc_stats->embedded_nsmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_frmr",
(u64)rsrc_stats->frmr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_prefetch_qps",
(u64)rsrc_stats->prefetch_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_ondemand_qps",
(u64)rsrc_stats->ondemand_qps);
pcur += ocrdma_add_stat(stats, pcur, "threshold_phy_mr",
(u64)rsrc_stats->phy_mr);
pcur += ocrdma_add_stat(stats, pcur, "threshold_mw",
(u64)rsrc_stats->mw);
return stats;
}
static noinline_for_stack char *ocrdma_rx_stats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rx_stats *rx_stats = &rdma_stats->rx_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat
(stats, pcur, "roce_frame_bytes",
convert_to_64bit(rx_stats->roce_frame_bytes_lo,
rx_stats->roce_frame_bytes_hi));
pcur += ocrdma_add_stat(stats, pcur, "roce_frame_icrc_drops",
(u64)rx_stats->roce_frame_icrc_drops);
pcur += ocrdma_add_stat(stats, pcur, "roce_frame_payload_len_drops",
(u64)rx_stats->roce_frame_payload_len_drops);
pcur += ocrdma_add_stat(stats, pcur, "ud_drops",
(u64)rx_stats->ud_drops);
pcur += ocrdma_add_stat(stats, pcur, "qp1_drops",
(u64)rx_stats->qp1_drops);
pcur += ocrdma_add_stat(stats, pcur, "psn_error_request_packets",
(u64)rx_stats->psn_error_request_packets);
pcur += ocrdma_add_stat(stats, pcur, "psn_error_resp_packets",
(u64)rx_stats->psn_error_resp_packets);
pcur += ocrdma_add_stat(stats, pcur, "rnr_nak_timeouts",
(u64)rx_stats->rnr_nak_timeouts);
pcur += ocrdma_add_stat(stats, pcur, "rnr_nak_receives",
(u64)rx_stats->rnr_nak_receives);
pcur += ocrdma_add_stat(stats, pcur, "roce_frame_rxmt_drops",
(u64)rx_stats->roce_frame_rxmt_drops);
pcur += ocrdma_add_stat(stats, pcur, "nak_count_psn_sequence_errors",
(u64)rx_stats->nak_count_psn_sequence_errors);
pcur += ocrdma_add_stat(stats, pcur, "rc_drop_count_lookup_errors",
(u64)rx_stats->rc_drop_count_lookup_errors);
pcur += ocrdma_add_stat(stats, pcur, "rq_rnr_naks",
(u64)rx_stats->rq_rnr_naks);
pcur += ocrdma_add_stat(stats, pcur, "srq_rnr_naks",
(u64)rx_stats->srq_rnr_naks);
pcur += ocrdma_add_stat(stats, pcur, "roce_frames",
convert_to_64bit(rx_stats->roce_frames_lo,
rx_stats->roce_frames_hi));
return stats;
}
static u64 ocrdma_sysfs_rcv_pkts(struct ocrdma_dev *dev)
{
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rx_stats *rx_stats = &rdma_stats->rx_stats;
return convert_to_64bit(rx_stats->roce_frames_lo,
rx_stats->roce_frames_hi) + (u64)rx_stats->roce_frame_icrc_drops
+ (u64)rx_stats->roce_frame_payload_len_drops;
}
static u64 ocrdma_sysfs_rcv_data(struct ocrdma_dev *dev)
{
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rx_stats *rx_stats = &rdma_stats->rx_stats;
return (convert_to_64bit(rx_stats->roce_frame_bytes_lo,
rx_stats->roce_frame_bytes_hi))/4;
}
static noinline_for_stack char *ocrdma_tx_stats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_tx_stats *tx_stats = &rdma_stats->tx_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "send_pkts",
convert_to_64bit(tx_stats->send_pkts_lo,
tx_stats->send_pkts_hi));
pcur += ocrdma_add_stat(stats, pcur, "write_pkts",
convert_to_64bit(tx_stats->write_pkts_lo,
tx_stats->write_pkts_hi));
pcur += ocrdma_add_stat(stats, pcur, "read_pkts",
convert_to_64bit(tx_stats->read_pkts_lo,
tx_stats->read_pkts_hi));
pcur += ocrdma_add_stat(stats, pcur, "read_rsp_pkts",
convert_to_64bit(tx_stats->read_rsp_pkts_lo,
tx_stats->read_rsp_pkts_hi));
pcur += ocrdma_add_stat(stats, pcur, "ack_pkts",
convert_to_64bit(tx_stats->ack_pkts_lo,
tx_stats->ack_pkts_hi));
pcur += ocrdma_add_stat(stats, pcur, "send_bytes",
convert_to_64bit(tx_stats->send_bytes_lo,
tx_stats->send_bytes_hi));
pcur += ocrdma_add_stat(stats, pcur, "write_bytes",
convert_to_64bit(tx_stats->write_bytes_lo,
tx_stats->write_bytes_hi));
pcur += ocrdma_add_stat(stats, pcur, "read_req_bytes",
convert_to_64bit(tx_stats->read_req_bytes_lo,
tx_stats->read_req_bytes_hi));
pcur += ocrdma_add_stat(stats, pcur, "read_rsp_bytes",
convert_to_64bit(tx_stats->read_rsp_bytes_lo,
tx_stats->read_rsp_bytes_hi));
pcur += ocrdma_add_stat(stats, pcur, "ack_timeouts",
(u64)tx_stats->ack_timeouts);
return stats;
}
static u64 ocrdma_sysfs_xmit_pkts(struct ocrdma_dev *dev)
{
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_tx_stats *tx_stats = &rdma_stats->tx_stats;
return (convert_to_64bit(tx_stats->send_pkts_lo,
tx_stats->send_pkts_hi) +
convert_to_64bit(tx_stats->write_pkts_lo, tx_stats->write_pkts_hi) +
convert_to_64bit(tx_stats->read_pkts_lo, tx_stats->read_pkts_hi) +
convert_to_64bit(tx_stats->read_rsp_pkts_lo,
tx_stats->read_rsp_pkts_hi) +
convert_to_64bit(tx_stats->ack_pkts_lo, tx_stats->ack_pkts_hi));
}
static u64 ocrdma_sysfs_xmit_data(struct ocrdma_dev *dev)
{
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_tx_stats *tx_stats = &rdma_stats->tx_stats;
return (convert_to_64bit(tx_stats->send_bytes_lo,
tx_stats->send_bytes_hi) +
convert_to_64bit(tx_stats->write_bytes_lo,
tx_stats->write_bytes_hi) +
convert_to_64bit(tx_stats->read_req_bytes_lo,
tx_stats->read_req_bytes_hi) +
convert_to_64bit(tx_stats->read_rsp_bytes_lo,
tx_stats->read_rsp_bytes_hi))/4;
}
static noinline_for_stack char *ocrdma_wqe_stats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_wqe_stats *wqe_stats = &rdma_stats->wqe_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "large_send_rc_wqes",
convert_to_64bit(wqe_stats->large_send_rc_wqes_lo,
wqe_stats->large_send_rc_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "large_write_rc_wqes",
convert_to_64bit(wqe_stats->large_write_rc_wqes_lo,
wqe_stats->large_write_rc_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "read_wqes",
convert_to_64bit(wqe_stats->read_wqes_lo,
wqe_stats->read_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "frmr_wqes",
convert_to_64bit(wqe_stats->frmr_wqes_lo,
wqe_stats->frmr_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "mw_bind_wqes",
convert_to_64bit(wqe_stats->mw_bind_wqes_lo,
wqe_stats->mw_bind_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "invalidate_wqes",
convert_to_64bit(wqe_stats->invalidate_wqes_lo,
wqe_stats->invalidate_wqes_hi));
pcur += ocrdma_add_stat(stats, pcur, "dpp_wqe_drops",
(u64)wqe_stats->dpp_wqe_drops);
return stats;
}
static noinline_for_stack char *ocrdma_db_errstats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_db_err_stats *db_err_stats = &rdma_stats->db_err_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "sq_doorbell_errors",
(u64)db_err_stats->sq_doorbell_errors);
pcur += ocrdma_add_stat(stats, pcur, "cq_doorbell_errors",
(u64)db_err_stats->cq_doorbell_errors);
pcur += ocrdma_add_stat(stats, pcur, "rq_srq_doorbell_errors",
(u64)db_err_stats->rq_srq_doorbell_errors);
pcur += ocrdma_add_stat(stats, pcur, "cq_overflow_errors",
(u64)db_err_stats->cq_overflow_errors);
return stats;
}
static noinline_for_stack char *ocrdma_rxqp_errstats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rx_qp_err_stats *rx_qp_err_stats =
&rdma_stats->rx_qp_err_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "nak_invalid_request_errors",
(u64)rx_qp_err_stats->nak_invalid_request_errors);
pcur += ocrdma_add_stat(stats, pcur, "nak_remote_operation_errors",
(u64)rx_qp_err_stats->nak_remote_operation_errors);
pcur += ocrdma_add_stat(stats, pcur, "nak_count_remote_access_errors",
(u64)rx_qp_err_stats->nak_count_remote_access_errors);
pcur += ocrdma_add_stat(stats, pcur, "local_length_errors",
(u64)rx_qp_err_stats->local_length_errors);
pcur += ocrdma_add_stat(stats, pcur, "local_protection_errors",
(u64)rx_qp_err_stats->local_protection_errors);
pcur += ocrdma_add_stat(stats, pcur, "local_qp_operation_errors",
(u64)rx_qp_err_stats->local_qp_operation_errors);
return stats;
}
static noinline_for_stack char *ocrdma_txqp_errstats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_tx_qp_err_stats *tx_qp_err_stats =
&rdma_stats->tx_qp_err_stats;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "local_length_errors",
(u64)tx_qp_err_stats->local_length_errors);
pcur += ocrdma_add_stat(stats, pcur, "local_protection_errors",
(u64)tx_qp_err_stats->local_protection_errors);
pcur += ocrdma_add_stat(stats, pcur, "local_qp_operation_errors",
(u64)tx_qp_err_stats->local_qp_operation_errors);
pcur += ocrdma_add_stat(stats, pcur, "retry_count_exceeded_errors",
(u64)tx_qp_err_stats->retry_count_exceeded_errors);
pcur += ocrdma_add_stat(stats, pcur, "rnr_retry_count_exceeded_errors",
(u64)tx_qp_err_stats->rnr_retry_count_exceeded_errors);
return stats;
}
static noinline_for_stack char *ocrdma_tx_dbg_stats(struct ocrdma_dev *dev)
{
int i;
char *pstats = dev->stats_mem.debugfs_mem;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_tx_dbg_stats *tx_dbg_stats =
&rdma_stats->tx_dbg_stats;
memset(pstats, 0, (OCRDMA_MAX_DBGFS_MEM));
for (i = 0; i < 100; i++)
pstats += snprintf(pstats, 80, "DW[%d] = 0x%x\n", i,
tx_dbg_stats->data[i]);
return dev->stats_mem.debugfs_mem;
}
static noinline_for_stack char *ocrdma_rx_dbg_stats(struct ocrdma_dev *dev)
{
int i;
char *pstats = dev->stats_mem.debugfs_mem;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rx_dbg_stats *rx_dbg_stats =
&rdma_stats->rx_dbg_stats;
memset(pstats, 0, (OCRDMA_MAX_DBGFS_MEM));
for (i = 0; i < 200; i++)
pstats += snprintf(pstats, 80, "DW[%d] = 0x%x\n", i,
rx_dbg_stats->data[i]);
return dev->stats_mem.debugfs_mem;
}
static noinline_for_stack char *ocrdma_driver_dbg_stats(struct ocrdma_dev *dev)
{
char *stats = dev->stats_mem.debugfs_mem, *pcur;
memset(stats, 0, (OCRDMA_MAX_DBGFS_MEM));
pcur = stats;
pcur += ocrdma_add_stat(stats, pcur, "async_cq_err",
(u64)(dev->async_err_stats
[OCRDMA_CQ_ERROR].counter));
pcur += ocrdma_add_stat(stats, pcur, "async_cq_overrun_err",
(u64)dev->async_err_stats
[OCRDMA_CQ_OVERRUN_ERROR].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_cq_qpcat_err",
(u64)dev->async_err_stats
[OCRDMA_CQ_QPCAT_ERROR].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_qp_access_err",
(u64)dev->async_err_stats
[OCRDMA_QP_ACCESS_ERROR].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_qp_commm_est_evt",
(u64)dev->async_err_stats
[OCRDMA_QP_COMM_EST_EVENT].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_sq_drained_evt",
(u64)dev->async_err_stats
[OCRDMA_SQ_DRAINED_EVENT].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_dev_fatal_evt",
(u64)dev->async_err_stats
[OCRDMA_DEVICE_FATAL_EVENT].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_srqcat_err",
(u64)dev->async_err_stats
[OCRDMA_SRQCAT_ERROR].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_srq_limit_evt",
(u64)dev->async_err_stats
[OCRDMA_SRQ_LIMIT_EVENT].counter);
pcur += ocrdma_add_stat(stats, pcur, "async_qp_last_wqe_evt",
(u64)dev->async_err_stats
[OCRDMA_QP_LAST_WQE_EVENT].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_len_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_LEN_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_qp_op_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_QP_OP_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_eec_op_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_EEC_OP_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_prot_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_PROT_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_wr_flush_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_WR_FLUSH_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_mw_bind_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_MW_BIND_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_bad_resp_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_BAD_RESP_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_access_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_ACCESS_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rem_inv_req_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_REM_INV_REQ_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rem_access_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_REM_ACCESS_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rem_op_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_REM_OP_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_retry_exc_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_RETRY_EXC_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rnr_retry_exc_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_RNR_RETRY_EXC_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_loc_rdd_viol_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_LOC_RDD_VIOL_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rem_inv_rd_req_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_REM_INV_RD_REQ_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_rem_abort_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_REM_ABORT_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_inv_eecn_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_INV_EECN_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_inv_eec_state_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_INV_EEC_STATE_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_fatal_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_FATAL_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_resp_timeout_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_RESP_TIMEOUT_ERR].counter);
pcur += ocrdma_add_stat(stats, pcur, "cqe_general_err",
(u64)dev->cqe_err_stats
[OCRDMA_CQE_GENERAL_ERR].counter);
return stats;
}
static void ocrdma_update_stats(struct ocrdma_dev *dev)
{
ulong now = jiffies, secs;
int status;
struct ocrdma_rdma_stats_resp *rdma_stats =
(struct ocrdma_rdma_stats_resp *)dev->stats_mem.va;
struct ocrdma_rsrc_stats *rsrc_stats = &rdma_stats->act_rsrc_stats;
secs = jiffies_to_msecs(now - dev->last_stats_time) / 1000U;
if (secs) {
/* update */
status = ocrdma_mbx_rdma_stats(dev, false);
if (status)
pr_err("%s: stats mbox failed with status = %d\n",
__func__, status);
/* Update PD counters from PD resource manager */
if (dev->pd_mgr->pd_prealloc_valid) {
rsrc_stats->dpp_pds = dev->pd_mgr->pd_dpp_count;
rsrc_stats->non_dpp_pds = dev->pd_mgr->pd_norm_count;
/* Threshold stata*/
rsrc_stats = &rdma_stats->th_rsrc_stats;
rsrc_stats->dpp_pds = dev->pd_mgr->pd_dpp_thrsh;
rsrc_stats->non_dpp_pds = dev->pd_mgr->pd_norm_thrsh;
}
dev->last_stats_time = jiffies;
}
}
static ssize_t ocrdma_dbgfs_ops_write(struct file *filp,
const char __user *buffer,
size_t count, loff_t *ppos)
{
char tmp_str[32];
long reset;
int status;
struct ocrdma_stats *pstats = filp->private_data;
struct ocrdma_dev *dev = pstats->dev;
if (*ppos != 0 || count == 0 || count > sizeof(tmp_str))
goto err;
if (copy_from_user(tmp_str, buffer, count))
goto err;
tmp_str[count-1] = '\0';
if (kstrtol(tmp_str, 10, &reset))
goto err;
switch (pstats->type) {
case OCRDMA_RESET_STATS:
if (reset) {
status = ocrdma_mbx_rdma_stats(dev, true);
if (status) {
pr_err("Failed to reset stats = %d\n", status);
goto err;
}
}
break;
default:
goto err;
}
return count;
err:
return -EFAULT;
}
void ocrdma_pma_counters(struct ocrdma_dev *dev, struct ib_mad *out_mad)
{
struct ib_pma_portcounters *pma_cnt;
pma_cnt = (void *)(out_mad->data + 40);
ocrdma_update_stats(dev);
pma_cnt->port_xmit_data = cpu_to_be32(ocrdma_sysfs_xmit_data(dev));
pma_cnt->port_rcv_data = cpu_to_be32(ocrdma_sysfs_rcv_data(dev));
pma_cnt->port_xmit_packets = cpu_to_be32(ocrdma_sysfs_xmit_pkts(dev));
pma_cnt->port_rcv_packets = cpu_to_be32(ocrdma_sysfs_rcv_pkts(dev));
}
static ssize_t ocrdma_dbgfs_ops_read(struct file *filp, char __user *buffer,
size_t usr_buf_len, loff_t *ppos)
{
struct ocrdma_stats *pstats = filp->private_data;
struct ocrdma_dev *dev = pstats->dev;
ssize_t status = 0;
char *data = NULL;
/* No partial reads */
if (*ppos != 0)
return 0;
mutex_lock(&dev->stats_lock);
ocrdma_update_stats(dev);
switch (pstats->type) {
case OCRDMA_RSRC_STATS:
data = ocrdma_resource_stats(dev);
break;
case OCRDMA_RXSTATS:
data = ocrdma_rx_stats(dev);
break;
case OCRDMA_WQESTATS:
data = ocrdma_wqe_stats(dev);
break;
case OCRDMA_TXSTATS:
data = ocrdma_tx_stats(dev);
break;
case OCRDMA_DB_ERRSTATS:
data = ocrdma_db_errstats(dev);
break;
case OCRDMA_RXQP_ERRSTATS:
data = ocrdma_rxqp_errstats(dev);
break;
case OCRDMA_TXQP_ERRSTATS:
data = ocrdma_txqp_errstats(dev);
break;
case OCRDMA_TX_DBG_STATS:
data = ocrdma_tx_dbg_stats(dev);
break;
case OCRDMA_RX_DBG_STATS:
data = ocrdma_rx_dbg_stats(dev);
break;
case OCRDMA_DRV_STATS:
data = ocrdma_driver_dbg_stats(dev);
break;
default:
status = -EFAULT;
goto exit;
}
if (usr_buf_len < strlen(data)) {
status = -ENOSPC;
goto exit;
}
status = simple_read_from_buffer(buffer, usr_buf_len, ppos, data,
strlen(data));
exit:
mutex_unlock(&dev->stats_lock);
return status;
}
static const struct file_operations ocrdma_dbg_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = ocrdma_dbgfs_ops_read,
.write = ocrdma_dbgfs_ops_write,
};
void ocrdma_add_port_stats(struct ocrdma_dev *dev)
{
const struct pci_dev *pdev = dev->nic_info.pdev;
if (!ocrdma_dbgfs_dir)
return;
/* Create post stats base dir */
dev->dir = debugfs_create_dir(pci_name(pdev), ocrdma_dbgfs_dir);
dev->rsrc_stats.type = OCRDMA_RSRC_STATS;
dev->rsrc_stats.dev = dev;
debugfs_create_file("resource_stats", S_IRUSR, dev->dir,
&dev->rsrc_stats, &ocrdma_dbg_ops);
dev->rx_stats.type = OCRDMA_RXSTATS;
dev->rx_stats.dev = dev;
debugfs_create_file("rx_stats", S_IRUSR, dev->dir, &dev->rx_stats,
&ocrdma_dbg_ops);
dev->wqe_stats.type = OCRDMA_WQESTATS;
dev->wqe_stats.dev = dev;
debugfs_create_file("wqe_stats", S_IRUSR, dev->dir, &dev->wqe_stats,
&ocrdma_dbg_ops);
dev->tx_stats.type = OCRDMA_TXSTATS;
dev->tx_stats.dev = dev;
debugfs_create_file("tx_stats", S_IRUSR, dev->dir, &dev->tx_stats,
&ocrdma_dbg_ops);
dev->db_err_stats.type = OCRDMA_DB_ERRSTATS;
dev->db_err_stats.dev = dev;
debugfs_create_file("db_err_stats", S_IRUSR, dev->dir,
&dev->db_err_stats, &ocrdma_dbg_ops);
dev->tx_qp_err_stats.type = OCRDMA_TXQP_ERRSTATS;
dev->tx_qp_err_stats.dev = dev;
debugfs_create_file("tx_qp_err_stats", S_IRUSR, dev->dir,
&dev->tx_qp_err_stats, &ocrdma_dbg_ops);
dev->rx_qp_err_stats.type = OCRDMA_RXQP_ERRSTATS;
dev->rx_qp_err_stats.dev = dev;
debugfs_create_file("rx_qp_err_stats", S_IRUSR, dev->dir,
&dev->rx_qp_err_stats, &ocrdma_dbg_ops);
dev->tx_dbg_stats.type = OCRDMA_TX_DBG_STATS;
dev->tx_dbg_stats.dev = dev;
debugfs_create_file("tx_dbg_stats", S_IRUSR, dev->dir,
&dev->tx_dbg_stats, &ocrdma_dbg_ops);
dev->rx_dbg_stats.type = OCRDMA_RX_DBG_STATS;
dev->rx_dbg_stats.dev = dev;
debugfs_create_file("rx_dbg_stats", S_IRUSR, dev->dir,
&dev->rx_dbg_stats, &ocrdma_dbg_ops);
dev->driver_stats.type = OCRDMA_DRV_STATS;
dev->driver_stats.dev = dev;
debugfs_create_file("driver_dbg_stats", S_IRUSR, dev->dir,
&dev->driver_stats, &ocrdma_dbg_ops);
dev->reset_stats.type = OCRDMA_RESET_STATS;
dev->reset_stats.dev = dev;
debugfs_create_file("reset_stats", 0200, dev->dir, &dev->reset_stats,
&ocrdma_dbg_ops);
}
void ocrdma_rem_port_stats(struct ocrdma_dev *dev)
{
debugfs_remove_recursive(dev->dir);
}
void ocrdma_init_debugfs(void)
{
/* Create base dir in debugfs root dir */
ocrdma_dbgfs_dir = debugfs_create_dir("ocrdma", NULL);
}
void ocrdma_rem_debugfs(void)
{
debugfs_remove_recursive(ocrdma_dbgfs_dir);
}
@@ -0,0 +1,74 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef __OCRDMA_STATS_H__
#define __OCRDMA_STATS_H__
#include <linux/debugfs.h>
#include "ocrdma.h"
#include "ocrdma_hw.h"
#define OCRDMA_MAX_DBGFS_MEM 4096
enum OCRDMA_STATS_TYPE {
OCRDMA_RSRC_STATS,
OCRDMA_RXSTATS,
OCRDMA_WQESTATS,
OCRDMA_TXSTATS,
OCRDMA_DB_ERRSTATS,
OCRDMA_RXQP_ERRSTATS,
OCRDMA_TXQP_ERRSTATS,
OCRDMA_TX_DBG_STATS,
OCRDMA_RX_DBG_STATS,
OCRDMA_DRV_STATS,
OCRDMA_RESET_STATS
};
void ocrdma_rem_debugfs(void);
void ocrdma_init_debugfs(void);
bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev);
void ocrdma_release_stats_resources(struct ocrdma_dev *dev);
void ocrdma_rem_port_stats(struct ocrdma_dev *dev);
void ocrdma_add_port_stats(struct ocrdma_dev *dev);
void ocrdma_pma_counters(struct ocrdma_dev *dev, struct ib_mad *out_mad);
#endif /* __OCRDMA_STATS_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,108 @@
/* This file is part of the Emulex RoCE Device Driver for
* RoCE (RDMA over Converged Ethernet) adapters.
* Copyright (C) 2012-2015 Emulex. All rights reserved.
* EMULEX and SLI are trademarks of Emulex.
* www.emulex.com
*
* 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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contact Information:
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef __OCRDMA_VERBS_H__
#define __OCRDMA_VERBS_H__
int ocrdma_post_send(struct ib_qp *, const struct ib_send_wr *,
const struct ib_send_wr **bad_wr);
int ocrdma_post_recv(struct ib_qp *, const struct ib_recv_wr *,
const struct ib_recv_wr **bad_wr);
int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc);
int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags);
int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props,
struct ib_udata *uhw);
int ocrdma_query_port(struct ib_device *ibdev, u32 port,
struct ib_port_attr *props);
enum rdma_protocol_type
ocrdma_query_protocol(struct ib_device *device, u32 port_num);
int ocrdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey);
int ocrdma_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
void ocrdma_dealloc_ucontext(struct ib_ucontext *uctx);
int ocrdma_mmap(struct ib_ucontext *, struct vm_area_struct *vma);
int ocrdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
int ocrdma_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
int ocrdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs);
int ocrdma_resize_cq(struct ib_cq *, unsigned int cqe, struct ib_udata *);
int ocrdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
int ocrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
struct ib_udata *udata);
int _ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
int attr_mask);
int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int ocrdma_query_qp(struct ib_qp *,
struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_qp_init_attr *);
int ocrdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
void ocrdma_del_flush_qp(struct ocrdma_qp *qp);
int ocrdma_create_srq(struct ib_srq *srq, struct ib_srq_init_attr *attr,
struct ib_udata *udata);
int ocrdma_modify_srq(struct ib_srq *, struct ib_srq_attr *,
enum ib_srq_attr_mask, struct ib_udata *);
int ocrdma_query_srq(struct ib_srq *, struct ib_srq_attr *);
int ocrdma_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata);
int ocrdma_post_srq_recv(struct ib_srq *, const struct ib_recv_wr *,
const struct ib_recv_wr **bad_recv_wr);
int ocrdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
struct ib_mr *ocrdma_get_dma_mr(struct ib_pd *, int acc);
struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length,
u64 virt, int acc, struct ib_dmah *dmah,
struct ib_udata *);
struct ib_mr *ocrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
u32 max_num_sg);
int ocrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
unsigned int *sg_offset);
#endif /* __OCRDMA_VERBS_H__ */