diff options
Diffstat (limited to 'drivers/lguest/lguest_device.c')
-rw-r--r-- | drivers/lguest/lguest_device.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index df44d962626d..e082cdac88b4 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -228,7 +228,8 @@ extern void lguest_setup_irq(unsigned int irq); | |||
228 | * function. */ | 228 | * function. */ |
229 | static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | 229 | static struct virtqueue *lg_find_vq(struct virtio_device *vdev, |
230 | unsigned index, | 230 | unsigned index, |
231 | void (*callback)(struct virtqueue *vq)) | 231 | void (*callback)(struct virtqueue *vq), |
232 | const char *name) | ||
232 | { | 233 | { |
233 | struct lguest_device *ldev = to_lgdev(vdev); | 234 | struct lguest_device *ldev = to_lgdev(vdev); |
234 | struct lguest_vq_info *lvq; | 235 | struct lguest_vq_info *lvq; |
@@ -263,7 +264,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | |||
263 | /* OK, tell virtio_ring.c to set up a virtqueue now we know its size | 264 | /* OK, tell virtio_ring.c to set up a virtqueue now we know its size |
264 | * and we've got a pointer to its pages. */ | 265 | * and we've got a pointer to its pages. */ |
265 | vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, | 266 | vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, |
266 | vdev, lvq->pages, lg_notify, callback); | 267 | vdev, lvq->pages, lg_notify, callback, name); |
267 | if (!vq) { | 268 | if (!vq) { |
268 | err = -ENOMEM; | 269 | err = -ENOMEM; |
269 | goto unmap; | 270 | goto unmap; |
@@ -312,6 +313,38 @@ static void lg_del_vq(struct virtqueue *vq) | |||
312 | kfree(lvq); | 313 | kfree(lvq); |
313 | } | 314 | } |
314 | 315 | ||
316 | static void lg_del_vqs(struct virtio_device *vdev) | ||
317 | { | ||
318 | struct virtqueue *vq, *n; | ||
319 | |||
320 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) | ||
321 | lg_del_vq(vq); | ||
322 | } | ||
323 | |||
324 | static int lg_find_vqs(struct virtio_device *vdev, unsigned nvqs, | ||
325 | struct virtqueue *vqs[], | ||
326 | vq_callback_t *callbacks[], | ||
327 | const char *names[]) | ||
328 | { | ||
329 | struct lguest_device *ldev = to_lgdev(vdev); | ||
330 | int i; | ||
331 | |||
332 | /* We must have this many virtqueues. */ | ||
333 | if (nvqs > ldev->desc->num_vq) | ||
334 | return -ENOENT; | ||
335 | |||
336 | for (i = 0; i < nvqs; ++i) { | ||
337 | vqs[i] = lg_find_vq(vdev, i, callbacks[i], names[i]); | ||
338 | if (IS_ERR(vqs[i])) | ||
339 | goto error; | ||
340 | } | ||
341 | return 0; | ||
342 | |||
343 | error: | ||
344 | lg_del_vqs(vdev); | ||
345 | return PTR_ERR(vqs[i]); | ||
346 | } | ||
347 | |||
315 | /* The ops structure which hooks everything together. */ | 348 | /* The ops structure which hooks everything together. */ |
316 | static struct virtio_config_ops lguest_config_ops = { | 349 | static struct virtio_config_ops lguest_config_ops = { |
317 | .get_features = lg_get_features, | 350 | .get_features = lg_get_features, |
@@ -321,8 +354,8 @@ static struct virtio_config_ops lguest_config_ops = { | |||
321 | .get_status = lg_get_status, | 354 | .get_status = lg_get_status, |
322 | .set_status = lg_set_status, | 355 | .set_status = lg_set_status, |
323 | .reset = lg_reset, | 356 | .reset = lg_reset, |
324 | .find_vq = lg_find_vq, | 357 | .find_vqs = lg_find_vqs, |
325 | .del_vq = lg_del_vq, | 358 | .del_vqs = lg_del_vqs, |
326 | }; | 359 | }; |
327 | 360 | ||
328 | /* The root device for the lguest virtio devices. This makes them appear as | 361 | /* The root device for the lguest virtio devices. This makes them appear as |