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 
59 typedef 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 
73 typedef 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 
81 struct 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 };
102 typedef struct PVRDMADev PVRDMADev;
DECLARE_INSTANCE_CHECKER(PVRDMADev,PVRDMA_DEV,PVRDMA_HW_NAME)103 DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV,
104                          PVRDMA_HW_NAME)
105 
106 static 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 
set_reg_val(PVRDMADev * dev,hwaddr addr,uint32_t val)119 static 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 
post_interrupt(PVRDMADev * dev,unsigned vector)132 static 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 
142 int pvrdma_exec_cmd(PVRDMADev *dev);
143 
144 #endif
145