From patchwork Thu Feb 7 12:22:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 2110451 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 9C37F40E3A for ; Thu, 7 Feb 2013 12:23:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758436Ab3BGMXG (ORCPT ); Thu, 7 Feb 2013 07:23:06 -0500 Received: from mail-ve0-f178.google.com ([209.85.128.178]:41099 "EHLO mail-ve0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757845Ab3BGMXE (ORCPT ); Thu, 7 Feb 2013 07:23:04 -0500 Received: by mail-ve0-f178.google.com with SMTP id db10so2188184veb.23 for ; Thu, 07 Feb 2013 04:23:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=TutsPiNoEuCkzwWag5BdqEwDtWfIp5yavnB+59S0T8s=; b=mLJ62rL3JIo5PjU2+skCOzXh3DVKgLEl/ApYrVtE1cA2rEGt4tlUkoW4OKwILv9dOM 27I5AbhzgWtlBnX0hHksavS3fXl9iHSBMx8+KrB7aMR+53vjvtCs4biPqRwSYnyFoK/m H/mlREbqJVTGZYAw26+m3Ju6OB6Vrl53xVIWVza01MqYBxGr6pB3AmLnEIh6l1VMdJ12 LOMh0oLAcK2/jFVb36td8whkP6jJInu1lrNmv55o87DjWFFxGTjXdNRt4/zNlouY5Ffw G/cVx5U9muwNIM7Rl7PpSahk0Cn2gwvAGZikgGXW9UHdXdQ64x0lUzVNTY09WnK//vOl BEgA== X-Received: by 10.220.156.10 with SMTP id u10mr1299595vcw.28.1360239783344; Thu, 07 Feb 2013 04:23:03 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-179-137.ip50.fastwebnet.it. [93.34.179.137]) by mx.google.com with ESMTPS id sk8sm37937888vdb.13.2013.02.07.04.23.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 07 Feb 2013 04:23:02 -0800 (PST) From: Paolo Bonzini To: linux-kernel@vger.kernel.org Cc: Wanlong Gao , asias@redhat.com, Rusty Russell , mst@redhat.com, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org Subject: [RFC PATCH 8/8] virtio: reimplement virtqueue_add_buf using new functions Date: Thu, 7 Feb 2013 13:22:32 +0100 Message-Id: <1360239752-2470-9-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1360239752-2470-1-git-send-email-pbonzini@redhat.com> References: <1360239752-2470-1-git-send-email-pbonzini@redhat.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Eliminate the code duplication between virtqueue_add_buf and virtqueue_add_sg. That's safe to do now that no devices will pass scatterlists with a termination marker in the middle. Signed-off-by: Paolo Bonzini --- drivers/virtio/virtio_ring.c | 157 +++--------------------------------------- 1 files changed, 11 insertions(+), 146 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 25f56e6..d19113d 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -119,63 +119,6 @@ struct vring_virtqueue #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) -/* Set up an indirect table of descriptors and add it to the queue. */ -static int vring_add_indirect(struct vring_virtqueue *vq, - struct scatterlist sg[], - unsigned int out, - unsigned int in, - gfp_t gfp) -{ - struct vring_desc *desc; - unsigned head; - int i; - - /* - * We require lowmem mappings for the descriptors because - * otherwise virt_to_phys will give us bogus addresses in the - * virtqueue. - */ - gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); - - desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); - if (!desc) - return -ENOMEM; - - /* Transfer entries from the sg list into the indirect page */ - for (i = 0; i < out; i++) { - desc[i].flags = VRING_DESC_F_NEXT; - desc[i].addr = sg_phys(sg); - desc[i].len = sg->length; - desc[i].next = i+1; - sg++; - } - for (; i < (out + in); i++) { - desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - desc[i].addr = sg_phys(sg); - desc[i].len = sg->length; - desc[i].next = i+1; - sg++; - } - - /* Last one doesn't continue. */ - desc[i-1].flags &= ~VRING_DESC_F_NEXT; - desc[i-1].next = 0; - - /* We're about to use a buffer */ - vq->vq.num_free--; - - /* Use a single buffer which doesn't continue */ - head = vq->free_head; - vq->vring.desc[head].flags = VRING_DESC_F_INDIRECT; - vq->vring.desc[head].addr = virt_to_phys(desc); - vq->vring.desc[head].len = i * sizeof(struct vring_desc); - - /* Update free pointer */ - vq->free_head = vq->vring.desc[head].next; - - return head; -} - /** * virtqueue_add_buf - expose buffer to other end * @vq: the struct virtqueue we're talking about. @@ -190,104 +133,26 @@ static int vring_add_indirect(struct vring_virtqueue *vq, * * Returns zero or a negative error (ie. ENOSPC, ENOMEM). */ -int virtqueue_add_buf(struct virtqueue *_vq, +int virtqueue_add_buf(struct virtqueue *vq, struct scatterlist sg[], unsigned int out, unsigned int in, void *data, gfp_t gfp) { - struct vring_virtqueue *vq = to_vvq(_vq); - unsigned int i, avail, uninitialized_var(prev); - int head; - - START_USE(vq); - - BUG_ON(data == NULL); - -#ifdef DEBUG - { - ktime_t now = ktime_get(); + struct virtqueue_buf buf; + int ret; - /* No kick or get, with .1 second between? Warn. */ - if (vq->last_add_time_valid) - WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time)) - > 100); - vq->last_add_time = now; - vq->last_add_time_valid = true; - } -#endif + ret = virtqueue_start_buf(vq, &buf, data, out + in, !!out + !!in, gfp); + if (ret < 0) + return ret; - /* If the host supports indirect descriptor tables, and we have multiple - * buffers, then go indirect. FIXME: tune this threshold */ - if (vq->indirect && (out + in) > 1 && vq->vq.num_free) { - head = vring_add_indirect(vq, sg, out, in, gfp); - if (likely(head >= 0)) - goto add_head; - } - - BUG_ON(out + in > vq->vring.num); - BUG_ON(out + in == 0); - - if (vq->vq.num_free < out + in) { - pr_debug("Can't add buf len %i - avail = %i\n", - out + in, vq->vq.num_free); - /* FIXME: for historical reasons, we force a notify here if - * there are outgoing parts to the buffer. Presumably the - * host should service the ring ASAP. */ - if (out) - vq->notify(&vq->vq); - END_USE(vq); - return -ENOSPC; - } - - /* We're about to use some buffers from the free list. */ - vq->vq.num_free -= out + in; - - head = vq->free_head; - for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) { - vq->vring.desc[i].flags = VRING_DESC_F_NEXT; - vq->vring.desc[i].addr = sg_phys(sg); - vq->vring.desc[i].len = sg->length; - prev = i; - sg++; - } - for (; in; i = vq->vring.desc[i].next, in--) { - vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - vq->vring.desc[i].addr = sg_phys(sg); - vq->vring.desc[i].len = sg->length; - prev = i; - sg++; - } - /* Last one doesn't continue. */ - vq->vring.desc[prev].flags &= ~VRING_DESC_F_NEXT; - - /* Update free pointer */ - vq->free_head = i; - -add_head: - /* Set token. */ - vq->data[head] = data; - - /* Put entry in available array (but don't update avail->idx until they - * do sync). */ - avail = (vq->vring.avail->idx & (vq->vring.num-1)); - vq->vring.avail->ring[avail] = head; - - /* Descriptors and available array need to be set before we expose the - * new available array entries. */ - virtio_wmb(vq); - vq->vring.avail->idx++; - vq->num_added++; - - /* This is very unlikely, but theoretically possible. Kick - * just in case. */ - if (unlikely(vq->num_added == (1 << 16) - 1)) - virtqueue_kick(_vq); - - pr_debug("Added buffer head %i to %p\n", head, vq); - END_USE(vq); + if (out) + virtqueue_add_sg(&buf, sg, out, DMA_TO_DEVICE); + if (in) + virtqueue_add_sg(&buf, sg + out, in, DMA_FROM_DEVICE); + virtqueue_end_buf(&buf); return 0; } EXPORT_SYMBOL_GPL(virtqueue_add_buf);