aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-04-29 10:26:37 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-05-19 08:45:46 -0400
commitbbd603efb4238cf78083c00f0a81adfa8994aa33 (patch)
tree3980961f9dbf08e748b3c2de56caf43dec21aa76
parentdc3f5e68f846eec38fb31d78f0b6e83633ad375e (diff)
virtio: add_buf_gfp
Add an add_buf variant that gets gfp parameter. Use that to allocate indirect buffers. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/virtio/virtio_ring.c20
-rw-r--r--include/linux/virtio.h22
2 files changed, 28 insertions, 14 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 0717b5b000bb..1ca88908723b 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -110,13 +110,14 @@ struct vring_virtqueue
110static int vring_add_indirect(struct vring_virtqueue *vq, 110static int vring_add_indirect(struct vring_virtqueue *vq,
111 struct scatterlist sg[], 111 struct scatterlist sg[],
112 unsigned int out, 112 unsigned int out,
113 unsigned int in) 113 unsigned int in,
114 gfp_t gfp)
114{ 115{
115 struct vring_desc *desc; 116 struct vring_desc *desc;
116 unsigned head; 117 unsigned head;
117 int i; 118 int i;
118 119
119 desc = kmalloc((out + in) * sizeof(struct vring_desc), GFP_ATOMIC); 120 desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
120 if (!desc) 121 if (!desc)
121 return vq->vring.num; 122 return vq->vring.num;
122 123
@@ -155,11 +156,12 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
155 return head; 156 return head;
156} 157}
157 158
158int virtqueue_add_buf(struct virtqueue *_vq, 159int virtqueue_add_buf_gfp(struct virtqueue *_vq,
159 struct scatterlist sg[], 160 struct scatterlist sg[],
160 unsigned int out, 161 unsigned int out,
161 unsigned int in, 162 unsigned int in,
162 void *data) 163 void *data,
164 gfp_t gfp)
163{ 165{
164 struct vring_virtqueue *vq = to_vvq(_vq); 166 struct vring_virtqueue *vq = to_vvq(_vq);
165 unsigned int i, avail, head, uninitialized_var(prev); 167 unsigned int i, avail, head, uninitialized_var(prev);
@@ -171,7 +173,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
171 /* If the host supports indirect descriptor tables, and we have multiple 173 /* If the host supports indirect descriptor tables, and we have multiple
172 * buffers, then go indirect. FIXME: tune this threshold */ 174 * buffers, then go indirect. FIXME: tune this threshold */
173 if (vq->indirect && (out + in) > 1 && vq->num_free) { 175 if (vq->indirect && (out + in) > 1 && vq->num_free) {
174 head = vring_add_indirect(vq, sg, out, in); 176 head = vring_add_indirect(vq, sg, out, in, gfp);
175 if (head != vq->vring.num) 177 if (head != vq->vring.num)
176 goto add_head; 178 goto add_head;
177 } 179 }
@@ -232,7 +234,7 @@ add_head:
232 return vq->num_free ? vq->vring.num : 0; 234 return vq->num_free ? vq->vring.num : 0;
233 return vq->num_free; 235 return vq->num_free;
234} 236}
235EXPORT_SYMBOL_GPL(virtqueue_add_buf); 237EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp);
236 238
237void virtqueue_kick(struct virtqueue *_vq) 239void virtqueue_kick(struct virtqueue *_vq)
238{ 240{
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 5b0fce0d2aa2..aff5b4f74041 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -7,6 +7,7 @@
7#include <linux/spinlock.h> 7#include <linux/spinlock.h>
8#include <linux/device.h> 8#include <linux/device.h>
9#include <linux/mod_devicetable.h> 9#include <linux/mod_devicetable.h>
10#include <linux/gfp.h>
10 11
11/** 12/**
12 * virtqueue - a queue to register buffers for sending or receiving. 13 * virtqueue - a queue to register buffers for sending or receiving.
@@ -32,6 +33,7 @@ struct virtqueue {
32 * out_num: the number of sg readable by other side 33 * out_num: the number of sg readable by other side
33 * in_num: the number of sg which are writable (after readable ones) 34 * in_num: the number of sg which are writable (after readable ones)
34 * data: the token identifying the buffer. 35 * data: the token identifying the buffer.
36 * gfp: how to do memory allocations (if necessary).
35 * Returns remaining capacity of queue (sg segments) or a negative error. 37 * Returns remaining capacity of queue (sg segments) or a negative error.
36 * virtqueue_kick: update after add_buf 38 * virtqueue_kick: update after add_buf
37 * vq: the struct virtqueue 39 * vq: the struct virtqueue
@@ -60,11 +62,21 @@ struct virtqueue {
60 * All operations can be called in any context. 62 * All operations can be called in any context.
61 */ 63 */
62 64
63int virtqueue_add_buf(struct virtqueue *vq, 65int virtqueue_add_buf_gfp(struct virtqueue *vq,
64 struct scatterlist sg[], 66 struct scatterlist sg[],
65 unsigned int out_num, 67 unsigned int out_num,
66 unsigned int in_num, 68 unsigned int in_num,
67 void *data); 69 void *data,
70 gfp_t gfp);
71
72static inline int virtqueue_add_buf(struct virtqueue *vq,
73 struct scatterlist sg[],
74 unsigned int out_num,
75 unsigned int in_num,
76 void *data)
77{
78 return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC);
79}
68 80
69void virtqueue_kick(struct virtqueue *vq); 81void virtqueue_kick(struct virtqueue *vq);
70 82