Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / hw / rdma / vmw / pvrdma_dev_ring.c
blob30ce22a5be3ed95c5650f90d37ef2afe900ca377
1 /*
2 * QEMU paravirtual RDMA - Device rings
4 * Copyright (C) 2018 Oracle
5 * Copyright (C) 2018 Red Hat Inc
7 * Authors:
8 * Yuval Shaia <yuval.shaia@oracle.com>
9 * Marcel Apfelbaum <marcel@redhat.com>
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.
16 #include "qemu/osdep.h"
17 #include "hw/pci/pci.h"
18 #include "cpu.h"
19 #include "qemu/cutils.h"
21 #include "trace.h"
23 #include "../rdma_utils.h"
24 #include "pvrdma_dev_ring.h"
26 int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
27 PvrdmaRingState *ring_state, uint32_t max_elems,
28 size_t elem_sz, dma_addr_t *tbl, uint32_t npages)
30 int i;
31 int rc = 0;
33 pstrcpy(ring->name, MAX_RING_NAME_SZ, name);
34 ring->dev = dev;
35 ring->ring_state = ring_state;
36 ring->max_elems = max_elems;
37 ring->elem_sz = elem_sz;
38 /* TODO: Give a moment to think if we want to redo driver settings
39 qatomic_set(&ring->ring_state->prod_tail, 0);
40 qatomic_set(&ring->ring_state->cons_head, 0);
42 ring->npages = npages;
43 ring->pages = g_new0(void *, npages);
45 for (i = 0; i < npages; i++) {
46 if (!tbl[i]) {
47 rdma_error_report("npages=%d but tbl[%d] is NULL", npages, i);
48 continue;
51 ring->pages[i] = rdma_pci_dma_map(dev, tbl[i], TARGET_PAGE_SIZE);
52 if (!ring->pages[i]) {
53 rc = -ENOMEM;
54 rdma_error_report("Failed to map to page %d in ring %s", i, name);
55 goto out_free;
57 memset(ring->pages[i], 0, TARGET_PAGE_SIZE);
60 goto out;
62 out_free:
63 while (i--) {
64 rdma_pci_dma_unmap(dev, ring->pages[i], TARGET_PAGE_SIZE);
66 g_free(ring->pages);
68 out:
69 return rc;
72 void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
74 unsigned int idx, offset;
75 const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
76 const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
78 if (tail & ~((ring->max_elems << 1) - 1) ||
79 head & ~((ring->max_elems << 1) - 1) ||
80 tail == head) {
81 trace_pvrdma_ring_next_elem_read_no_data(ring->name);
82 return NULL;
85 idx = head & (ring->max_elems - 1);
86 offset = idx * ring->elem_sz;
87 return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
90 void pvrdma_ring_read_inc(PvrdmaRing *ring)
92 uint32_t idx = qatomic_read(&ring->ring_state->cons_head);
94 idx = (idx + 1) & ((ring->max_elems << 1) - 1);
95 qatomic_set(&ring->ring_state->cons_head, idx);
98 void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
100 unsigned int idx, offset;
101 const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
102 const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
104 if (tail & ~((ring->max_elems << 1) - 1) ||
105 head & ~((ring->max_elems << 1) - 1) ||
106 tail == (head ^ ring->max_elems)) {
107 rdma_error_report("CQ is full");
108 return NULL;
111 idx = tail & (ring->max_elems - 1);
112 offset = idx * ring->elem_sz;
113 return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
116 void pvrdma_ring_write_inc(PvrdmaRing *ring)
118 uint32_t idx = qatomic_read(&ring->ring_state->prod_tail);
120 idx = (idx + 1) & ((ring->max_elems << 1) - 1);
121 qatomic_set(&ring->ring_state->prod_tail, idx);
124 void pvrdma_ring_free(PvrdmaRing *ring)
126 if (!ring) {
127 return;
130 if (!ring->pages) {
131 return;
134 while (ring->npages--) {
135 rdma_pci_dma_unmap(ring->dev, ring->pages[ring->npages],
136 TARGET_PAGE_SIZE);
139 g_free(ring->pages);
140 ring->pages = NULL;