Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michael S. Tsirkin and committed by
Rusty Russell
bbd603ef dc3f5e68

+28 -14
+11 -9
drivers/virtio/virtio_ring.c
··· 110 110 static int vring_add_indirect(struct vring_virtqueue *vq, 111 111 struct scatterlist sg[], 112 112 unsigned int out, 113 - unsigned int in) 113 + unsigned int in, 114 + gfp_t gfp) 114 115 { 115 116 struct vring_desc *desc; 116 117 unsigned head; 117 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 121 if (!desc) 121 122 return vq->vring.num; 122 123 ··· 156 155 return head; 157 156 } 158 157 159 - int virtqueue_add_buf(struct virtqueue *_vq, 160 - struct scatterlist sg[], 161 - unsigned int out, 162 - unsigned int in, 163 - void *data) 158 + int virtqueue_add_buf_gfp(struct virtqueue *_vq, 159 + struct scatterlist sg[], 160 + unsigned int out, 161 + unsigned int in, 162 + void *data, 163 + gfp_t gfp) 164 164 { 165 165 struct vring_virtqueue *vq = to_vvq(_vq); 166 166 unsigned int i, avail, head, uninitialized_var(prev); ··· 173 171 /* If the host supports indirect descriptor tables, and we have multiple 174 172 * buffers, then go indirect. FIXME: tune this threshold */ 175 173 if (vq->indirect && (out + in) > 1 && vq->num_free) { 176 - head = vring_add_indirect(vq, sg, out, in); 174 + head = vring_add_indirect(vq, sg, out, in, gfp); 177 175 if (head != vq->vring.num) 178 176 goto add_head; 179 177 } ··· 234 232 return vq->num_free ? vq->vring.num : 0; 235 233 return vq->num_free; 236 234 } 237 - EXPORT_SYMBOL_GPL(virtqueue_add_buf); 235 + EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp); 238 236 239 237 void virtqueue_kick(struct virtqueue *_vq) 240 238 {
+17 -5
include/linux/virtio.h
··· 7 7 #include <linux/spinlock.h> 8 8 #include <linux/device.h> 9 9 #include <linux/mod_devicetable.h> 10 + #include <linux/gfp.h> 10 11 11 12 /** 12 13 * virtqueue - a queue to register buffers for sending or receiving. ··· 33 32 * out_num: the number of sg readable by other side 34 33 * in_num: the number of sg which are writable (after readable ones) 35 34 * data: the token identifying the buffer. 35 + * gfp: how to do memory allocations (if necessary). 36 36 * Returns remaining capacity of queue (sg segments) or a negative error. 37 37 * virtqueue_kick: update after add_buf 38 38 * vq: the struct virtqueue ··· 62 60 * All operations can be called in any context. 63 61 */ 64 62 65 - int virtqueue_add_buf(struct virtqueue *vq, 66 - struct scatterlist sg[], 67 - unsigned int out_num, 68 - unsigned int in_num, 69 - void *data); 63 + int virtqueue_add_buf_gfp(struct virtqueue *vq, 64 + struct scatterlist sg[], 65 + unsigned int out_num, 66 + unsigned int in_num, 67 + void *data, 68 + gfp_t gfp); 69 + 70 + static inline int virtqueue_add_buf(struct virtqueue *vq, 71 + struct scatterlist sg[], 72 + unsigned int out_num, 73 + unsigned int in_num, 74 + void *data) 75 + { 76 + return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC); 77 + } 70 78 71 79 void virtqueue_kick(struct virtqueue *vq); 72 80