mirror of
https://github.com/torvalds/linux.git
synced 2025-11-01 00:58:39 +02:00
Implement device stats operations for hw stats and qp stats. Co-developed-by: Allen Hubbe <allen.hubbe@amd.com> Signed-off-by: Allen Hubbe <allen.hubbe@amd.com> Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com> Link: https://patch.msgid.link/20250903061606.4139957-14-abhijit.gangurde@amd.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
1029 lines
23 KiB
C
1029 lines
23 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
|
|
|
|
#ifndef _IONIC_FW_H_
|
|
#define _IONIC_FW_H_
|
|
|
|
#include <linux/kernel.h>
|
|
#include <rdma/ib_verbs.h>
|
|
|
|
/* common for ib spec */
|
|
|
|
#define IONIC_EXP_DBELL_SZ 8
|
|
|
|
enum ionic_mrid_bits {
|
|
IONIC_MRID_INDEX_SHIFT = 8,
|
|
};
|
|
|
|
static inline u32 ionic_mrid(u32 index, u8 key)
|
|
{
|
|
return (index << IONIC_MRID_INDEX_SHIFT) | key;
|
|
}
|
|
|
|
static inline u32 ionic_mrid_index(u32 lrkey)
|
|
{
|
|
return lrkey >> IONIC_MRID_INDEX_SHIFT;
|
|
}
|
|
|
|
/* common to all versions */
|
|
|
|
/* wqe scatter gather element */
|
|
struct ionic_sge {
|
|
__be64 va;
|
|
__be32 len;
|
|
__be32 lkey;
|
|
};
|
|
|
|
/* admin queue mr type */
|
|
enum ionic_mr_flags {
|
|
/* bits that determine mr access */
|
|
IONIC_MRF_LOCAL_WRITE = BIT(0),
|
|
IONIC_MRF_REMOTE_WRITE = BIT(1),
|
|
IONIC_MRF_REMOTE_READ = BIT(2),
|
|
IONIC_MRF_REMOTE_ATOMIC = BIT(3),
|
|
IONIC_MRF_MW_BIND = BIT(4),
|
|
IONIC_MRF_ZERO_BASED = BIT(5),
|
|
IONIC_MRF_ON_DEMAND = BIT(6),
|
|
IONIC_MRF_PB = BIT(7),
|
|
IONIC_MRF_ACCESS_MASK = BIT(12) - 1,
|
|
|
|
/* bits that determine mr type */
|
|
IONIC_MRF_UKEY_EN = BIT(13),
|
|
IONIC_MRF_IS_MW = BIT(14),
|
|
IONIC_MRF_INV_EN = BIT(15),
|
|
|
|
/* base flags combinations for mr types */
|
|
IONIC_MRF_USER_MR = 0,
|
|
IONIC_MRF_PHYS_MR = (IONIC_MRF_UKEY_EN |
|
|
IONIC_MRF_INV_EN),
|
|
IONIC_MRF_MW_1 = (IONIC_MRF_UKEY_EN |
|
|
IONIC_MRF_IS_MW),
|
|
IONIC_MRF_MW_2 = (IONIC_MRF_UKEY_EN |
|
|
IONIC_MRF_IS_MW |
|
|
IONIC_MRF_INV_EN),
|
|
};
|
|
|
|
static inline int to_ionic_mr_flags(int access)
|
|
{
|
|
int flags = 0;
|
|
|
|
if (access & IB_ACCESS_LOCAL_WRITE)
|
|
flags |= IONIC_MRF_LOCAL_WRITE;
|
|
|
|
if (access & IB_ACCESS_REMOTE_READ)
|
|
flags |= IONIC_MRF_REMOTE_READ;
|
|
|
|
if (access & IB_ACCESS_REMOTE_WRITE)
|
|
flags |= IONIC_MRF_REMOTE_WRITE;
|
|
|
|
if (access & IB_ACCESS_REMOTE_ATOMIC)
|
|
flags |= IONIC_MRF_REMOTE_ATOMIC;
|
|
|
|
if (access & IB_ACCESS_MW_BIND)
|
|
flags |= IONIC_MRF_MW_BIND;
|
|
|
|
if (access & IB_ZERO_BASED)
|
|
flags |= IONIC_MRF_ZERO_BASED;
|
|
|
|
return flags;
|
|
}
|
|
|
|
enum ionic_qp_flags {
|
|
/* bits that determine qp access */
|
|
IONIC_QPF_REMOTE_WRITE = BIT(0),
|
|
IONIC_QPF_REMOTE_READ = BIT(1),
|
|
IONIC_QPF_REMOTE_ATOMIC = BIT(2),
|
|
|
|
/* bits that determine other qp behavior */
|
|
IONIC_QPF_SQ_PB = BIT(6),
|
|
IONIC_QPF_RQ_PB = BIT(7),
|
|
IONIC_QPF_SQ_SPEC = BIT(8),
|
|
IONIC_QPF_RQ_SPEC = BIT(9),
|
|
IONIC_QPF_REMOTE_PRIVILEGED = BIT(10),
|
|
IONIC_QPF_SQ_DRAINING = BIT(11),
|
|
IONIC_QPF_SQD_NOTIFY = BIT(12),
|
|
IONIC_QPF_SQ_CMB = BIT(13),
|
|
IONIC_QPF_RQ_CMB = BIT(14),
|
|
IONIC_QPF_PRIVILEGED = BIT(15),
|
|
};
|
|
|
|
static inline int from_ionic_qp_flags(int flags)
|
|
{
|
|
int access_flags = 0;
|
|
|
|
if (flags & IONIC_QPF_REMOTE_WRITE)
|
|
access_flags |= IB_ACCESS_REMOTE_WRITE;
|
|
|
|
if (flags & IONIC_QPF_REMOTE_READ)
|
|
access_flags |= IB_ACCESS_REMOTE_READ;
|
|
|
|
if (flags & IONIC_QPF_REMOTE_ATOMIC)
|
|
access_flags |= IB_ACCESS_REMOTE_ATOMIC;
|
|
|
|
return access_flags;
|
|
}
|
|
|
|
static inline int to_ionic_qp_flags(int access, bool sqd_notify,
|
|
bool sq_is_cmb, bool rq_is_cmb,
|
|
bool sq_spec, bool rq_spec,
|
|
bool privileged, bool remote_privileged)
|
|
{
|
|
int flags = 0;
|
|
|
|
if (access & IB_ACCESS_REMOTE_WRITE)
|
|
flags |= IONIC_QPF_REMOTE_WRITE;
|
|
|
|
if (access & IB_ACCESS_REMOTE_READ)
|
|
flags |= IONIC_QPF_REMOTE_READ;
|
|
|
|
if (access & IB_ACCESS_REMOTE_ATOMIC)
|
|
flags |= IONIC_QPF_REMOTE_ATOMIC;
|
|
|
|
if (sqd_notify)
|
|
flags |= IONIC_QPF_SQD_NOTIFY;
|
|
|
|
if (sq_is_cmb)
|
|
flags |= IONIC_QPF_SQ_CMB;
|
|
|
|
if (rq_is_cmb)
|
|
flags |= IONIC_QPF_RQ_CMB;
|
|
|
|
if (sq_spec)
|
|
flags |= IONIC_QPF_SQ_SPEC;
|
|
|
|
if (rq_spec)
|
|
flags |= IONIC_QPF_RQ_SPEC;
|
|
|
|
if (privileged)
|
|
flags |= IONIC_QPF_PRIVILEGED;
|
|
|
|
if (remote_privileged)
|
|
flags |= IONIC_QPF_REMOTE_PRIVILEGED;
|
|
|
|
return flags;
|
|
}
|
|
|
|
/* cqe non-admin status indicated in status_length field when err bit is set */
|
|
enum ionic_status {
|
|
IONIC_STS_OK,
|
|
IONIC_STS_LOCAL_LEN_ERR,
|
|
IONIC_STS_LOCAL_QP_OPER_ERR,
|
|
IONIC_STS_LOCAL_PROT_ERR,
|
|
IONIC_STS_WQE_FLUSHED_ERR,
|
|
IONIC_STS_MEM_MGMT_OPER_ERR,
|
|
IONIC_STS_BAD_RESP_ERR,
|
|
IONIC_STS_LOCAL_ACC_ERR,
|
|
IONIC_STS_REMOTE_INV_REQ_ERR,
|
|
IONIC_STS_REMOTE_ACC_ERR,
|
|
IONIC_STS_REMOTE_OPER_ERR,
|
|
IONIC_STS_RETRY_EXCEEDED,
|
|
IONIC_STS_RNR_RETRY_EXCEEDED,
|
|
IONIC_STS_XRC_VIO_ERR,
|
|
IONIC_STS_LOCAL_SGL_INV_ERR,
|
|
};
|
|
|
|
static inline int ionic_to_ib_status(int sts)
|
|
{
|
|
switch (sts) {
|
|
case IONIC_STS_OK:
|
|
return IB_WC_SUCCESS;
|
|
case IONIC_STS_LOCAL_LEN_ERR:
|
|
return IB_WC_LOC_LEN_ERR;
|
|
case IONIC_STS_LOCAL_QP_OPER_ERR:
|
|
case IONIC_STS_LOCAL_SGL_INV_ERR:
|
|
return IB_WC_LOC_QP_OP_ERR;
|
|
case IONIC_STS_LOCAL_PROT_ERR:
|
|
return IB_WC_LOC_PROT_ERR;
|
|
case IONIC_STS_WQE_FLUSHED_ERR:
|
|
return IB_WC_WR_FLUSH_ERR;
|
|
case IONIC_STS_MEM_MGMT_OPER_ERR:
|
|
return IB_WC_MW_BIND_ERR;
|
|
case IONIC_STS_BAD_RESP_ERR:
|
|
return IB_WC_BAD_RESP_ERR;
|
|
case IONIC_STS_LOCAL_ACC_ERR:
|
|
return IB_WC_LOC_ACCESS_ERR;
|
|
case IONIC_STS_REMOTE_INV_REQ_ERR:
|
|
return IB_WC_REM_INV_REQ_ERR;
|
|
case IONIC_STS_REMOTE_ACC_ERR:
|
|
return IB_WC_REM_ACCESS_ERR;
|
|
case IONIC_STS_REMOTE_OPER_ERR:
|
|
return IB_WC_REM_OP_ERR;
|
|
case IONIC_STS_RETRY_EXCEEDED:
|
|
return IB_WC_RETRY_EXC_ERR;
|
|
case IONIC_STS_RNR_RETRY_EXCEEDED:
|
|
return IB_WC_RNR_RETRY_EXC_ERR;
|
|
case IONIC_STS_XRC_VIO_ERR:
|
|
default:
|
|
return IB_WC_GENERAL_ERR;
|
|
}
|
|
}
|
|
|
|
/* admin queue qp type */
|
|
enum ionic_qp_type {
|
|
IONIC_QPT_RC,
|
|
IONIC_QPT_UC,
|
|
IONIC_QPT_RD,
|
|
IONIC_QPT_UD,
|
|
IONIC_QPT_SRQ,
|
|
IONIC_QPT_XRC_INI,
|
|
IONIC_QPT_XRC_TGT,
|
|
IONIC_QPT_XRC_SRQ,
|
|
};
|
|
|
|
static inline int to_ionic_qp_type(enum ib_qp_type type)
|
|
{
|
|
switch (type) {
|
|
case IB_QPT_GSI:
|
|
case IB_QPT_UD:
|
|
return IONIC_QPT_UD;
|
|
case IB_QPT_RC:
|
|
return IONIC_QPT_RC;
|
|
case IB_QPT_UC:
|
|
return IONIC_QPT_UC;
|
|
case IB_QPT_XRC_INI:
|
|
return IONIC_QPT_XRC_INI;
|
|
case IB_QPT_XRC_TGT:
|
|
return IONIC_QPT_XRC_TGT;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
/* admin queue qp state */
|
|
enum ionic_qp_state {
|
|
IONIC_QPS_RESET,
|
|
IONIC_QPS_INIT,
|
|
IONIC_QPS_RTR,
|
|
IONIC_QPS_RTS,
|
|
IONIC_QPS_SQD,
|
|
IONIC_QPS_SQE,
|
|
IONIC_QPS_ERR,
|
|
};
|
|
|
|
static inline int from_ionic_qp_state(enum ionic_qp_state state)
|
|
{
|
|
switch (state) {
|
|
case IONIC_QPS_RESET:
|
|
return IB_QPS_RESET;
|
|
case IONIC_QPS_INIT:
|
|
return IB_QPS_INIT;
|
|
case IONIC_QPS_RTR:
|
|
return IB_QPS_RTR;
|
|
case IONIC_QPS_RTS:
|
|
return IB_QPS_RTS;
|
|
case IONIC_QPS_SQD:
|
|
return IB_QPS_SQD;
|
|
case IONIC_QPS_SQE:
|
|
return IB_QPS_SQE;
|
|
case IONIC_QPS_ERR:
|
|
return IB_QPS_ERR;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline int to_ionic_qp_state(enum ib_qp_state state)
|
|
{
|
|
switch (state) {
|
|
case IB_QPS_RESET:
|
|
return IONIC_QPS_RESET;
|
|
case IB_QPS_INIT:
|
|
return IONIC_QPS_INIT;
|
|
case IB_QPS_RTR:
|
|
return IONIC_QPS_RTR;
|
|
case IB_QPS_RTS:
|
|
return IONIC_QPS_RTS;
|
|
case IB_QPS_SQD:
|
|
return IONIC_QPS_SQD;
|
|
case IB_QPS_SQE:
|
|
return IONIC_QPS_SQE;
|
|
case IB_QPS_ERR:
|
|
return IONIC_QPS_ERR;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline int to_ionic_qp_modify_state(enum ib_qp_state to_state,
|
|
enum ib_qp_state from_state)
|
|
{
|
|
return to_ionic_qp_state(to_state) |
|
|
(to_ionic_qp_state(from_state) << 4);
|
|
}
|
|
|
|
/* fw abi v1 */
|
|
|
|
/* data payload part of v1 wqe */
|
|
union ionic_v1_pld {
|
|
struct ionic_sge sgl[2];
|
|
__be32 spec32[8];
|
|
__be16 spec16[16];
|
|
__u8 data[32];
|
|
};
|
|
|
|
/* completion queue v1 cqe */
|
|
struct ionic_v1_cqe {
|
|
union {
|
|
struct {
|
|
__be16 cmd_idx;
|
|
__u8 cmd_op;
|
|
__u8 rsvd[17];
|
|
__le16 old_sq_cindex;
|
|
__le16 old_rq_cq_cindex;
|
|
} admin;
|
|
struct {
|
|
__u64 wqe_id;
|
|
__be32 src_qpn_op;
|
|
__u8 src_mac[6];
|
|
__be16 vlan_tag;
|
|
__be32 imm_data_rkey;
|
|
} recv;
|
|
struct {
|
|
__u8 rsvd[4];
|
|
__be32 msg_msn;
|
|
__u8 rsvd2[8];
|
|
__u64 npg_wqe_id;
|
|
} send;
|
|
};
|
|
__be32 status_length;
|
|
__be32 qid_type_flags;
|
|
};
|
|
|
|
/* bits for cqe recv */
|
|
enum ionic_v1_cqe_src_qpn_bits {
|
|
IONIC_V1_CQE_RECV_QPN_MASK = 0xffffff,
|
|
IONIC_V1_CQE_RECV_OP_SHIFT = 24,
|
|
|
|
/* MASK could be 0x3, but need 0x1f for makeshift values:
|
|
* OP_TYPE_RDMA_OPER_WITH_IMM, OP_TYPE_SEND_RCVD
|
|
*/
|
|
IONIC_V1_CQE_RECV_OP_MASK = 0x1f,
|
|
IONIC_V1_CQE_RECV_OP_SEND = 0,
|
|
IONIC_V1_CQE_RECV_OP_SEND_INV = 1,
|
|
IONIC_V1_CQE_RECV_OP_SEND_IMM = 2,
|
|
IONIC_V1_CQE_RECV_OP_RDMA_IMM = 3,
|
|
|
|
IONIC_V1_CQE_RECV_IS_IPV4 = BIT(7 + IONIC_V1_CQE_RECV_OP_SHIFT),
|
|
IONIC_V1_CQE_RECV_IS_VLAN = BIT(6 + IONIC_V1_CQE_RECV_OP_SHIFT),
|
|
};
|
|
|
|
/* bits for cqe qid_type_flags */
|
|
enum ionic_v1_cqe_qtf_bits {
|
|
IONIC_V1_CQE_COLOR = BIT(0),
|
|
IONIC_V1_CQE_ERROR = BIT(1),
|
|
IONIC_V1_CQE_TYPE_SHIFT = 5,
|
|
IONIC_V1_CQE_TYPE_MASK = 0x7,
|
|
IONIC_V1_CQE_QID_SHIFT = 8,
|
|
|
|
IONIC_V1_CQE_TYPE_ADMIN = 0,
|
|
IONIC_V1_CQE_TYPE_RECV = 1,
|
|
IONIC_V1_CQE_TYPE_SEND_MSN = 2,
|
|
IONIC_V1_CQE_TYPE_SEND_NPG = 3,
|
|
};
|
|
|
|
static inline bool ionic_v1_cqe_color(struct ionic_v1_cqe *cqe)
|
|
{
|
|
return cqe->qid_type_flags & cpu_to_be32(IONIC_V1_CQE_COLOR);
|
|
}
|
|
|
|
static inline bool ionic_v1_cqe_error(struct ionic_v1_cqe *cqe)
|
|
{
|
|
return cqe->qid_type_flags & cpu_to_be32(IONIC_V1_CQE_ERROR);
|
|
}
|
|
|
|
static inline bool ionic_v1_cqe_recv_is_ipv4(struct ionic_v1_cqe *cqe)
|
|
{
|
|
return cqe->recv.src_qpn_op & cpu_to_be32(IONIC_V1_CQE_RECV_IS_IPV4);
|
|
}
|
|
|
|
static inline bool ionic_v1_cqe_recv_is_vlan(struct ionic_v1_cqe *cqe)
|
|
{
|
|
return cqe->recv.src_qpn_op & cpu_to_be32(IONIC_V1_CQE_RECV_IS_VLAN);
|
|
}
|
|
|
|
static inline void ionic_v1_cqe_clean(struct ionic_v1_cqe *cqe)
|
|
{
|
|
cqe->qid_type_flags |= cpu_to_be32(~0u << IONIC_V1_CQE_QID_SHIFT);
|
|
}
|
|
|
|
static inline u32 ionic_v1_cqe_qtf(struct ionic_v1_cqe *cqe)
|
|
{
|
|
return be32_to_cpu(cqe->qid_type_flags);
|
|
}
|
|
|
|
static inline u8 ionic_v1_cqe_qtf_type(u32 qtf)
|
|
{
|
|
return (qtf >> IONIC_V1_CQE_TYPE_SHIFT) & IONIC_V1_CQE_TYPE_MASK;
|
|
}
|
|
|
|
static inline u32 ionic_v1_cqe_qtf_qid(u32 qtf)
|
|
{
|
|
return qtf >> IONIC_V1_CQE_QID_SHIFT;
|
|
}
|
|
|
|
/* v1 base wqe header */
|
|
struct ionic_v1_base_hdr {
|
|
__u64 wqe_id;
|
|
__u8 op;
|
|
__u8 num_sge_key;
|
|
__be16 flags;
|
|
__be32 imm_data_key;
|
|
};
|
|
|
|
/* v1 receive wqe body */
|
|
struct ionic_v1_recv_bdy {
|
|
__u8 rsvd[16];
|
|
union ionic_v1_pld pld;
|
|
};
|
|
|
|
/* v1 send/rdma wqe body (common, has sgl) */
|
|
struct ionic_v1_common_bdy {
|
|
union {
|
|
struct {
|
|
__be32 ah_id;
|
|
__be32 dest_qpn;
|
|
__be32 dest_qkey;
|
|
} send;
|
|
struct {
|
|
__be32 remote_va_high;
|
|
__be32 remote_va_low;
|
|
__be32 remote_rkey;
|
|
} rdma;
|
|
};
|
|
__be32 length;
|
|
union ionic_v1_pld pld;
|
|
};
|
|
|
|
/* v1 atomic wqe body */
|
|
struct ionic_v1_atomic_bdy {
|
|
__be32 remote_va_high;
|
|
__be32 remote_va_low;
|
|
__be32 remote_rkey;
|
|
__be32 swap_add_high;
|
|
__be32 swap_add_low;
|
|
__be32 compare_high;
|
|
__be32 compare_low;
|
|
__u8 rsvd[4];
|
|
struct ionic_sge sge;
|
|
};
|
|
|
|
/* v1 reg mr wqe body */
|
|
struct ionic_v1_reg_mr_bdy {
|
|
__be64 va;
|
|
__be64 length;
|
|
__be64 offset;
|
|
__be64 dma_addr;
|
|
__be32 map_count;
|
|
__be16 flags;
|
|
__u8 dir_size_log2;
|
|
__u8 page_size_log2;
|
|
__u8 rsvd[8];
|
|
};
|
|
|
|
/* v1 bind mw wqe body */
|
|
struct ionic_v1_bind_mw_bdy {
|
|
__be64 va;
|
|
__be64 length;
|
|
__be32 lkey;
|
|
__be16 flags;
|
|
__u8 rsvd[26];
|
|
};
|
|
|
|
/* v1 send/recv wqe */
|
|
struct ionic_v1_wqe {
|
|
struct ionic_v1_base_hdr base;
|
|
union {
|
|
struct ionic_v1_recv_bdy recv;
|
|
struct ionic_v1_common_bdy common;
|
|
struct ionic_v1_atomic_bdy atomic;
|
|
struct ionic_v1_reg_mr_bdy reg_mr;
|
|
struct ionic_v1_bind_mw_bdy bind_mw;
|
|
};
|
|
};
|
|
|
|
/* queue pair v1 send opcodes */
|
|
enum ionic_v1_op {
|
|
IONIC_V1_OP_SEND,
|
|
IONIC_V1_OP_SEND_INV,
|
|
IONIC_V1_OP_SEND_IMM,
|
|
IONIC_V1_OP_RDMA_READ,
|
|
IONIC_V1_OP_RDMA_WRITE,
|
|
IONIC_V1_OP_RDMA_WRITE_IMM,
|
|
IONIC_V1_OP_ATOMIC_CS,
|
|
IONIC_V1_OP_ATOMIC_FA,
|
|
IONIC_V1_OP_REG_MR,
|
|
IONIC_V1_OP_LOCAL_INV,
|
|
IONIC_V1_OP_BIND_MW,
|
|
|
|
/* flags */
|
|
IONIC_V1_FLAG_FENCE = BIT(0),
|
|
IONIC_V1_FLAG_SOL = BIT(1),
|
|
IONIC_V1_FLAG_INL = BIT(2),
|
|
IONIC_V1_FLAG_SIG = BIT(3),
|
|
|
|
/* flags last four bits for sgl spec format */
|
|
IONIC_V1_FLAG_SPEC32 = (1u << 12),
|
|
IONIC_V1_FLAG_SPEC16 = (2u << 12),
|
|
IONIC_V1_SPEC_FIRST_SGE = 2,
|
|
};
|
|
|
|
/* queue pair v2 send opcodes */
|
|
enum ionic_v2_op {
|
|
IONIC_V2_OPSL_OUT = 0x20,
|
|
IONIC_V2_OPSL_IMM = 0x40,
|
|
IONIC_V2_OPSL_INV = 0x80,
|
|
|
|
IONIC_V2_OP_SEND = 0x0 | IONIC_V2_OPSL_OUT,
|
|
IONIC_V2_OP_SEND_IMM = IONIC_V2_OP_SEND | IONIC_V2_OPSL_IMM,
|
|
IONIC_V2_OP_SEND_INV = IONIC_V2_OP_SEND | IONIC_V2_OPSL_INV,
|
|
|
|
IONIC_V2_OP_RDMA_WRITE = 0x1 | IONIC_V2_OPSL_OUT,
|
|
IONIC_V2_OP_RDMA_WRITE_IMM = IONIC_V2_OP_RDMA_WRITE | IONIC_V2_OPSL_IMM,
|
|
|
|
IONIC_V2_OP_RDMA_READ = 0x2,
|
|
|
|
IONIC_V2_OP_ATOMIC_CS = 0x4,
|
|
IONIC_V2_OP_ATOMIC_FA = 0x5,
|
|
IONIC_V2_OP_REG_MR = 0x6,
|
|
IONIC_V2_OP_LOCAL_INV = 0x7,
|
|
IONIC_V2_OP_BIND_MW = 0x8,
|
|
};
|
|
|
|
static inline size_t ionic_v1_send_wqe_min_size(int min_sge, int min_data,
|
|
int spec, bool expdb)
|
|
{
|
|
size_t sz_wqe, sz_sgl, sz_data;
|
|
|
|
if (spec > IONIC_V1_SPEC_FIRST_SGE)
|
|
min_sge += IONIC_V1_SPEC_FIRST_SGE;
|
|
|
|
if (expdb) {
|
|
min_sge += 1;
|
|
min_data += IONIC_EXP_DBELL_SZ;
|
|
}
|
|
|
|
sz_wqe = sizeof(struct ionic_v1_wqe);
|
|
sz_sgl = offsetof(struct ionic_v1_wqe, common.pld.sgl[min_sge]);
|
|
sz_data = offsetof(struct ionic_v1_wqe, common.pld.data[min_data]);
|
|
|
|
if (sz_sgl > sz_wqe)
|
|
sz_wqe = sz_sgl;
|
|
|
|
if (sz_data > sz_wqe)
|
|
sz_wqe = sz_data;
|
|
|
|
return sz_wqe;
|
|
}
|
|
|
|
static inline int ionic_v1_send_wqe_max_sge(u8 stride_log2, int spec,
|
|
bool expdb)
|
|
{
|
|
struct ionic_sge *sge = (void *)(1ull << stride_log2);
|
|
struct ionic_v1_wqe *wqe = (void *)0;
|
|
int num_sge = 0;
|
|
|
|
if (expdb)
|
|
sge -= 1;
|
|
|
|
if (spec > IONIC_V1_SPEC_FIRST_SGE)
|
|
num_sge = IONIC_V1_SPEC_FIRST_SGE;
|
|
|
|
num_sge = sge - &wqe->common.pld.sgl[num_sge];
|
|
|
|
if (spec && num_sge > spec)
|
|
num_sge = spec;
|
|
|
|
return num_sge;
|
|
}
|
|
|
|
static inline int ionic_v1_send_wqe_max_data(u8 stride_log2, bool expdb)
|
|
{
|
|
struct ionic_v1_wqe *wqe = (void *)0;
|
|
__u8 *data = (void *)(1ull << stride_log2);
|
|
|
|
if (expdb)
|
|
data -= IONIC_EXP_DBELL_SZ;
|
|
|
|
return data - wqe->common.pld.data;
|
|
}
|
|
|
|
static inline size_t ionic_v1_recv_wqe_min_size(int min_sge, int spec,
|
|
bool expdb)
|
|
{
|
|
size_t sz_wqe, sz_sgl;
|
|
|
|
if (spec > IONIC_V1_SPEC_FIRST_SGE)
|
|
min_sge += IONIC_V1_SPEC_FIRST_SGE;
|
|
|
|
if (expdb)
|
|
min_sge += 1;
|
|
|
|
sz_wqe = sizeof(struct ionic_v1_wqe);
|
|
sz_sgl = offsetof(struct ionic_v1_wqe, recv.pld.sgl[min_sge]);
|
|
|
|
if (sz_sgl > sz_wqe)
|
|
sz_wqe = sz_sgl;
|
|
|
|
return sz_wqe;
|
|
}
|
|
|
|
static inline int ionic_v1_recv_wqe_max_sge(u8 stride_log2, int spec,
|
|
bool expdb)
|
|
{
|
|
struct ionic_sge *sge = (void *)(1ull << stride_log2);
|
|
struct ionic_v1_wqe *wqe = (void *)0;
|
|
int num_sge = 0;
|
|
|
|
if (expdb)
|
|
sge -= 1;
|
|
|
|
if (spec > IONIC_V1_SPEC_FIRST_SGE)
|
|
num_sge = IONIC_V1_SPEC_FIRST_SGE;
|
|
|
|
num_sge = sge - &wqe->recv.pld.sgl[num_sge];
|
|
|
|
if (spec && num_sge > spec)
|
|
num_sge = spec;
|
|
|
|
return num_sge;
|
|
}
|
|
|
|
static inline int ionic_v1_use_spec_sge(int min_sge, int spec)
|
|
{
|
|
if (!spec || min_sge > spec)
|
|
return 0;
|
|
|
|
if (min_sge <= IONIC_V1_SPEC_FIRST_SGE)
|
|
return IONIC_V1_SPEC_FIRST_SGE;
|
|
|
|
return spec;
|
|
}
|
|
|
|
struct ionic_admin_stats_hdr {
|
|
__le64 dma_addr;
|
|
__le32 length;
|
|
__le32 id_ver;
|
|
__u8 type_state;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_STATS_HDRS_IN_V1_LEN 17
|
|
static_assert(sizeof(struct ionic_admin_stats_hdr) ==
|
|
IONIC_ADMIN_STATS_HDRS_IN_V1_LEN);
|
|
|
|
struct ionic_admin_create_ah {
|
|
__le64 dma_addr;
|
|
__le32 length;
|
|
__le32 pd_id;
|
|
__le32 id_ver;
|
|
__le16 dbid_flags;
|
|
__u8 csum_profile;
|
|
__u8 crypto;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_CREATE_AH_IN_V1_LEN 24
|
|
static_assert(sizeof(struct ionic_admin_create_ah) ==
|
|
IONIC_ADMIN_CREATE_AH_IN_V1_LEN);
|
|
|
|
struct ionic_admin_destroy_ah {
|
|
__le32 ah_id;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_DESTROY_AH_IN_V1_LEN 4
|
|
static_assert(sizeof(struct ionic_admin_destroy_ah) ==
|
|
IONIC_ADMIN_DESTROY_AH_IN_V1_LEN);
|
|
|
|
struct ionic_admin_query_ah {
|
|
__le64 dma_addr;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_QUERY_AH_IN_V1_LEN 8
|
|
static_assert(sizeof(struct ionic_admin_query_ah) ==
|
|
IONIC_ADMIN_QUERY_AH_IN_V1_LEN);
|
|
|
|
struct ionic_admin_create_mr {
|
|
__le64 va;
|
|
__le64 length;
|
|
__le32 pd_id;
|
|
__le32 id_ver;
|
|
__le32 tbl_index;
|
|
__le32 map_count;
|
|
__le64 dma_addr;
|
|
__le16 dbid_flags;
|
|
__u8 pt_type;
|
|
__u8 dir_size_log2;
|
|
__u8 page_size_log2;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_CREATE_MR_IN_V1_LEN 45
|
|
static_assert(sizeof(struct ionic_admin_create_mr) ==
|
|
IONIC_ADMIN_CREATE_MR_IN_V1_LEN);
|
|
|
|
struct ionic_admin_destroy_mr {
|
|
__le32 mr_id;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_DESTROY_MR_IN_V1_LEN 4
|
|
static_assert(sizeof(struct ionic_admin_destroy_mr) ==
|
|
IONIC_ADMIN_DESTROY_MR_IN_V1_LEN);
|
|
|
|
struct ionic_admin_create_cq {
|
|
__le32 eq_id;
|
|
__u8 depth_log2;
|
|
__u8 stride_log2;
|
|
__u8 dir_size_log2_rsvd;
|
|
__u8 page_size_log2;
|
|
__le32 cq_flags;
|
|
__le32 id_ver;
|
|
__le32 tbl_index;
|
|
__le32 map_count;
|
|
__le64 dma_addr;
|
|
__le16 dbid_flags;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_CREATE_CQ_IN_V1_LEN 34
|
|
static_assert(sizeof(struct ionic_admin_create_cq) ==
|
|
IONIC_ADMIN_CREATE_CQ_IN_V1_LEN);
|
|
|
|
struct ionic_admin_destroy_cq {
|
|
__le32 cq_id;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_DESTROY_CQ_IN_V1_LEN 4
|
|
static_assert(sizeof(struct ionic_admin_destroy_cq) ==
|
|
IONIC_ADMIN_DESTROY_CQ_IN_V1_LEN);
|
|
|
|
struct ionic_admin_create_qp {
|
|
__le32 pd_id;
|
|
__be32 priv_flags;
|
|
__le32 sq_cq_id;
|
|
__u8 sq_depth_log2;
|
|
__u8 sq_stride_log2;
|
|
__u8 sq_dir_size_log2_rsvd;
|
|
__u8 sq_page_size_log2;
|
|
__le32 sq_tbl_index_xrcd_id;
|
|
__le32 sq_map_count;
|
|
__le64 sq_dma_addr;
|
|
__le32 rq_cq_id;
|
|
__u8 rq_depth_log2;
|
|
__u8 rq_stride_log2;
|
|
__u8 rq_dir_size_log2_rsvd;
|
|
__u8 rq_page_size_log2;
|
|
__le32 rq_tbl_index_srq_id;
|
|
__le32 rq_map_count;
|
|
__le64 rq_dma_addr;
|
|
__le32 id_ver;
|
|
__le16 dbid_flags;
|
|
__u8 type_state;
|
|
__u8 rsvd;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_CREATE_QP_IN_V1_LEN 64
|
|
static_assert(sizeof(struct ionic_admin_create_qp) ==
|
|
IONIC_ADMIN_CREATE_QP_IN_V1_LEN);
|
|
|
|
struct ionic_admin_destroy_qp {
|
|
__le32 qp_id;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_DESTROY_QP_IN_V1_LEN 4
|
|
static_assert(sizeof(struct ionic_admin_destroy_qp) ==
|
|
IONIC_ADMIN_DESTROY_QP_IN_V1_LEN);
|
|
|
|
struct ionic_admin_mod_qp {
|
|
__be32 attr_mask;
|
|
__u8 dcqcn_profile;
|
|
__u8 tfp_csum_profile;
|
|
__be16 access_flags;
|
|
__le32 rq_psn;
|
|
__le32 sq_psn;
|
|
__le32 qkey_dest_qpn;
|
|
__le32 rate_limit_kbps;
|
|
__u8 pmtu;
|
|
__u8 retry;
|
|
__u8 rnr_timer;
|
|
__u8 retry_timeout;
|
|
__u8 rsq_depth;
|
|
__u8 rrq_depth;
|
|
__le16 pkey_id;
|
|
__le32 ah_id_len;
|
|
__u8 en_pcp;
|
|
__u8 ip_dscp;
|
|
__u8 rsvd2;
|
|
__u8 type_state;
|
|
union {
|
|
struct {
|
|
__le16 rsvd1;
|
|
};
|
|
__le32 rrq_index;
|
|
};
|
|
__le32 rsq_index;
|
|
__le64 dma_addr;
|
|
__le32 id_ver;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_MODIFY_QP_IN_V1_LEN 60
|
|
static_assert(sizeof(struct ionic_admin_mod_qp) ==
|
|
IONIC_ADMIN_MODIFY_QP_IN_V1_LEN);
|
|
|
|
struct ionic_admin_query_qp {
|
|
__le64 hdr_dma_addr;
|
|
__le64 sq_dma_addr;
|
|
__le64 rq_dma_addr;
|
|
__le32 ah_id;
|
|
__le32 id_ver;
|
|
__le16 dbid_flags;
|
|
} __packed;
|
|
|
|
#define IONIC_ADMIN_QUERY_QP_IN_V1_LEN 34
|
|
static_assert(sizeof(struct ionic_admin_query_qp) ==
|
|
IONIC_ADMIN_QUERY_QP_IN_V1_LEN);
|
|
|
|
#define ADMIN_WQE_STRIDE 64
|
|
#define ADMIN_WQE_HDR_LEN 4
|
|
|
|
/* admin queue v1 wqe */
|
|
struct ionic_v1_admin_wqe {
|
|
__u8 op;
|
|
__u8 rsvd;
|
|
__le16 len;
|
|
|
|
union {
|
|
struct ionic_admin_stats_hdr stats;
|
|
struct ionic_admin_create_ah create_ah;
|
|
struct ionic_admin_destroy_ah destroy_ah;
|
|
struct ionic_admin_query_ah query_ah;
|
|
struct ionic_admin_create_mr create_mr;
|
|
struct ionic_admin_destroy_mr destroy_mr;
|
|
struct ionic_admin_create_cq create_cq;
|
|
struct ionic_admin_destroy_cq destroy_cq;
|
|
struct ionic_admin_create_qp create_qp;
|
|
struct ionic_admin_destroy_qp destroy_qp;
|
|
struct ionic_admin_mod_qp mod_qp;
|
|
struct ionic_admin_query_qp query_qp;
|
|
} cmd;
|
|
};
|
|
|
|
/* side data for query qp */
|
|
struct ionic_v1_admin_query_qp_sq {
|
|
__u8 rnr_timer;
|
|
__u8 retry_timeout;
|
|
__be16 access_perms_flags;
|
|
__be16 rsvd;
|
|
__be16 pkey_id;
|
|
__be32 qkey_dest_qpn;
|
|
__be32 rate_limit_kbps;
|
|
__be32 rq_psn;
|
|
};
|
|
|
|
struct ionic_v1_admin_query_qp_rq {
|
|
__u8 state_pmtu;
|
|
__u8 retry_rnrtry;
|
|
__u8 rrq_depth;
|
|
__u8 rsq_depth;
|
|
__be32 sq_psn;
|
|
__be16 access_perms_flags;
|
|
__be16 rsvd;
|
|
};
|
|
|
|
/* admin queue v1 opcodes */
|
|
enum ionic_v1_admin_op {
|
|
IONIC_V1_ADMIN_NOOP,
|
|
IONIC_V1_ADMIN_CREATE_CQ,
|
|
IONIC_V1_ADMIN_CREATE_QP,
|
|
IONIC_V1_ADMIN_CREATE_MR,
|
|
IONIC_V1_ADMIN_STATS_HDRS,
|
|
IONIC_V1_ADMIN_STATS_VALS,
|
|
IONIC_V1_ADMIN_DESTROY_MR,
|
|
IONIC_V1_ADMIN_RSVD_7, /* RESIZE_CQ */
|
|
IONIC_V1_ADMIN_DESTROY_CQ,
|
|
IONIC_V1_ADMIN_MODIFY_QP,
|
|
IONIC_V1_ADMIN_QUERY_QP,
|
|
IONIC_V1_ADMIN_DESTROY_QP,
|
|
IONIC_V1_ADMIN_DEBUG,
|
|
IONIC_V1_ADMIN_CREATE_AH,
|
|
IONIC_V1_ADMIN_QUERY_AH,
|
|
IONIC_V1_ADMIN_MODIFY_DCQCN,
|
|
IONIC_V1_ADMIN_DESTROY_AH,
|
|
IONIC_V1_ADMIN_QP_STATS_HDRS,
|
|
IONIC_V1_ADMIN_QP_STATS_VALS,
|
|
IONIC_V1_ADMIN_OPCODES_MAX,
|
|
};
|
|
|
|
/* admin queue v1 cqe status */
|
|
enum ionic_v1_admin_status {
|
|
IONIC_V1_ASTS_OK,
|
|
IONIC_V1_ASTS_BAD_CMD,
|
|
IONIC_V1_ASTS_BAD_INDEX,
|
|
IONIC_V1_ASTS_BAD_STATE,
|
|
IONIC_V1_ASTS_BAD_TYPE,
|
|
IONIC_V1_ASTS_BAD_ATTR,
|
|
IONIC_V1_ASTS_MSG_TOO_BIG,
|
|
};
|
|
|
|
/* event queue v1 eqe */
|
|
struct ionic_v1_eqe {
|
|
__be32 evt;
|
|
};
|
|
|
|
/* bits for cqe queue_type_flags */
|
|
enum ionic_v1_eqe_evt_bits {
|
|
IONIC_V1_EQE_COLOR = BIT(0),
|
|
IONIC_V1_EQE_TYPE_SHIFT = 1,
|
|
IONIC_V1_EQE_TYPE_MASK = 0x7,
|
|
IONIC_V1_EQE_CODE_SHIFT = 4,
|
|
IONIC_V1_EQE_CODE_MASK = 0xf,
|
|
IONIC_V1_EQE_QID_SHIFT = 8,
|
|
|
|
/* cq events */
|
|
IONIC_V1_EQE_TYPE_CQ = 0,
|
|
/* cq normal events */
|
|
IONIC_V1_EQE_CQ_NOTIFY = 0,
|
|
/* cq error events */
|
|
IONIC_V1_EQE_CQ_ERR = 8,
|
|
|
|
/* qp and srq events */
|
|
IONIC_V1_EQE_TYPE_QP = 1,
|
|
/* qp normal events */
|
|
IONIC_V1_EQE_SRQ_LEVEL = 0,
|
|
IONIC_V1_EQE_SQ_DRAIN = 1,
|
|
IONIC_V1_EQE_QP_COMM_EST = 2,
|
|
IONIC_V1_EQE_QP_LAST_WQE = 3,
|
|
/* qp error events */
|
|
IONIC_V1_EQE_QP_ERR = 8,
|
|
IONIC_V1_EQE_QP_ERR_REQUEST = 9,
|
|
IONIC_V1_EQE_QP_ERR_ACCESS = 10,
|
|
};
|
|
|
|
enum ionic_tfp_csum_profiles {
|
|
IONIC_TFP_CSUM_PROF_ETH_IPV4_UDP = 0,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP = 1,
|
|
IONIC_TFP_CSUM_PROF_ETH_IPV6_UDP = 2,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV6_UDP = 3,
|
|
IONIC_TFP_CSUM_PROF_IPV4_UDP_VXLAN_ETH_QTAG_IPV4_UDP = 4,
|
|
IONIC_TFP_CSUM_PROF_IPV4_UDP_VXLAN_ETH_QTAG_IPV6_UDP = 5,
|
|
IONIC_TFP_CSUM_PROF_QTAG_IPV4_UDP_VXLAN_ETH_QTAG_IPV4_UDP = 6,
|
|
IONIC_TFP_CSUM_PROF_QTAG_IPV4_UDP_VXLAN_ETH_QTAG_IPV6_UDP = 7,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP_ESP_IPV4_UDP = 8,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_ESP_UDP = 9,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP_ESP_UDP = 10,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV6_ESP_UDP = 11,
|
|
IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP_CSUM = 12,
|
|
};
|
|
|
|
static inline bool ionic_v1_eqe_color(struct ionic_v1_eqe *eqe)
|
|
{
|
|
return eqe->evt & cpu_to_be32(IONIC_V1_EQE_COLOR);
|
|
}
|
|
|
|
static inline u32 ionic_v1_eqe_evt(struct ionic_v1_eqe *eqe)
|
|
{
|
|
return be32_to_cpu(eqe->evt);
|
|
}
|
|
|
|
static inline u8 ionic_v1_eqe_evt_type(u32 evt)
|
|
{
|
|
return (evt >> IONIC_V1_EQE_TYPE_SHIFT) & IONIC_V1_EQE_TYPE_MASK;
|
|
}
|
|
|
|
static inline u8 ionic_v1_eqe_evt_code(u32 evt)
|
|
{
|
|
return (evt >> IONIC_V1_EQE_CODE_SHIFT) & IONIC_V1_EQE_CODE_MASK;
|
|
}
|
|
|
|
static inline u32 ionic_v1_eqe_evt_qid(u32 evt)
|
|
{
|
|
return evt >> IONIC_V1_EQE_QID_SHIFT;
|
|
}
|
|
|
|
enum ionic_v1_stat_bits {
|
|
IONIC_V1_STAT_TYPE_SHIFT = 28,
|
|
IONIC_V1_STAT_TYPE_NONE = 0,
|
|
IONIC_V1_STAT_TYPE_8 = 1,
|
|
IONIC_V1_STAT_TYPE_LE16 = 2,
|
|
IONIC_V1_STAT_TYPE_LE32 = 3,
|
|
IONIC_V1_STAT_TYPE_LE64 = 4,
|
|
IONIC_V1_STAT_TYPE_BE16 = 5,
|
|
IONIC_V1_STAT_TYPE_BE32 = 6,
|
|
IONIC_V1_STAT_TYPE_BE64 = 7,
|
|
IONIC_V1_STAT_OFF_MASK = BIT(IONIC_V1_STAT_TYPE_SHIFT) - 1,
|
|
};
|
|
|
|
struct ionic_v1_stat {
|
|
union {
|
|
__be32 be_type_off;
|
|
u32 type_off;
|
|
};
|
|
char name[28];
|
|
};
|
|
|
|
static inline int ionic_v1_stat_type(struct ionic_v1_stat *hdr)
|
|
{
|
|
return hdr->type_off >> IONIC_V1_STAT_TYPE_SHIFT;
|
|
}
|
|
|
|
static inline unsigned int ionic_v1_stat_off(struct ionic_v1_stat *hdr)
|
|
{
|
|
return hdr->type_off & IONIC_V1_STAT_OFF_MASK;
|
|
}
|
|
|
|
#endif /* _IONIC_FW_H_ */
|