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_ring.h" 30 #include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h" 31 #include "pvrdma_dev_ring.h" 32 #include "qom/object.h" 33 34 /* BARs */ 35 #define RDMA_MSIX_BAR_IDX 0 36 #define RDMA_REG_BAR_IDX 1 37 #define RDMA_UAR_BAR_IDX 2 38 #define RDMA_BAR0_MSIX_SIZE (16 * KiB) 39 #define RDMA_BAR1_REGS_SIZE 64 40 #define RDMA_BAR2_UAR_SIZE (0x1000 * MAX_UCS) /* each uc gets page */ 41 42 /* MSIX */ 43 #define RDMA_MAX_INTRS 3 44 #define RDMA_MSIX_TABLE 0x0000 45 #define RDMA_MSIX_PBA 0x2000 46 47 /* Interrupts Vectors */ 48 #define INTR_VEC_CMD_RING 0 49 #define INTR_VEC_CMD_ASYNC_EVENTS 1 50 #define INTR_VEC_CMD_COMPLETION_Q 2 51 52 /* HW attributes */ 53 #define PVRDMA_HW_NAME "pvrdma" 54 #define PVRDMA_HW_VERSION 17 55 #define PVRDMA_FW_VERSION 14 56 57 /* Some defaults */ 58 #define PVRDMA_PKEY 0xFFFF 59 60 typedef struct DSRInfo { 61 dma_addr_t dma; 62 struct pvrdma_device_shared_region *dsr; 63 64 union pvrdma_cmd_req *req; 65 union pvrdma_cmd_resp *rsp; 66 67 struct pvrdma_ring *async_ring_state; 68 PvrdmaRing async; 69 70 struct pvrdma_ring *cq_ring_state; 71 PvrdmaRing cq; 72 } DSRInfo; 73 74 typedef struct PVRDMADevStats { 75 uint64_t commands; 76 uint64_t regs_reads; 77 uint64_t regs_writes; 78 uint64_t uar_writes; 79 uint64_t interrupts; 80 } PVRDMADevStats; 81 82 struct PVRDMADev { 83 PCIDevice parent_obj; 84 MemoryRegion msix; 85 MemoryRegion regs; 86 uint32_t regs_data[RDMA_BAR1_REGS_SIZE]; 87 MemoryRegion uar; 88 uint32_t uar_data[RDMA_BAR2_UAR_SIZE]; 89 DSRInfo dsr_info; 90 int interrupt_mask; 91 struct ibv_device_attr dev_attr; 92 uint64_t node_guid; 93 char *backend_eth_device_name; 94 char *backend_device_name; 95 uint8_t backend_port_num; 96 RdmaBackendDev backend_dev; 97 RdmaDeviceResources rdma_dev_res; 98 CharBackend mad_chr; 99 VMXNET3State *func0; 100 Notifier shutdown_notifier; 101 PVRDMADevStats stats; 102 }; 103 typedef struct PVRDMADev PVRDMADev; 104 DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV, 105 PVRDMA_HW_NAME) 106 107 static inline int get_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t *val) 108 { 109 int idx = addr >> 2; 110 111 if (idx >= RDMA_BAR1_REGS_SIZE) { 112 return -EINVAL; 113 } 114 115 *val = dev->regs_data[idx]; 116 117 return 0; 118 } 119 120 static inline int set_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t val) 121 { 122 int idx = addr >> 2; 123 124 if (idx >= RDMA_BAR1_REGS_SIZE) { 125 return -EINVAL; 126 } 127 128 dev->regs_data[idx] = val; 129 130 return 0; 131 } 132 133 static inline void post_interrupt(PVRDMADev *dev, unsigned vector) 134 { 135 PCIDevice *pci_dev = PCI_DEVICE(dev); 136 137 if (likely(!dev->interrupt_mask)) { 138 dev->stats.interrupts++; 139 msix_notify(pci_dev, vector); 140 } 141 } 142 143 int pvrdma_exec_cmd(PVRDMADev *dev); 144 145 #endif 146