---
 drivers/virtio/virtio_ring.c |   36 ++++++++++++++++++++++--------------
 include/linux/virtio.h       |   10 ++++------
 2 files changed, 26 insertions(+), 20 deletions(-)

diff -r b3aec596b841 drivers/virtio/virtio_ring.c
--- a/drivers/virtio/virtio_ring.c	Mon Jan 07 12:43:56 2008 +1100
+++ b/drivers/virtio/virtio_ring.c	Mon Jan 07 13:28:21 2008 +1100
@@ -71,16 +71,28 @@ struct vring_virtqueue
 
 #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
 
+static unsigned int count_sg(struct scatterlist *sg)
+{
+	unsigned int count;
+
+	for (count = 0; sg; sg = sg_next(sg))
+		count++;
+	return count;
+}
+
 static int vring_add_buf(struct virtqueue *_vq,
-			 struct scatterlist sg[],
-			 unsigned int out,
-			 unsigned int in,
+			 struct scatterlist *out_sg,
+			 struct scatterlist *in_sg,
 			 void *data)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
-	unsigned int i, avail, head, uninitialized_var(prev);
+	unsigned int in, out, i, avail, head, uninitialized_var(prev);
 
 	BUG_ON(data == NULL);
+
+	out = count_sg(out_sg);
+	in = count_sg(in_sg);
+
 	BUG_ON(out + in > vq->vring.num);
 	BUG_ON(out + in == 0);
 
@@ -97,21 +109,17 @@ static int vring_add_buf(struct virtqueu
 	vq->num_free -= out + in;
 
 	head = vq->free_head;
-	for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
+	for (i = vq->free_head; out_sg; i = vq->vring.desc[i].next, out_sg = sg_next(out_sg)) {
 		vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
-		vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
-			+ sg->offset;
-		vq->vring.desc[i].len = sg->length;
+		vq->vring.desc[i].addr = sg_phys(out_sg);
+		vq->vring.desc[i].len = out_sg->length;
 		prev = i;
-		sg++;
 	}
-	for (; in; i = vq->vring.desc[i].next, in--) {
+	for (; in_sg; i = vq->vring.desc[i].next, in_sg = sg_next(in_sg)) {
 		vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
-		vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
-			+ sg->offset;
-		vq->vring.desc[i].len = sg->length;
+		vq->vring.desc[i].addr = sg_phys(in_sg);
+		vq->vring.desc[i].len = in_sg->length;
 		prev = i;
-		sg++;
 	}
 	/* Last one doesn't continue. */
 	vq->vring.desc[prev].flags &= ~VRING_DESC_F_NEXT;
diff -r b3aec596b841 include/linux/virtio.h
--- a/include/linux/virtio.h	Mon Jan 07 12:43:56 2008 +1100
+++ b/include/linux/virtio.h	Mon Jan 07 13:28:21 2008 +1100
@@ -27,9 +27,8 @@ struct virtqueue
  * virtqueue_ops - operations for virtqueue abstraction layer
  * @add_buf: expose buffer to other end
  *	vq: the struct virtqueue we're talking about.
- *	sg: the description of the buffer(s).
- *	out_num: the number of sg readable by other side
- *	in_num: the number of sg which are writable (after readable ones)
+ *	out_sg: the sgs readable by other side
+ *	in_sg: the sgs which are writable
  *	data: the token identifying the buffer.
  *      Returns 0 or an error.
  * @kick: update after add_buf
@@ -56,9 +55,8 @@ struct virtqueue
  */
 struct virtqueue_ops {
 	int (*add_buf)(struct virtqueue *vq,
-		       struct scatterlist sg[],
-		       unsigned int out_num,
-		       unsigned int in_num,
+		       struct scatterlist *out_sg,
+		       struct scatterlist *in_sg,
 		       void *data);
 
 	void (*kick)(struct virtqueue *vq);
