aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeinz Graalfs <graalfs@linux.vnet.ibm.com>2013-10-28 19:08:50 -0400
committerRusty Russell <rusty@rustcorp.com.au>2013-10-28 20:58:11 -0400
commit46f9c2b925ac12e5ad8b8b7c90c71dacc9d5db37 (patch)
tree39b9bd752cb3cb43a5e11d4f0fc35f425f1d02e2
parent630b54d33493d1f67e79b148b5e361c5bbd3f29d (diff)
virtio_ring: change host notification API
Currently a host kick error is silently ignored and not reflected in the virtqueue of a particular virtio device. Changing the notify API for guest->host notification seems to be one prerequisite in order to be able to handle such errors in the context where the kick is triggered. This patch changes the notify API. The notify function must return a bool return value. It returns false if the host notification failed. Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/lguest_device.c3
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c3
-rw-r--r--drivers/s390/kvm/kvm_virtio.c8
-rw-r--r--drivers/s390/kvm/virtio_ccw.c5
-rw-r--r--drivers/virtio/virtio_mmio.c3
-rw-r--r--drivers/virtio/virtio_pci.c3
-rw-r--r--drivers/virtio/virtio_ring.c4
-rw-r--r--include/linux/virtio_ring.h2
-rw-r--r--tools/virtio/virtio_test.c3
-rw-r--r--tools/virtio/vringh_test.c13
10 files changed, 32 insertions, 15 deletions
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index b3256ff0d426..d0a1d8a45c81 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -229,7 +229,7 @@ struct lguest_vq_info {
229 * make a hypercall. We hand the physical address of the virtqueue so the Host 229 * make a hypercall. We hand the physical address of the virtqueue so the Host
230 * knows which virtqueue we're talking about. 230 * knows which virtqueue we're talking about.
231 */ 231 */
232static void lg_notify(struct virtqueue *vq) 232static bool lg_notify(struct virtqueue *vq)
233{ 233{
234 /* 234 /*
235 * We store our virtqueue information in the "priv" pointer of the 235 * We store our virtqueue information in the "priv" pointer of the
@@ -238,6 +238,7 @@ static void lg_notify(struct virtqueue *vq)
238 struct lguest_vq_info *lvq = vq->priv; 238 struct lguest_vq_info *lvq = vq->priv;
239 239
240 hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0); 240 hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
241 return true;
241} 242}
242 243
243/* An extern declaration inside a C file is bad form. Don't do it. */ 244/* An extern declaration inside a C file is bad form. Don't do it. */
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index b09c75c21b60..a34b50690b4e 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -30,7 +30,7 @@
30#include "remoteproc_internal.h" 30#include "remoteproc_internal.h"
31 31
32/* kick the remote processor, and let it know which virtqueue to poke at */ 32/* kick the remote processor, and let it know which virtqueue to poke at */
33static void rproc_virtio_notify(struct virtqueue *vq) 33static bool rproc_virtio_notify(struct virtqueue *vq)
34{ 34{
35 struct rproc_vring *rvring = vq->priv; 35 struct rproc_vring *rvring = vq->priv;
36 struct rproc *rproc = rvring->rvdev->rproc; 36 struct rproc *rproc = rvring->rvdev->rproc;
@@ -39,6 +39,7 @@ static void rproc_virtio_notify(struct virtqueue *vq)
39 dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); 39 dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);
40 40
41 rproc->ops->kick(rproc, notifyid); 41 rproc->ops->kick(rproc, notifyid);
42 return true;
42} 43}
43 44
44/** 45/**
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index af2166fa5159..1abd0db29915 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -166,11 +166,15 @@ static void kvm_reset(struct virtio_device *vdev)
166 * make a hypercall. We hand the address of the virtqueue so the Host 166 * make a hypercall. We hand the address of the virtqueue so the Host
167 * knows which virtqueue we're talking about. 167 * knows which virtqueue we're talking about.
168 */ 168 */
169static void kvm_notify(struct virtqueue *vq) 169static bool kvm_notify(struct virtqueue *vq)
170{ 170{
171 long rc;
171 struct kvm_vqconfig *config = vq->priv; 172 struct kvm_vqconfig *config = vq->priv;
172 173
173 kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); 174 rc = kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address);
175 if (rc < 0)
176 return false;
177 return true;
174} 178}
175 179
176/* 180/*
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c
index 779dc5136291..d6297176ab85 100644
--- a/drivers/s390/kvm/virtio_ccw.c
+++ b/drivers/s390/kvm/virtio_ccw.c
@@ -162,7 +162,7 @@ static inline long do_kvm_notify(struct subchannel_id schid,
162 return __rc; 162 return __rc;
163} 163}
164 164
165static void virtio_ccw_kvm_notify(struct virtqueue *vq) 165static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
166{ 166{
167 struct virtio_ccw_vq_info *info = vq->priv; 167 struct virtio_ccw_vq_info *info = vq->priv;
168 struct virtio_ccw_device *vcdev; 168 struct virtio_ccw_device *vcdev;
@@ -171,6 +171,9 @@ static void virtio_ccw_kvm_notify(struct virtqueue *vq)
171 vcdev = to_vc_device(info->vq->vdev); 171 vcdev = to_vc_device(info->vq->vdev);
172 ccw_device_get_schid(vcdev->cdev, &schid); 172 ccw_device_get_schid(vcdev->cdev, &schid);
173 info->cookie = do_kvm_notify(schid, vq->index, info->cookie); 173 info->cookie = do_kvm_notify(schid, vq->index, info->cookie);
174 if (info->cookie < 0)
175 return false;
176 return true;
174} 177}
175 178
176static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, 179static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 1ba0d6831015..e9fdeb861992 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -219,13 +219,14 @@ static void vm_reset(struct virtio_device *vdev)
219/* Transport interface */ 219/* Transport interface */
220 220
221/* the notify function used when creating a virt queue */ 221/* the notify function used when creating a virt queue */
222static void vm_notify(struct virtqueue *vq) 222static bool vm_notify(struct virtqueue *vq)
223{ 223{
224 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); 224 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
225 225
226 /* We write the queue's selector into the notification register to 226 /* We write the queue's selector into the notification register to
227 * signal the other end */ 227 * signal the other end */
228 writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); 228 writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
229 return true;
229} 230}
230 231
231/* Notify all virtqueues on an interrupt. */ 232/* Notify all virtqueues on an interrupt. */
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 98917fc872a4..a37c69941d30 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -197,13 +197,14 @@ static void vp_reset(struct virtio_device *vdev)
197} 197}
198 198
199/* the notify function used when creating a virt queue */ 199/* the notify function used when creating a virt queue */
200static void vp_notify(struct virtqueue *vq) 200static bool vp_notify(struct virtqueue *vq)
201{ 201{
202 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); 202 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
203 203
204 /* we write the queue's selector into the notification register to 204 /* we write the queue's selector into the notification register to
205 * signal the other end */ 205 * signal the other end */
206 iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); 206 iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
207 return true;
207} 208}
208 209
209/* Handle a configuration change: Tell driver if it wants to know. */ 210/* Handle a configuration change: Tell driver if it wants to know. */
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 6547d46171b3..97dd51619b55 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -81,7 +81,7 @@ struct vring_virtqueue
81 u16 last_used_idx; 81 u16 last_used_idx;
82 82
83 /* How to notify other side. FIXME: commonalize hcalls! */ 83 /* How to notify other side. FIXME: commonalize hcalls! */
84 void (*notify)(struct virtqueue *vq); 84 bool (*notify)(struct virtqueue *vq);
85 85
86#ifdef DEBUG 86#ifdef DEBUG
87 /* They're supposed to lock for us. */ 87 /* They're supposed to lock for us. */
@@ -744,7 +744,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
744 struct virtio_device *vdev, 744 struct virtio_device *vdev,
745 bool weak_barriers, 745 bool weak_barriers,
746 void *pages, 746 void *pages,
747 void (*notify)(struct virtqueue *), 747 bool (*notify)(struct virtqueue *),
748 void (*callback)(struct virtqueue *), 748 void (*callback)(struct virtqueue *),
749 const char *name) 749 const char *name)
750{ 750{
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index b300787af8e0..67e06fe18c03 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -71,7 +71,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
71 struct virtio_device *vdev, 71 struct virtio_device *vdev,
72 bool weak_barriers, 72 bool weak_barriers,
73 void *pages, 73 void *pages,
74 void (*notify)(struct virtqueue *vq), 74 bool (*notify)(struct virtqueue *vq),
75 void (*callback)(struct virtqueue *vq), 75 void (*callback)(struct virtqueue *vq),
76 const char *name); 76 const char *name);
77void vring_del_virtqueue(struct virtqueue *vq); 77void vring_del_virtqueue(struct virtqueue *vq);
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index da7a19558281..059cb723f6a7 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -41,13 +41,14 @@ struct vdev_info {
41 struct vhost_memory *mem; 41 struct vhost_memory *mem;
42}; 42};
43 43
44void vq_notify(struct virtqueue *vq) 44bool vq_notify(struct virtqueue *vq)
45{ 45{
46 struct vq_info *info = vq->priv; 46 struct vq_info *info = vq->priv;
47 unsigned long long v = 1; 47 unsigned long long v = 1;
48 int r; 48 int r;
49 r = write(info->kick, &v, sizeof v); 49 r = write(info->kick, &v, sizeof v);
50 assert(r == sizeof v); 50 assert(r == sizeof v);
51 return true;
51} 52}
52 53
53void vq_callback(struct virtqueue *vq) 54void vq_callback(struct virtqueue *vq)
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c
index d053ea40c001..14a4f4cab5b9 100644
--- a/tools/virtio/vringh_test.c
+++ b/tools/virtio/vringh_test.c
@@ -22,7 +22,7 @@ static u64 user_addr_offset;
22#define RINGSIZE 256 22#define RINGSIZE 256
23#define ALIGN 4096 23#define ALIGN 4096
24 24
25static void never_notify_host(struct virtqueue *vq) 25static bool never_notify_host(struct virtqueue *vq)
26{ 26{
27 abort(); 27 abort();
28} 28}
@@ -65,17 +65,22 @@ struct guest_virtio_device {
65 unsigned long notifies; 65 unsigned long notifies;
66}; 66};
67 67
68static void parallel_notify_host(struct virtqueue *vq) 68static bool parallel_notify_host(struct virtqueue *vq)
69{ 69{
70 int rc;
70 struct guest_virtio_device *gvdev; 71 struct guest_virtio_device *gvdev;
71 72
72 gvdev = container_of(vq->vdev, struct guest_virtio_device, vdev); 73 gvdev = container_of(vq->vdev, struct guest_virtio_device, vdev);
73 write(gvdev->to_host_fd, "", 1); 74 rc = write(gvdev->to_host_fd, "", 1);
75 if (rc < 0)
76 return false;
74 gvdev->notifies++; 77 gvdev->notifies++;
78 return true;
75} 79}
76 80
77static void no_notify_host(struct virtqueue *vq) 81static bool no_notify_host(struct virtqueue *vq)
78{ 82{
83 return true;
79} 84}
80 85
81#define NUM_XFERS (10000000) 86#define NUM_XFERS (10000000)