aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/lguest_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/lguest_device.c')
-rw-r--r--drivers/lguest/lguest_device.c41
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. */
229static struct virtqueue *lg_find_vq(struct virtio_device *vdev, 229static 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
316static 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
324static 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
343error:
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. */
316static struct virtio_config_ops lguest_config_ops = { 349static 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