virtio: put an explicit threshold in the virtio_ring

Experiment.  Unfinished.

FIXME: Adjust vring_size

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 include/linux/virtio_ring.h |   32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff -r 7fd3abcb9848 include/linux/virtio_ring.h
--- a/include/linux/virtio_ring.h	Wed Jun 25 18:19:10 2008 +1000
+++ b/include/linux/virtio_ring.h	Wed Jun 25 19:19:36 2008 +1000
@@ -26,6 +26,8 @@
 
 /* We publish our last-seen used index at the end of the avail ring. */
 #define VIRTIO_RING_F_PUBLISH_INDICES	28
+/* Threshold for notifications/interrupts */
+#define VIRTIO_RING_F_THRESHOLD		29
 
 /* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
 struct vring_desc
@@ -63,6 +65,13 @@ struct vring_used
 	struct vring_used_elem ring[];
 };
 
+struct vring_tailer {
+	/* Consumed count */
+	__u16 last_seen;
+	/* Threshold to notify/interrupt */
+	__u16 threshold;
+};
+
 struct vring {
 	unsigned int num;
 
@@ -87,6 +97,9 @@ struct vring {
  *	__u16 available[num];
  *	__u16 last_used_idx;
  *
+ *	__u16 last_seen_avail;
+ *	__u16 avail_threshold;
+ *
  *	// Padding to the next page boundary.
  *	char pad[];
  *
@@ -95,6 +108,9 @@ struct vring {
  *	__u16 used_idx;
  *	struct vring_used_elem used[num];
  *	__u16 last_avail_idx;
+ *
+ *	__u16 last_seen_used;
+ *	__u16 used_threshold;
  * };
  */
 static inline void vring_init(struct vring *vr, unsigned int num, void *p,
@@ -116,8 +132,21 @@ static inline unsigned vring_size(unsign
 
 /* We publish the last-seen used index at the end of the available ring, and
  * vice-versa.  These are at the end for backwards compatibility. */
-#define vring_last_used(vr) ((vr)->avail->ring[(vr)->num])
-#define vring_last_avail(vr) (*(__u16 *)&(vr)->used->ring[(vr)->num])
+static inline struct vring_tailer *vring_avail_tailer(const struct vring *vr)
+{
+	return (struct vring_tailer *)&(vr->used->ring[vr->num]);
+}
+
+static inline struct vring_tailer *vring_used_tailer(const struct vring *vr)
+{
+	return (struct vring_tailer *)&(vr-avail->ring[vr->num]);
+}
+
+#define vring_last_used(vr) (&vring_avail_tailer(vr)->last_seen)
+#define vring_last_avail(vr) (&vring_used_tailer(vr)->last_seen)
+
+#define vring_avail_threshold(vr) (&vring_used_tailer(vr)->threshold)
+#define vring_used_threshold(vr) (&vring_avail_tailer(vr)->threshold)
 
 #ifdef __KERNEL__
 #include <linux/irqreturn.h>
