blob: ee0b80831943395754a3fe23e9051063796b33b8 [file] [log] [blame] [edit]
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
* Copyright (c) 2024, Microsoft Corporation. All rights reserved.
*/
#ifndef _GDMA_H_
#define _GDMA_H_
#include <stdio.h>
#include <linux/types.h>
#include <endian.h>
#include <infiniband/verbs.h>
#include <sys/mman.h>
#include <util/util.h>
#define GDMA_QUEUE_OFFSET_WIDTH 27
#define GDMA_QUEUE_OFFSET_MASK ((1 << GDMA_QUEUE_OFFSET_WIDTH) - 1)
#define GDMA_COMP_DATA_SIZE 60
#define IB_SYNDROME_ACK(credits) (0x00 + (credits))
#define IB_SYNDROME_RNR_NAK(timer) (0x20 + (timer))
#define IB_SYNDROME_NAK(code) (0x60 + (code))
#define IB_IS_ACK(syndrome) (((syndrome) & 0xE0) == IB_SYNDROME_ACK(0))
enum gdma_work_req_flags {
GDMA_WORK_REQ_NONE = 0,
GDMA_WORK_REQ_OOB_IN_SGL = BIT(0),
GDMA_WORK_REQ_SGL_DIRECT = BIT(1),
GDMA_WORK_REQ_CONSUME_CREDIT = BIT(2),
GDMA_WORK_REQ_FENCE = BIT(3),
GDMA_WORK_REQ_CHECK_SN = BIT(4),
GDMA_WORK_REQ_PAD_DATA_BY_FIRST_SGE_SIZE = BIT(5),
GDMA_WORK_REQ_EXTRA_LARGE_OOB = BIT(5),
};
union gdma_oob {
struct {
uint32_t num_padding_sgls:5;
uint32_t reserved1:19;
uint32_t last_vbytes:8;
uint32_t num_sgl_entries:8;
uint32_t inline_client_oob_size:3;
uint32_t client_oob_in_sgl:1;
uint32_t consume_credit:1;
uint32_t fence:1;
uint32_t reserved2:2;
uint32_t client_data_unit:14;
uint32_t check_sn:1;
uint32_t sgl_direct:1;
} tx;
struct {
uint32_t reserved1;
uint32_t num_sgl_entries:8;
uint32_t inline_client_oob_size:3;
uint32_t reserved2:19;
uint32_t check_sn:1;
uint32_t reserved3:1;
} rx;
}; /* HW DATA */
/* The 16-byte struct is part of the GDMA work queue entry (WQE). */
struct gdma_sge {
uint64_t address;
uint32_t mem_key;
uint32_t size;
}; /* HW DATA */
struct rdma_recv_oob {
uint32_t psn_start:24;
uint32_t reserved1:8;
uint32_t psn_range:24;
uint32_t reserved2:8;
}; /* HW DATA */
struct extra_large_wqe {
__le32 immediate;
uint32_t reserved;
uint64_t padding;
}; /* HW DATA */
struct rdma_send_oob {
uint32_t wqe_type:5;
uint32_t fence:1;
uint32_t signaled:1;
uint32_t solicited:1;
uint32_t psn:24;
uint32_t ssn:24; // also remote_qpn
uint32_t reserved1:8;
union {
uint32_t req_details[4];
union {
__le32 immediate;
uint32_t invalidate_key;
} send;
struct {
uint32_t address_hi;
uint32_t address_low;
uint32_t rkey;
uint32_t dma_len;
} rdma;
};
}; /* HW DATA */
struct gdma_wqe {
// in units of 32-byte blocks, masked by GDMA_QUEUE_OFFSET_MASK.
uint32_t unmasked_wqe_index;
uint32_t size_in_bu;
// Client oob is either 8 bytes or 24 bytes, so DmaOob + ClientOob will never wrap.
union gdma_oob *gdma_oob;
void *client_oob;
uint32_t client_oob_size;
struct gdma_sge *sgl1;
uint32_t num_sge1;
// In case SGL wraps in the queue buffer.
struct gdma_sge *sgl2;
uint32_t num_sge2;
};
enum wqe_opcode_types {
WQE_TYPE_UD_SEND = 0,
WQE_TYPE_UD_SEND_IMM = 1,
WQE_TYPE_RC_SEND = 2,
WQE_TYPE_RC_SEND_IMM = 3,
WQE_TYPE_RC_SEND_INV = 4,
WQE_TYPE_WRITE = 5,
WQE_TYPE_WRITE_IMM = 6,
WQE_TYPE_READ = 7,
WQE_TYPE_UD_RECV = 8,
WQE_TYPE_RC_RECV = 9,
WQE_TYPE_LOCAL_INV = 10,
WQE_TYPE_REG_MR = 11,
WQE_TYPE_MAX,
}; /* HW DATA */
static inline enum wqe_opcode_types
convert_wr_to_hw_opcode(enum ibv_wr_opcode opcode)
{
switch (opcode) {
case IBV_WR_RDMA_WRITE:
return WQE_TYPE_WRITE;
case IBV_WR_RDMA_WRITE_WITH_IMM:
return WQE_TYPE_WRITE_IMM;
case IBV_WR_SEND:
return WQE_TYPE_RC_SEND;
case IBV_WR_SEND_WITH_IMM:
return WQE_TYPE_RC_SEND_IMM;
case IBV_WR_RDMA_READ:
return WQE_TYPE_READ;
default:
return WQE_TYPE_MAX;
}
}
enum {
CQE_TYPE_NOP = 0,
CQE_TYPE_UD_SEND = 1,
CQE_TYPE_UD_SEND_IMM = 2,
CQE_TYPE_RC_SEND = 3,
CQE_TYPE_RC_SEND_IMM = 4,
CQE_TYPE_RC_SEND_INV = 5,
CQE_TYPE_RC_WRITE_IMM = 6,
CQE_TYPE_ARMED_CMPL = 7,
CQE_TYPE_LWR = 8,
CQE_TYPE_ERROR = 34,
}; /* HW DATA */
union mana_rdma_cqe {
struct {
uint8_t cqe_type;
uint8_t data[GDMA_COMP_DATA_SIZE - 1];
};
struct {
uint32_t cqe_type : 8;
uint32_t reserved1 : 24;
uint32_t msg_len;
uint32_t psn : 24;
uint32_t reserved2 : 8;
uint32_t imm_data;
uint32_t rx_wqe_offset;
} rc_recv;
struct {
uint32_t cqe_type : 8;
uint32_t vendor_error : 9;
uint32_t reserved1 : 15;
uint32_t sge_offset : 5;
uint32_t tx_wqe_offset : 27;
} ud_send;
struct {
uint32_t cqe_type : 8;
uint32_t reserved1 : 24;
uint32_t msg_len;
uint32_t src_qpn : 24;
uint32_t reserved2 : 8;
uint32_t imm_data;
uint32_t rx_wqe_offset;
} ud_recv;
struct {
uint32_t cqe_type : 8;
uint32_t vendor_error : 10;
uint32_t reserved1 : 14;
uint32_t msn : 24;
uint32_t syndrome : 8;
uint32_t psn : 24;
uint32_t opcode : 8;
uint32_t rsp_msn : 24;
uint32_t reserved2 : 8;
uint32_t rsp_psn : 24;
uint32_t reserved3 : 8;
} error;
struct {
uint32_t cqe_type : 8;
uint32_t reserved1 : 24;
uint32_t msn : 24;
uint32_t syndrome : 8;
uint32_t psn : 24;
uint32_t reserved2 : 8;
} rc_armed_completion;
}; /* HW DATA */
static_assert(sizeof(union mana_rdma_cqe) == GDMA_COMP_DATA_SIZE, "bad size");
struct gdma_cqe {
union mana_rdma_cqe rdma_cqe;
uint32_t wqid : 24;
uint32_t is_sq : 1;
uint32_t reserved : 4;
uint32_t owner_bits : 3;
}; /* HW DATA */
enum mana_error_code {
VENDOR_ERR_OK = 0x0,
VENDOR_ERR_RX_OP_REQ = 0x03,
VENDOR_ERR_RX_PKT_LEN = 0x05,
VENDOR_ERR_RX_ATB_RKEY_MISCONFIG_ERR = 0x43,
VENDOR_ERR_RX_ATB_RKEY_ADDR_RIGHT = 0x83,
VENDOR_ERR_RX_ATB_RKEY_ADDR_RANGE = 0xc3,
VENDOR_ERR_RX_MSG_LEN_OVFL = 0x102,
VENDOR_ERR_RX_MISBEHAVING_CLIENT = 0x108,
VENDOR_ERR_RX_MALFORMED_WQE = 0x109,
VENDOR_ERR_RX_CLIENT_ID = 0x10a,
VENDOR_ERR_RX_GFID = 0x10b,
VENDOR_ERR_RX_READRESP_LEN_MISMATCH = 0x10f,
VENDOR_ERR_RX_PCIE = 0x10c,
VENDOR_ERR_RX_NO_AVAIL_WQE = 0x111,
VENDOR_ERR_RX_ATB_SGE_MISSCONFIG = 0x143,
VENDOR_ERR_RX_ATB_WQE_MISCONFIG = 0x145,
VENDOR_ERR_RX_INVALID_REQ_NAK = 0x161,
VENDOR_ERR_RX_REMOTE_ACCESS_NAK = 0x162,
VENDOR_ERR_RX_REMOTE_OP_ERR_NAK = 0x163,
VENDOR_ERR_RX_RNR_NAK = 0x164,
VENDOR_ERR_RX_ATB_SGE_ADDR_RIGHT = 0x183,
VENDOR_ERR_RX_ATB_WQE_ADDR_RIGHT = 0x185,
VENDOR_ERR_RX_ATB_SGE_ADDR_RANGE = 0x1c3,
VENDOR_ERR_RX_ATB_WQE_ADDR_RANGE = 0x1c5,
VENDOR_ERR_TX_RETRY_LIMIT_EXCEEDED = 0x1c6,
VENDOR_ERR_RX_NOT_EMPTY_ON_DISABLE = 0x1c7,
VENDOR_ERR_TX_GDMA_CORRUPTED_WQE = 0x201,
VENDOR_ERR_TX_ATB_WQE_ACCESS_VIOLATION = 0x202,
VENDOR_ERR_TX_ATB_WQE_ADDR_RANGE = 0x203,
VENDOR_ERR_TX_ATB_WQE_CONFIG_ERR = 0x204,
VENDOR_ERR_TX_PCIE_WQE = 0x205,
VENDOR_ERR_TX_ATB_MSG_ACCESS_VIOLATION = 0x206,
VENDOR_ERR_TX_ATB_MSG_ADDR_RANGE = 0x207,
VENDOR_ERR_TX_ATB_MSG_CONFIG_ERR = 0x208,
VENDOR_ERR_TX_PCIE_MSG = 0x209,
VENDOR_ERR_TX_GDMA_INVALID_STATE = 0x20a,
VENDOR_ERR_TX_MISBEHAVING_CLIENT = 0x20b,
VENDOR_ERR_TX_RDMA_MALFORMED_WQE_SIZE = 0x210,
VENDOR_ERR_TX_RDMA_MALFORMED_WQE_FIELD = 0x211,
VENDOR_ERR_TX_RDMA_INVALID_STATE = 0x212,
VENDOR_ERR_TX_RDMA_INVALID_NPT = 0x213,
VENDOR_ERR_TX_RDMA_INVALID_SGID = 0x214,
VENDOR_ERR_TX_RDMA_WQE_UNSUPPORTED = 0x215,
VENDOR_ERR_TX_RDMA_WQE_LEN_ERR = 0x216,
VENDOR_ERR_TX_RDMA_MTU_ERR = 0x217,
VENDOR_ERR_TX_RDMA_VFID_MISMATCH = 0x218,
VENDOR_ERR_TX_RDMA_ATB_CMD_MISS = 0x220,
VENDOR_ERR_TX_RDMA_ATB_CMD_IDX_ERROR = 0x221,
VENDOR_ERR_TX_RDMA_ATB_CMD_TAG_MISMATCH_ERROR = 0x222,
VENDOR_ERR_TX_RDMA_ATB_CMD_PDID_MISMATCH_ERROR = 0x223,
VENDOR_ERR_TX_RDMA_ATB_CMD_AR_ERROR = 0x224,
VENDOR_ERR_TX_RDMA_ATB_CMD_PT_OVF = 0x225,
VENDOR_ERR_TX_RDMA_ATB_CMD_PT_LENGHT_MISMATCH = 0x226,
VENDOR_ERR_TX_RDMA_ATB_CMD_ILLEGAL_CMD = 0x227,
VENDOR_ERR_HW_MAX = 0x3ff,
/* SW vendor errors */
VENDOR_ERR_SW_FLUSHED = 0xfff,
};
#endif //_GDMA_H_