/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright (c) 2021, Microsoft Corporation. */
#ifndef _GDMA_H
#define _GDMA_H
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
#include "shm_channel.h"
#define GDMA_STATUS_MORE_ENTRIES 0x00000105
#define GDMA_STATUS_CMD_UNSUPPORTED 0xffffffff
/* Structures labeled with "HW DATA" are exchanged with the hardware. All of
* them are naturally aligned and hence don't need __packed.
*/
enum gdma_request_type {
GDMA_VERIFY_VF_DRIVER_VERSION = 1,
GDMA_QUERY_MAX_RESOURCES = 2,
GDMA_LIST_DEVICES = 3,
GDMA_REGISTER_DEVICE = 4,
GDMA_DEREGISTER_DEVICE = 5,
GDMA_GENERATE_TEST_EQE = 10,
GDMA_CREATE_QUEUE = 12,
GDMA_DISABLE_QUEUE = 13,
GDMA_ALLOCATE_RESOURCE_RANGE = 22,
GDMA_DESTROY_RESOURCE_RANGE = 24,
GDMA_CREATE_DMA_REGION = 25,
GDMA_DMA_REGION_ADD_PAGES = 26,
GDMA_DESTROY_DMA_REGION = 27,
GDMA_CREATE_PD = 29,
GDMA_DESTROY_PD = 30,
GDMA_CREATE_MR = 31,
GDMA_DESTROY_MR = 32,
GDMA_QUERY_HWC_TIMEOUT = 84, /* 0x54 */
};
#define GDMA_RESOURCE_DOORBELL_PAGE 27
enum gdma_queue_type {
GDMA_INVALID_QUEUE,
GDMA_SQ,
GDMA_RQ,
GDMA_CQ,
GDMA_EQ,
};
enum gdma_work_request_flags {
GDMA_WR_NONE = 0,
GDMA_WR_OOB_IN_SGL = BIT(0),
GDMA_WR_PAD_BY_SGE0 = BIT(1),
};
enum gdma_eqe_type {
GDMA_EQE_COMPLETION = 3,
GDMA_EQE_TEST_EVENT = 64,
GDMA_EQE_HWC_INIT_EQ_ID_DB = 129,
GDMA_EQE_HWC_INIT_DATA = 130,
GDMA_EQE_HWC_INIT_DONE = 131,
GDMA_EQE_HWC_FPGA_RECONFIG = 132,
GDMA_EQE_HWC_SOC_RECONFIG_DATA = 133,
GDMA_EQE_HWC_SOC_SERVICE = 134,
GDMA_EQE_HWC_RESET_REQUEST = 135,
GDMA_EQE_RNIC_QP_FATAL = 176,
};
enum {
GDMA_DEVICE_NONE = 0,
GDMA_DEVICE_HWC = 1,
GDMA_DEVICE_MANA = 2,
GDMA_DEVICE_MANA_IB = 3,
};
enum gdma_service_type {
GDMA_SERVICE_TYPE_NONE = 0,
GDMA_SERVICE_TYPE_RDMA_SUSPEND = 1,
GDMA_SERVICE_TYPE_RDMA_RESUME = 2,
};
struct mana_service_work {
struct work_struct work;
struct gdma_dev *gdma_dev;
enum gdma_service_type event;
};
struct gdma_resource {
/* Protect the bitmap */
spinlock_t lock;
/* The bitmap size in bits. */
u32 size;
/* The bitmap tracks the resources. */
unsigned long *map;
};
union gdma_doorbell_entry {
u64 as_uint64;
struct {
u64 id : 24;
u64 reserved : 8;
u64 tail_ptr : 31;
u64 arm : 1;
} cq;
struct {
u64 id : 24;
u64 wqe_cnt : 8;
u64 tail_ptr : 32;
} rq;
struct {
u64 id : 24;
u64 reserved : 8;
u64 tail_ptr : 32;
} sq;
struct {
u64 id : 16;
u64 reserved : 16;
u64 tail_ptr : 31;
u64 arm : 1;
} eq;
}; /* HW DATA */
struct gdma_msg_hdr {
u32 hdr_type;
u32 msg_type;
u16 msg_version;
u16 hwc_msg_id;
u32 msg_size;
}; /* HW DATA */
struct gdma_dev_id {
union {
struct {
u16 type;
u16 instance;
};
u32 as_uint32;
};
}; /* HW DATA */
struct gdma_req_hdr {
struct gdma_msg_hdr req;
struct gdma_msg_hdr resp; /* The expected response */
struct gdma_dev_id dev_id;
u32 activity_id;
}; /* HW DATA */
struct gdma_resp_hdr {
struct gdma_msg_hdr response;
struct gdma_dev_id dev_id;
u32 activity_id;
u32 status;
u32 reserved;
}; /* HW DATA */
struct gdma_general_req {
struct gdma_req_hdr hdr;
}; /* HW DATA */
#define GDMA_MESSAGE_V1 1
#define GDMA_MESSAGE_V2 2
#define GDMA_MESSAGE_V3 3
#define GDMA_MESSAGE_V4 4
struct gdma_general_resp {
struct gdma_resp_hdr hdr;
}; /* HW DATA */
#define GDMA_STANDARD_HEADER_TYPE 0
static inline void mana_gd_init_req_hdr(struct gdma_req_hdr *hdr, u32 code,
u32 req_size, u32 resp_size)
{
hdr->req.hdr_type = GDMA_STANDARD_HEADER_TYPE;
hdr->req.msg_type = code;
hdr->req.msg_version = GDMA_MESSAGE_V1;
hdr->req.msg_size = req_size;
hdr->resp.hdr_type = GDMA_STANDARD_HEADER_TYPE;
hdr->resp.msg_type = code;
hdr->resp.msg_version = GDMA_MESSAGE_V1;
hdr->resp.msg_size = resp_