X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=include%2Flinux%2Fvirtio_ring.h;h=abe481ed990e328bd6f5ec1f5212deeed07b9fea;hb=03054de1e0b90b33e9974107d84dabd2509f5898;hp=ac69e7bb5a14f5465df654a5d7668cb45a7669f5;hpb=43cd73658d8077ee6899b0b5029aad0cba1e9f92;p=linux-2.6 diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index ac69e7bb5a..abe481ed99 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -15,9 +15,13 @@ /* This marks a buffer as write-only (otherwise read-only). */ #define VRING_DESC_F_WRITE 2 -/* This means don't notify other side when buffer added. */ +/* The Host uses this in used->flags to advise the Guest: don't kick me when + * you add a buffer. It's unreliable, so it's simply an optimization. Guest + * will still kick if it's out of buffers. */ #define VRING_USED_F_NO_NOTIFY 1 -/* This means don't interrupt guest when buffer consumed. */ +/* The Guest uses this in avail->flags to advise the Host: don't interrupt me + * when you consume a buffer. It's unreliable, so it's simply an + * optimization. */ #define VRING_AVAIL_F_NO_INTERRUPT 1 /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ @@ -67,7 +71,7 @@ struct vring { }; /* The standard layout for the ring is a continuous chunk of memory which looks - * like this. The used fields will be aligned to a "num+1" boundary. + * like this. We assume num is a power of 2. * * struct vring * { @@ -79,8 +83,8 @@ struct vring { * __u16 avail_idx; * __u16 available[num]; * - * // Padding so a correctly-chosen num value will cache-align used_idx. - * char pad[sizeof(struct vring_desc) - sizeof(avail_flags)]; + * // Padding to the next page boundary. + * char pad[]; * * // A ring of used descriptor heads with free-running index. * __u16 used_flags; @@ -88,18 +92,21 @@ struct vring { * struct vring_used_elem used[num]; * }; */ -static inline void vring_init(struct vring *vr, unsigned int num, void *p) +static inline void vring_init(struct vring *vr, unsigned int num, void *p, + unsigned long pagesize) { vr->num = num; vr->desc = p; - vr->avail = p + num*sizeof(struct vring); - vr->used = p + (num+1)*(sizeof(struct vring) + sizeof(__u16)); + vr->avail = p + num*sizeof(struct vring_desc); + vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1) + & ~(pagesize - 1)); } -static inline unsigned vring_size(unsigned int num) +static inline unsigned vring_size(unsigned int num, unsigned long pagesize) { - return (num + 1) * (sizeof(struct vring_desc) + sizeof(__u16)) - + sizeof(__u32) + num * sizeof(struct vring_used_elem); + return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num) + + pagesize - 1) & ~(pagesize - 1)) + + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num; } #ifdef __KERNEL__ @@ -111,7 +118,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, struct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *vq), - bool (*callback)(struct virtqueue *vq)); + void (*callback)(struct virtqueue *vq)); void vring_del_virtqueue(struct virtqueue *vq); irqreturn_t vring_interrupt(int irq, void *_vq);