1/* 2 * QEMU VMWARE paravirtual RDMA device definitions 3 * 4 * Copyright (C) 2018 Oracle 5 * Copyright (C) 2018 Red Hat Inc 6 * 7 * Authors: 8 * Yuval Shaia <yuval.shaia@oracle.com> 9 * Marcel Apfelbaum <marcel@redhat.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2 or later. 12 * See the COPYING file in the top-level directory. 13 * 14 */ 15 16#ifndef PVRDMA_PVRDMA_H 17#define PVRDMA_PVRDMA_H 18 19#include "qemu/units.h" 20#include "qemu/notify.h" 21#include "hw/pci/pci.h" 22#include "hw/pci/msix.h" 23#include "chardev/char-fe.h" 24#include "hw/net/vmxnet3_defs.h" 25 26#include "../rdma_backend_defs.h" 27#include "../rdma_rm_defs.h" 28 29#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h" 30#include "pvrdma_dev_ring.h" 31#include "qom/object.h" 32 33/* BARs */ 34#define RDMA_MSIX_BAR_IDX 0 35#define RDMA_REG_BAR_IDX 1 36#define RDMA_UAR_BAR_IDX 2 37#define RDMA_BAR0_MSIX_SIZE (16 * KiB) 38#define RDMA_BAR1_REGS_SIZE 64 39#define RDMA_BAR2_UAR_SIZE (0x1000 * MAX_UCS) /* each uc gets page */ 40 41/* MSIX */ 42#define RDMA_MAX_INTRS 3 43#define RDMA_MSIX_TABLE 0x0000 44#define RDMA_MSIX_PBA 0x2000 45 46/* Interrupts Vectors */ 47#define INTR_VEC_CMD_RING 0 48#define INTR_VEC_CMD_ASYNC_EVENTS 1 49#define INTR_VEC_CMD_COMPLETION_Q 2 50 51/* HW attributes */ 52#define PVRDMA_HW_NAME "pvrdma" 53#define PVRDMA_HW_VERSION 17 54#define PVRDMA_FW_VERSION 14 55 56/* Some defaults */ 57#define PVRDMA_PKEY 0xFFFF 58 59typedef struct DSRInfo { 60 dma_addr_t dma; 61 struct pvrdma_device_shared_region *dsr; 62 63 union pvrdma_cmd_req *req; 64 union pvrdma_cmd_resp *rsp; 65 66 PvrdmaRingState *async_ring_state; 67 PvrdmaRing async; 68 69 PvrdmaRingState *cq_ring_state; 70 PvrdmaRing cq; 71} DSRInfo; 72 73typedef struct PVRDMADevStats { 74 uint64_t commands; 75 uint64_t regs_reads; 76 uint64_t regs_writes; 77 uint64_t uar_writes; 78 uint64_t interrupts; 79} PVRDMADevStats; 80 81struct PVRDMADev { 82 PCIDevice parent_obj; 83 MemoryRegion msix; 84 MemoryRegion regs; 85 uint32_t regs_data[RDMA_BAR1_REGS_SIZE]; 86 MemoryRegion uar; 87 uint32_t uar_data[RDMA_BAR2_UAR_SIZE]; 88 DSRInfo dsr_info; 89 int interrupt_mask; 90 struct ibv_device_attr dev_attr; 91 uint64_t node_guid; 92 char *backend_eth_device_name; 93 char *backend_device_name; 94 uint8_t backend_port_num; 95 RdmaBackendDev backend_dev; 96 RdmaDeviceResources rdma_dev_res; 97 CharBackend mad_chr; 98 VMXNET3State *func0; 99 Notifier shutdown_notifier; 100 PVRDMADevStats stats; 101}; 102typedef struct PVRDMADev PVRDMADev; 103DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV, 104 PVRDMA_HW_NAME) 105 106static inline int get_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t *val) 107{ 108 int idx = addr >> 2; 109 110 if (idx >= RDMA_BAR1_REGS_SIZE) { 111 return -EINVAL; 112 } 113 114 *val = dev->regs_data[idx]; 115 116 return 0; 117} 118 119static inline int set_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t val) 120{ 121 int idx = addr >> 2; 122 123 if (idx >= RDMA_BAR1_REGS_SIZE) { 124 return -EINVAL; 125 } 126 127 dev->regs_data[idx] = val; 128 129 return 0; 130} 131 132static inline void post_interrupt(PVRDMADev *dev, unsigned vector) 133{ 134 PCIDevice *pci_dev = PCI_DEVICE(dev); 135 136 if (likely(!dev->interrupt_mask)) { 137 dev->stats.interrupts++; 138 msix_notify(pci_dev, vector); 139 } 140} 141 142int pvrdma_exec_cmd(PVRDMADev *dev); 143 144#endif 145