Commit 46f9c2b925ac12e5ad8b8b7c90c71dacc9d5db37

Authored by Heinz Graalfs
Committed by Rusty Russell
1 parent 630b54d334

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>

Showing 10 changed files with 32 additions and 15 deletions Side-by-side Diff

drivers/lguest/lguest_device.c
... ... @@ -229,7 +229,7 @@
229 229 * make a hypercall. We hand the physical address of the virtqueue so the Host
230 230 * knows which virtqueue we're talking about.
231 231 */
232   -static void lg_notify(struct virtqueue *vq)
  232 +static bool lg_notify(struct virtqueue *vq)
233 233 {
234 234 /*
235 235 * We store our virtqueue information in the "priv" pointer of the
... ... @@ -238,6 +238,7 @@
238 238 struct lguest_vq_info *lvq = vq->priv;
239 239  
240 240 hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
  241 + return true;
241 242 }
242 243  
243 244 /* An extern declaration inside a C file is bad form. Don't do it. */
drivers/remoteproc/remoteproc_virtio.c
... ... @@ -30,7 +30,7 @@
30 30 #include "remoteproc_internal.h"
31 31  
32 32 /* kick the remote processor, and let it know which virtqueue to poke at */
33   -static void rproc_virtio_notify(struct virtqueue *vq)
  33 +static bool rproc_virtio_notify(struct virtqueue *vq)
34 34 {
35 35 struct rproc_vring *rvring = vq->priv;
36 36 struct rproc *rproc = rvring->rvdev->rproc;
... ... @@ -39,6 +39,7 @@
39 39 dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);
40 40  
41 41 rproc->ops->kick(rproc, notifyid);
  42 + return true;
42 43 }
43 44  
44 45 /**
drivers/s390/kvm/kvm_virtio.c
... ... @@ -166,11 +166,15 @@
166 166 * make a hypercall. We hand the address of the virtqueue so the Host
167 167 * knows which virtqueue we're talking about.
168 168 */
169   -static void kvm_notify(struct virtqueue *vq)
  169 +static bool kvm_notify(struct virtqueue *vq)
170 170 {
  171 + long rc;
171 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 /*
drivers/s390/kvm/virtio_ccw.c
... ... @@ -162,7 +162,7 @@
162 162 return __rc;
163 163 }
164 164  
165   -static void virtio_ccw_kvm_notify(struct virtqueue *vq)
  165 +static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
166 166 {
167 167 struct virtio_ccw_vq_info *info = vq->priv;
168 168 struct virtio_ccw_device *vcdev;
... ... @@ -171,6 +171,9 @@
171 171 vcdev = to_vc_device(info->vq->vdev);
172 172 ccw_device_get_schid(vcdev->cdev, &schid);
173 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  
176 179 static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
drivers/virtio/virtio_mmio.c
... ... @@ -219,13 +219,14 @@
219 219 /* Transport interface */
220 220  
221 221 /* the notify function used when creating a virt queue */
222   -static void vm_notify(struct virtqueue *vq)
  222 +static bool vm_notify(struct virtqueue *vq)
223 223 {
224 224 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
225 225  
226 226 /* We write the queue's selector into the notification register to
227 227 * signal the other end */
228 228 writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
  229 + return true;
229 230 }
230 231  
231 232 /* Notify all virtqueues on an interrupt. */
drivers/virtio/virtio_pci.c
... ... @@ -197,13 +197,14 @@
197 197 }
198 198  
199 199 /* the notify function used when creating a virt queue */
200   -static void vp_notify(struct virtqueue *vq)
  200 +static bool vp_notify(struct virtqueue *vq)
201 201 {
202 202 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
203 203  
204 204 /* we write the queue's selector into the notification register to
205 205 * signal the other end */
206 206 iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
  207 + return true;
207 208 }
208 209  
209 210 /* Handle a configuration change: Tell driver if it wants to know. */
drivers/virtio/virtio_ring.c
... ... @@ -81,7 +81,7 @@
81 81 u16 last_used_idx;
82 82  
83 83 /* How to notify other side. FIXME: commonalize hcalls! */
84   - void (*notify)(struct virtqueue *vq);
  84 + bool (*notify)(struct virtqueue *vq);
85 85  
86 86 #ifdef DEBUG
87 87 /* They're supposed to lock for us. */
... ... @@ -744,7 +744,7 @@
744 744 struct virtio_device *vdev,
745 745 bool weak_barriers,
746 746 void *pages,
747   - void (*notify)(struct virtqueue *),
  747 + bool (*notify)(struct virtqueue *),
748 748 void (*callback)(struct virtqueue *),
749 749 const char *name)
750 750 {
include/linux/virtio_ring.h
... ... @@ -71,7 +71,7 @@
71 71 struct virtio_device *vdev,
72 72 bool weak_barriers,
73 73 void *pages,
74   - void (*notify)(struct virtqueue *vq),
  74 + bool (*notify)(struct virtqueue *vq),
75 75 void (*callback)(struct virtqueue *vq),
76 76 const char *name);
77 77 void vring_del_virtqueue(struct virtqueue *vq);
tools/virtio/virtio_test.c
... ... @@ -41,13 +41,14 @@
41 41 struct vhost_memory *mem;
42 42 };
43 43  
44   -void vq_notify(struct virtqueue *vq)
  44 +bool vq_notify(struct virtqueue *vq)
45 45 {
46 46 struct vq_info *info = vq->priv;
47 47 unsigned long long v = 1;
48 48 int r;
49 49 r = write(info->kick, &v, sizeof v);
50 50 assert(r == sizeof v);
  51 + return true;
51 52 }
52 53  
53 54 void vq_callback(struct virtqueue *vq)
tools/virtio/vringh_test.c
... ... @@ -22,7 +22,7 @@
22 22 #define RINGSIZE 256
23 23 #define ALIGN 4096
24 24  
25   -static void never_notify_host(struct virtqueue *vq)
  25 +static bool never_notify_host(struct virtqueue *vq)
26 26 {
27 27 abort();
28 28 }
29 29  
30 30  
31 31  
32 32  
33 33  
... ... @@ -65,17 +65,22 @@
65 65 unsigned long notifies;
66 66 };
67 67  
68   -static void parallel_notify_host(struct virtqueue *vq)
  68 +static bool parallel_notify_host(struct virtqueue *vq)
69 69 {
  70 + int rc;
70 71 struct guest_virtio_device *gvdev;
71 72  
72 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 77 gvdev->notifies++;
  78 + return true;
75 79 }
76 80  
77   -static void no_notify_host(struct virtqueue *vq)
  81 +static bool no_notify_host(struct virtqueue *vq)
78 82 {
  83 + return true;
79 84 }
80 85  
81 86 #define NUM_XFERS (10000000)