The pvrdma code relies on the pvrdma_ring.h kernel header for some basic ring buffer handling. The content of that header isn't very exciting, but contains some (q)atomic_*() invocations that (a) cause manual massaging when doing a headers update, and (b) are an indication that we probably should not be importing that header at all. Let's reimplement the ring buffer handling directly in the pvrdma code instead. This arguably also improves readability of the code. Importing the header can now be dropped. Signed-off-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Yuval Shaia <yuval.shaia.ml@gmail.com> Tested-by: Yuval Shaia <yuval.shaia.ml@gmail.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
145 lines
3.3 KiB
C
145 lines
3.3 KiB
C
/*
|
|
* QEMU VMWARE paravirtual RDMA device definitions
|
|
*
|
|
* Copyright (C) 2018 Oracle
|
|
* Copyright (C) 2018 Red Hat Inc
|
|
*
|
|
* Authors:
|
|
* Yuval Shaia <yuval.shaia@oracle.com>
|
|
* Marcel Apfelbaum <marcel@redhat.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#ifndef PVRDMA_PVRDMA_H
|
|
#define PVRDMA_PVRDMA_H
|
|
|
|
#include "qemu/units.h"
|
|
#include "qemu/notify.h"
|
|
#include "hw/pci/pci.h"
|
|
#include "hw/pci/msix.h"
|
|
#include "chardev/char-fe.h"
|
|
#include "hw/net/vmxnet3_defs.h"
|
|
|
|
#include "../rdma_backend_defs.h"
|
|
#include "../rdma_rm_defs.h"
|
|
|
|
#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h"
|
|
#include "pvrdma_dev_ring.h"
|
|
#include "qom/object.h"
|
|
|
|
/* BARs */
|
|
#define RDMA_MSIX_BAR_IDX 0
|
|
#define RDMA_REG_BAR_IDX 1
|
|
#define RDMA_UAR_BAR_IDX 2
|
|
#define RDMA_BAR0_MSIX_SIZE (16 * KiB)
|
|
#define RDMA_BAR1_REGS_SIZE 64
|
|
#define RDMA_BAR2_UAR_SIZE (0x1000 * MAX_UCS) /* each uc gets page */
|
|
|
|
/* MSIX */
|
|
#define RDMA_MAX_INTRS 3
|
|
#define RDMA_MSIX_TABLE 0x0000
|
|
#define RDMA_MSIX_PBA 0x2000
|
|
|
|
/* Interrupts Vectors */
|
|
#define INTR_VEC_CMD_RING 0
|
|
#define INTR_VEC_CMD_ASYNC_EVENTS 1
|
|
#define INTR_VEC_CMD_COMPLETION_Q 2
|
|
|
|
/* HW attributes */
|
|
#define PVRDMA_HW_NAME "pvrdma"
|
|
#define PVRDMA_HW_VERSION 17
|
|
#define PVRDMA_FW_VERSION 14
|
|
|
|
/* Some defaults */
|
|
#define PVRDMA_PKEY 0xFFFF
|
|
|
|
typedef struct DSRInfo {
|
|
dma_addr_t dma;
|
|
struct pvrdma_device_shared_region *dsr;
|
|
|
|
union pvrdma_cmd_req *req;
|
|
union pvrdma_cmd_resp *rsp;
|
|
|
|
PvrdmaRingState *async_ring_state;
|
|
PvrdmaRing async;
|
|
|
|
PvrdmaRingState *cq_ring_state;
|
|
PvrdmaRing cq;
|
|
} DSRInfo;
|
|
|
|
typedef struct PVRDMADevStats {
|
|
uint64_t commands;
|
|
uint64_t regs_reads;
|
|
uint64_t regs_writes;
|
|
uint64_t uar_writes;
|
|
uint64_t interrupts;
|
|
} PVRDMADevStats;
|
|
|
|
struct PVRDMADev {
|
|
PCIDevice parent_obj;
|
|
MemoryRegion msix;
|
|
MemoryRegion regs;
|
|
uint32_t regs_data[RDMA_BAR1_REGS_SIZE];
|
|
MemoryRegion uar;
|
|
uint32_t uar_data[RDMA_BAR2_UAR_SIZE];
|
|
DSRInfo dsr_info;
|
|
int interrupt_mask;
|
|
struct ibv_device_attr dev_attr;
|
|
uint64_t node_guid;
|
|
char *backend_eth_device_name;
|
|
char *backend_device_name;
|
|
uint8_t backend_port_num;
|
|
RdmaBackendDev backend_dev;
|
|
RdmaDeviceResources rdma_dev_res;
|
|
CharBackend mad_chr;
|
|
VMXNET3State *func0;
|
|
Notifier shutdown_notifier;
|
|
PVRDMADevStats stats;
|
|
};
|
|
typedef struct PVRDMADev PVRDMADev;
|
|
DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV,
|
|
PVRDMA_HW_NAME)
|
|
|
|
static inline int get_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t *val)
|
|
{
|
|
int idx = addr >> 2;
|
|
|
|
if (idx >= RDMA_BAR1_REGS_SIZE) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
*val = dev->regs_data[idx];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int set_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t val)
|
|
{
|
|
int idx = addr >> 2;
|
|
|
|
if (idx >= RDMA_BAR1_REGS_SIZE) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev->regs_data[idx] = val;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void post_interrupt(PVRDMADev *dev, unsigned vector)
|
|
{
|
|
PCIDevice *pci_dev = PCI_DEVICE(dev);
|
|
|
|
if (likely(!dev->interrupt_mask)) {
|
|
dev->stats.interrupts++;
|
|
msix_notify(pci_dev, vector);
|
|
}
|
|
}
|
|
|
|
int pvrdma_exec_cmd(PVRDMADev *dev);
|
|
|
|
#endif
|