virtio_ring.h 1.8 KB
Newer Older
1 2 3 4
#ifndef _LINUX_VIRTIO_RING_H
#define _LINUX_VIRTIO_RING_H

#include <linux/irqreturn.h>
5 6
#include <uapi/linux/virtio_ring.h>

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
/*
 * Barriers in virtio are tricky.  Non-SMP virtio guests can't assume
 * they're not on an SMP host system, so they need to assume real
 * barriers.  Non-SMP virtio hosts could skip the barriers, but does
 * anyone care?
 *
 * For virtio_pci on SMP, we don't need to order with respect to MMIO
 * accesses through relaxed memory I/O windows, so smp_mb() et al are
 * sufficient.
 *
 * For using virtio to talk to real devices (eg. other heterogeneous
 * CPUs) we do need real barriers.  In theory, we could be using both
 * kinds of virtio, so it's a runtime decision, and the branch is
 * actually quite cheap.
 */

#ifdef CONFIG_SMP
static inline void virtio_mb(bool weak_barriers)
{
	if (weak_barriers)
		smp_mb();
	else
		mb();
}

static inline void virtio_rmb(bool weak_barriers)
{
	if (weak_barriers)
		smp_rmb();
	else
		rmb();
}

static inline void virtio_wmb(bool weak_barriers)
{
	if (weak_barriers)
		smp_wmb();
	else
		wmb();
}
#else
static inline void virtio_mb(bool weak_barriers)
{
	mb();
}

static inline void virtio_rmb(bool weak_barriers)
{
	rmb();
}

static inline void virtio_wmb(bool weak_barriers)
{
	wmb();
}
#endif

64 65 66
struct virtio_device;
struct virtqueue;

67 68
struct virtqueue *vring_new_virtqueue(unsigned int index,
				      unsigned int num,
69
				      unsigned int vring_align,
70
				      struct virtio_device *vdev,
71
				      bool weak_barriers,
72 73
				      void *pages,
				      void (*notify)(struct virtqueue *vq),
74 75
				      void (*callback)(struct virtqueue *vq),
				      const char *name);
76
void vring_del_virtqueue(struct virtqueue *vq);
77 78
/* Filter out transport-specific feature bits. */
void vring_transport_features(struct virtio_device *vdev);
79 80 81

irqreturn_t vring_interrupt(int irq, void *_vq);
#endif /* _LINUX_VIRTIO_RING_H */