xref: /linux/include/linux/virtio_ring.h (revision bf897d2626abe4559953342e2f7dda05d034c8c7)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_VIRTIO_RING_H
3 #define _LINUX_VIRTIO_RING_H
4 
5 #include <asm/barrier.h>
6 #include <linux/virtio.h>
7 #include <linux/irqreturn.h>
8 #include <uapi/linux/virtio_ring.h>
9 
10 /*
11  * Barriers in virtio are tricky.  Non-SMP virtio guests can't assume
12  * they're not on an SMP host system, so they need to assume real
13  * barriers.  Non-SMP virtio hosts could skip the barriers, but does
14  * anyone care?
15  *
16  * For virtio_pci on SMP, we don't need to order with respect to MMIO
17  * accesses through relaxed memory I/O windows, so virt_mb() et al are
18  * sufficient.
19  *
20  * For using virtio to talk to real devices (eg. other heterogeneous
21  * CPUs) we do need real barriers.  In theory, we could be using both
22  * kinds of virtio, so it's a runtime decision, and the branch is
23  * actually quite cheap.
24  */
25 
26 static inline void virtio_mb(bool weak_barriers)
27 {
28 	if (weak_barriers)
29 		virt_mb();
30 	else
31 		mb();
32 }
33 
34 static inline void virtio_rmb(bool weak_barriers)
35 {
36 	if (weak_barriers)
37 		virt_rmb();
38 	else
39 		dma_rmb();
40 }
41 
42 static inline void virtio_wmb(bool weak_barriers)
43 {
44 	if (weak_barriers)
45 		virt_wmb();
46 	else
47 		dma_wmb();
48 }
49 
50 #define virtio_store_mb(weak_barriers, p, v) \
51 do { \
52 	if (weak_barriers) { \
53 		virt_store_mb(*p, v); \
54 	} else { \
55 		WRITE_ONCE(*p, v); \
56 		mb(); \
57 	} \
58 } while (0) \
59 
60 struct virtio_device;
61 struct virtqueue;
62 struct device;
63 
64 /*
65  * Creates a virtqueue and allocates the descriptor ring.  If
66  * may_reduce_num is set, then this may allocate a smaller ring than
67  * expected.  The caller should query virtqueue_get_vring_size to learn
68  * the actual size of the ring.
69  */
70 struct virtqueue *vring_create_virtqueue(unsigned int index,
71 					 unsigned int num,
72 					 unsigned int vring_align,
73 					 struct virtio_device *vdev,
74 					 bool weak_barriers,
75 					 bool may_reduce_num,
76 					 bool ctx,
77 					 bool (*notify)(struct virtqueue *vq),
78 					 void (*callback)(struct virtqueue *vq),
79 					 const char *name);
80 
81 /*
82  * Creates a virtqueue and allocates the descriptor ring with per
83  * virtqueue mapping operations.
84  */
85 struct virtqueue *vring_create_virtqueue_map(unsigned int index,
86 					     unsigned int num,
87 					     unsigned int vring_align,
88 					     struct virtio_device *vdev,
89 					     bool weak_barriers,
90 					     bool may_reduce_num,
91 					     bool ctx,
92 					     bool (*notify)(struct virtqueue *vq),
93 					     void (*callback)(struct virtqueue *vq),
94 					     const char *name,
95 					     union virtio_map map);
96 
97 /*
98  * Creates a virtqueue with a standard layout but a caller-allocated
99  * ring.
100  */
101 struct virtqueue *vring_new_virtqueue(unsigned int index,
102 				      unsigned int num,
103 				      unsigned int vring_align,
104 				      struct virtio_device *vdev,
105 				      bool weak_barriers,
106 				      bool ctx,
107 				      void *pages,
108 				      bool (*notify)(struct virtqueue *vq),
109 				      void (*callback)(struct virtqueue *vq),
110 				      const char *name);
111 
112 /*
113  * Destroys a virtqueue.  If created with vring_create_virtqueue, this
114  * also frees the ring.
115  */
116 void vring_del_virtqueue(struct virtqueue *vq);
117 
118 /* Filter out transport-specific feature bits. */
119 void vring_transport_features(struct virtio_device *vdev);
120 
121 irqreturn_t vring_interrupt(int irq, void *_vq);
122 
123 u32 vring_notification_data(struct virtqueue *_vq);
124 #endif /* _LINUX_VIRTIO_RING_H */
125