aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-02-03 00:46:37 -0500
committerMichael S. Tsirkin <mst@redhat.com>2016-03-02 10:01:57 -0500
commit2a2d1382fe9dccfce6f9c60a9c9fd2f0fe5bcf2b (patch)
treeab3783be11369f689e3e7aebe0c438ab6746375f
parent780bc7903a32edb63be138487fd981694d993610 (diff)
virtio: Add improved queue allocation API
This leaves vring_new_virtqueue alone for compatbility, but it adds two new improved APIs: vring_create_virtqueue: Creates a virtqueue backed by automatically allocated coherent memory. (Some day it this could be extended to support non-coherent memory, too, if there ends up being a platform on which it's worthwhile.) __vring_new_virtqueue: Creates a virtqueue with a manually-specified layout. This should allow mic_virtio to work much more cleanly. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/virtio/virtio_ring.c209
-rw-r--r--include/linux/virtio.h23
-rw-r--r--include/linux/virtio_ring.h35
3 files changed, 235 insertions, 32 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 9abc008ff7ea..e46d08107a50 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -95,6 +95,11 @@ struct vring_virtqueue {
95 /* How to notify other side. FIXME: commonalize hcalls! */ 95 /* How to notify other side. FIXME: commonalize hcalls! */
96 bool (*notify)(struct virtqueue *vq); 96 bool (*notify)(struct virtqueue *vq);
97 97
98 /* DMA, allocation, and size information */
99 bool we_own_ring;
100 size_t queue_size_in_bytes;
101 dma_addr_t queue_dma_addr;
102
98#ifdef DEBUG 103#ifdef DEBUG
99 /* They're supposed to lock for us. */ 104 /* They're supposed to lock for us. */
100 unsigned int in_use; 105 unsigned int in_use;
@@ -878,36 +883,31 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
878} 883}
879EXPORT_SYMBOL_GPL(vring_interrupt); 884EXPORT_SYMBOL_GPL(vring_interrupt);
880 885
881struct virtqueue *vring_new_virtqueue(unsigned int index, 886struct virtqueue *__vring_new_virtqueue(unsigned int index,
882 unsigned int num, 887 struct vring vring,
883 unsigned int vring_align, 888 struct virtio_device *vdev,
884 struct virtio_device *vdev, 889 bool weak_barriers,
885 bool weak_barriers, 890 bool (*notify)(struct virtqueue *),
886 void *pages, 891 void (*callback)(struct virtqueue *),
887 bool (*notify)(struct virtqueue *), 892 const char *name)
888 void (*callback)(struct virtqueue *),
889 const char *name)
890{ 893{
891 struct vring_virtqueue *vq;
892 unsigned int i; 894 unsigned int i;
895 struct vring_virtqueue *vq;
893 896
894 /* We assume num is a power of 2. */ 897 vq = kmalloc(sizeof(*vq) + vring.num * sizeof(struct vring_desc_state),
895 if (num & (num - 1)) {
896 dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
897 return NULL;
898 }
899
900 vq = kmalloc(sizeof(*vq) + num * sizeof(struct vring_desc_state),
901 GFP_KERNEL); 898 GFP_KERNEL);
902 if (!vq) 899 if (!vq)
903 return NULL; 900 return NULL;
904 901
905 vring_init(&vq->vring, num, pages, vring_align); 902 vq->vring = vring;
906 vq->vq.callback = callback; 903 vq->vq.callback = callback;
907 vq->vq.vdev = vdev; 904 vq->vq.vdev = vdev;
908 vq->vq.name = name; 905 vq->vq.name = name;
909 vq->vq.num_free = num; 906 vq->vq.num_free = vring.num;
910 vq->vq.index = index; 907 vq->vq.index = index;
908 vq->we_own_ring = false;
909 vq->queue_dma_addr = 0;
910 vq->queue_size_in_bytes = 0;
911 vq->notify = notify; 911 vq->notify = notify;
912 vq->weak_barriers = weak_barriers; 912 vq->weak_barriers = weak_barriers;
913 vq->broken = false; 913 vq->broken = false;
@@ -932,18 +932,145 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
932 932
933 /* Put everything in free lists. */ 933 /* Put everything in free lists. */
934 vq->free_head = 0; 934 vq->free_head = 0;
935 for (i = 0; i < num-1; i++) 935 for (i = 0; i < vring.num-1; i++)
936 vq->vring.desc[i].next = cpu_to_virtio16(vdev, i + 1); 936 vq->vring.desc[i].next = cpu_to_virtio16(vdev, i + 1);
937 memset(vq->desc_state, 0, num * sizeof(struct vring_desc_state)); 937 memset(vq->desc_state, 0, vring.num * sizeof(struct vring_desc_state));
938 938
939 return &vq->vq; 939 return &vq->vq;
940} 940}
941EXPORT_SYMBOL_GPL(__vring_new_virtqueue);
942
943static void *vring_alloc_queue(struct virtio_device *vdev, size_t size,
944 dma_addr_t *dma_handle, gfp_t flag)
945{
946 if (vring_use_dma_api(vdev)) {
947 return dma_alloc_coherent(vdev->dev.parent, size,
948 dma_handle, flag);
949 } else {
950 void *queue = alloc_pages_exact(PAGE_ALIGN(size), flag);
951 if (queue) {
952 phys_addr_t phys_addr = virt_to_phys(queue);
953 *dma_handle = (dma_addr_t)phys_addr;
954
955 /*
956 * Sanity check: make sure we dind't truncate
957 * the address. The only arches I can find that
958 * have 64-bit phys_addr_t but 32-bit dma_addr_t
959 * are certain non-highmem MIPS and x86
960 * configurations, but these configurations
961 * should never allocate physical pages above 32
962 * bits, so this is fine. Just in case, throw a
963 * warning and abort if we end up with an
964 * unrepresentable address.
965 */
966 if (WARN_ON_ONCE(*dma_handle != phys_addr)) {
967 free_pages_exact(queue, PAGE_ALIGN(size));
968 return NULL;
969 }
970 }
971 return queue;
972 }
973}
974
975static void vring_free_queue(struct virtio_device *vdev, size_t size,
976 void *queue, dma_addr_t dma_handle)
977{
978 if (vring_use_dma_api(vdev)) {
979 dma_free_coherent(vdev->dev.parent, size, queue, dma_handle);
980 } else {
981 free_pages_exact(queue, PAGE_ALIGN(size));
982 }
983}
984
985struct virtqueue *vring_create_virtqueue(
986 unsigned int index,
987 unsigned int num,
988 unsigned int vring_align,
989 struct virtio_device *vdev,
990 bool weak_barriers,
991 bool may_reduce_num,
992 bool (*notify)(struct virtqueue *),
993 void (*callback)(struct virtqueue *),
994 const char *name)
995{
996 struct virtqueue *vq;
997 void *queue;
998 dma_addr_t dma_addr;
999 size_t queue_size_in_bytes;
1000 struct vring vring;
1001
1002 /* We assume num is a power of 2. */
1003 if (num & (num - 1)) {
1004 dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
1005 return NULL;
1006 }
1007
1008 /* TODO: allocate each queue chunk individually */
1009 for (; num && vring_size(num, vring_align) > PAGE_SIZE; num /= 2) {
1010 queue = vring_alloc_queue(vdev, vring_size(num, vring_align),
1011 &dma_addr,
1012 GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
1013 if (queue)
1014 break;
1015 }
1016
1017 if (!num)
1018 return NULL;
1019
1020 if (!queue) {
1021 /* Try to get a single page. You are my only hope! */
1022 queue = vring_alloc_queue(vdev, vring_size(num, vring_align),
1023 &dma_addr, GFP_KERNEL|__GFP_ZERO);
1024 }
1025 if (!queue)
1026 return NULL;
1027
1028 queue_size_in_bytes = vring_size(num, vring_align);
1029 vring_init(&vring, num, queue, vring_align);
1030
1031 vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers,
1032 notify, callback, name);
1033 if (!vq) {
1034 vring_free_queue(vdev, queue_size_in_bytes, queue,
1035 dma_addr);
1036 return NULL;
1037 }
1038
1039 to_vvq(vq)->queue_dma_addr = dma_addr;
1040 to_vvq(vq)->queue_size_in_bytes = queue_size_in_bytes;
1041 to_vvq(vq)->we_own_ring = true;
1042
1043 return vq;
1044}
1045EXPORT_SYMBOL_GPL(vring_create_virtqueue);
1046
1047struct virtqueue *vring_new_virtqueue(unsigned int index,
1048 unsigned int num,
1049 unsigned int vring_align,
1050 struct virtio_device *vdev,
1051 bool weak_barriers,
1052 void *pages,
1053 bool (*notify)(struct virtqueue *vq),
1054 void (*callback)(struct virtqueue *vq),
1055 const char *name)
1056{
1057 struct vring vring;
1058 vring_init(&vring, num, pages, vring_align);
1059 return __vring_new_virtqueue(index, vring, vdev, weak_barriers,
1060 notify, callback, name);
1061}
941EXPORT_SYMBOL_GPL(vring_new_virtqueue); 1062EXPORT_SYMBOL_GPL(vring_new_virtqueue);
942 1063
943void vring_del_virtqueue(struct virtqueue *vq) 1064void vring_del_virtqueue(struct virtqueue *_vq)
944{ 1065{
945 list_del(&vq->list); 1066 struct vring_virtqueue *vq = to_vvq(_vq);
946 kfree(to_vvq(vq)); 1067
1068 if (vq->we_own_ring) {
1069 vring_free_queue(vq->vq.vdev, vq->queue_size_in_bytes,
1070 vq->vring.desc, vq->queue_dma_addr);
1071 }
1072 list_del(&_vq->list);
1073 kfree(vq);
947} 1074}
948EXPORT_SYMBOL_GPL(vring_del_virtqueue); 1075EXPORT_SYMBOL_GPL(vring_del_virtqueue);
949 1076
@@ -1007,20 +1134,42 @@ void virtio_break_device(struct virtio_device *dev)
1007} 1134}
1008EXPORT_SYMBOL_GPL(virtio_break_device); 1135EXPORT_SYMBOL_GPL(virtio_break_device);
1009 1136
1010void *virtqueue_get_avail(struct virtqueue *_vq) 1137dma_addr_t virtqueue_get_desc_addr(struct virtqueue *_vq)
1011{ 1138{
1012 struct vring_virtqueue *vq = to_vvq(_vq); 1139 struct vring_virtqueue *vq = to_vvq(_vq);
1013 1140
1014 return vq->vring.avail; 1141 BUG_ON(!vq->we_own_ring);
1142
1143 return vq->queue_dma_addr;
1015} 1144}
1016EXPORT_SYMBOL_GPL(virtqueue_get_avail); 1145EXPORT_SYMBOL_GPL(virtqueue_get_desc_addr);
1017 1146
1018void *virtqueue_get_used(struct virtqueue *_vq) 1147dma_addr_t virtqueue_get_avail_addr(struct virtqueue *_vq)
1019{ 1148{
1020 struct vring_virtqueue *vq = to_vvq(_vq); 1149 struct vring_virtqueue *vq = to_vvq(_vq);
1021 1150
1022 return vq->vring.used; 1151 BUG_ON(!vq->we_own_ring);
1152
1153 return vq->queue_dma_addr +
1154 ((char *)vq->vring.avail - (char *)vq->vring.desc);
1155}
1156EXPORT_SYMBOL_GPL(virtqueue_get_avail_addr);
1157
1158dma_addr_t virtqueue_get_used_addr(struct virtqueue *_vq)
1159{
1160 struct vring_virtqueue *vq = to_vvq(_vq);
1161
1162 BUG_ON(!vq->we_own_ring);
1163
1164 return vq->queue_dma_addr +
1165 ((char *)vq->vring.used - (char *)vq->vring.desc);
1166}
1167EXPORT_SYMBOL_GPL(virtqueue_get_used_addr);
1168
1169const struct vring *virtqueue_get_vring(struct virtqueue *vq)
1170{
1171 return &to_vvq(vq)->vring;
1023} 1172}
1024EXPORT_SYMBOL_GPL(virtqueue_get_used); 1173EXPORT_SYMBOL_GPL(virtqueue_get_vring);
1025 1174
1026MODULE_LICENSE("GPL"); 1175MODULE_LICENSE("GPL");
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 8f4d4bfa6d46..d5eb5479a425 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -75,8 +75,27 @@ unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
75 75
76bool virtqueue_is_broken(struct virtqueue *vq); 76bool virtqueue_is_broken(struct virtqueue *vq);
77 77
78void *virtqueue_get_avail(struct virtqueue *vq); 78const struct vring *virtqueue_get_vring(struct virtqueue *vq);
79void *virtqueue_get_used(struct virtqueue *vq); 79dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
80dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
81dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
82
83/*
84 * Legacy accessors -- in almost all cases, these are the wrong functions
85 * to use.
86 */
87static inline void *virtqueue_get_desc(struct virtqueue *vq)
88{
89 return virtqueue_get_vring(vq)->desc;
90}
91static inline void *virtqueue_get_avail(struct virtqueue *vq)
92{
93 return virtqueue_get_vring(vq)->avail;
94}
95static inline void *virtqueue_get_used(struct virtqueue *vq)
96{
97 return virtqueue_get_vring(vq)->used;
98}
80 99
81/** 100/**
82 * virtio_device - representation of a device using virtio 101 * virtio_device - representation of a device using virtio
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index a156e2b6ccfe..e8d36938f09a 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -59,6 +59,35 @@ static inline void virtio_store_mb(bool weak_barriers,
59struct virtio_device; 59struct virtio_device;
60struct virtqueue; 60struct virtqueue;
61 61
62/*
63 * Creates a virtqueue and allocates the descriptor ring. If
64 * may_reduce_num is set, then this may allocate a smaller ring than
65 * expected. The caller should query virtqueue_get_ring_size to learn
66 * the actual size of the ring.
67 */
68struct virtqueue *vring_create_virtqueue(unsigned int index,
69 unsigned int num,
70 unsigned int vring_align,
71 struct virtio_device *vdev,
72 bool weak_barriers,
73 bool may_reduce_num,
74 bool (*notify)(struct virtqueue *vq),
75 void (*callback)(struct virtqueue *vq),
76 const char *name);
77
78/* Creates a virtqueue with a custom layout. */
79struct virtqueue *__vring_new_virtqueue(unsigned int index,
80 struct vring vring,
81 struct virtio_device *vdev,
82 bool weak_barriers,
83 bool (*notify)(struct virtqueue *),
84 void (*callback)(struct virtqueue *),
85 const char *name);
86
87/*
88 * Creates a virtqueue with a standard layout but a caller-allocated
89 * ring.
90 */
62struct virtqueue *vring_new_virtqueue(unsigned int index, 91struct virtqueue *vring_new_virtqueue(unsigned int index,
63 unsigned int num, 92 unsigned int num,
64 unsigned int vring_align, 93 unsigned int vring_align,
@@ -68,7 +97,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
68 bool (*notify)(struct virtqueue *vq), 97 bool (*notify)(struct virtqueue *vq),
69 void (*callback)(struct virtqueue *vq), 98 void (*callback)(struct virtqueue *vq),
70 const char *name); 99 const char *name);
100
101/*
102 * Destroys a virtqueue. If created with vring_create_virtqueue, this
103 * also frees the ring.
104 */
71void vring_del_virtqueue(struct virtqueue *vq); 105void vring_del_virtqueue(struct virtqueue *vq);
106
72/* Filter out transport-specific feature bits. */ 107/* Filter out transport-specific feature bits. */
73void vring_transport_features(struct virtio_device *vdev); 108void vring_transport_features(struct virtio_device *vdev);
74 109