diff options
| -rw-r--r-- | drivers/virtio/virtio_mmio.c | 67 |
1 files changed, 15 insertions, 52 deletions
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 745c6ee1bb3e..48bfea91dbca 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
| @@ -99,12 +99,6 @@ struct virtio_mmio_vq_info { | |||
| 99 | /* the actual virtqueue */ | 99 | /* the actual virtqueue */ |
| 100 | struct virtqueue *vq; | 100 | struct virtqueue *vq; |
| 101 | 101 | ||
| 102 | /* the number of entries in the queue */ | ||
| 103 | unsigned int num; | ||
| 104 | |||
| 105 | /* the virtual address of the ring queue */ | ||
| 106 | void *queue; | ||
| 107 | |||
| 108 | /* the list node for the virtqueues list */ | 102 | /* the list node for the virtqueues list */ |
| 109 | struct list_head node; | 103 | struct list_head node; |
| 110 | }; | 104 | }; |
| @@ -322,15 +316,13 @@ static void vm_del_vq(struct virtqueue *vq) | |||
| 322 | { | 316 | { |
| 323 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); | 317 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); |
| 324 | struct virtio_mmio_vq_info *info = vq->priv; | 318 | struct virtio_mmio_vq_info *info = vq->priv; |
| 325 | unsigned long flags, size; | 319 | unsigned long flags; |
| 326 | unsigned int index = vq->index; | 320 | unsigned int index = vq->index; |
| 327 | 321 | ||
| 328 | spin_lock_irqsave(&vm_dev->lock, flags); | 322 | spin_lock_irqsave(&vm_dev->lock, flags); |
| 329 | list_del(&info->node); | 323 | list_del(&info->node); |
| 330 | spin_unlock_irqrestore(&vm_dev->lock, flags); | 324 | spin_unlock_irqrestore(&vm_dev->lock, flags); |
| 331 | 325 | ||
| 332 | vring_del_virtqueue(vq); | ||
| 333 | |||
| 334 | /* Select and deactivate the queue */ | 326 | /* Select and deactivate the queue */ |
| 335 | writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); | 327 | writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); |
| 336 | if (vm_dev->version == 1) { | 328 | if (vm_dev->version == 1) { |
| @@ -340,8 +332,8 @@ static void vm_del_vq(struct virtqueue *vq) | |||
| 340 | WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); | 332 | WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); |
| 341 | } | 333 | } |
| 342 | 334 | ||
| 343 | size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN)); | 335 | vring_del_virtqueue(vq); |
| 344 | free_pages_exact(info->queue, size); | 336 | |
| 345 | kfree(info); | 337 | kfree(info); |
| 346 | } | 338 | } |
| 347 | 339 | ||
| @@ -356,8 +348,6 @@ static void vm_del_vqs(struct virtio_device *vdev) | |||
| 356 | free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); | 348 | free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); |
| 357 | } | 349 | } |
| 358 | 350 | ||
| 359 | |||
| 360 | |||
| 361 | static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, | 351 | static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, |
| 362 | void (*callback)(struct virtqueue *vq), | 352 | void (*callback)(struct virtqueue *vq), |
| 363 | const char *name) | 353 | const char *name) |
| @@ -365,7 +355,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 365 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | 355 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); |
| 366 | struct virtio_mmio_vq_info *info; | 356 | struct virtio_mmio_vq_info *info; |
| 367 | struct virtqueue *vq; | 357 | struct virtqueue *vq; |
| 368 | unsigned long flags, size; | 358 | unsigned long flags; |
| 359 | unsigned int num; | ||
| 369 | int err; | 360 | int err; |
| 370 | 361 | ||
| 371 | if (!name) | 362 | if (!name) |
| @@ -388,66 +379,40 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 388 | goto error_kmalloc; | 379 | goto error_kmalloc; |
| 389 | } | 380 | } |
| 390 | 381 | ||
| 391 | /* Allocate pages for the queue - start with a queue as big as | 382 | num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX); |
| 392 | * possible (limited by maximum size allowed by device), drop down | 383 | if (num == 0) { |
| 393 | * to a minimal size, just big enough to fit descriptor table | ||
| 394 | * and two rings (which makes it "alignment_size * 2") | ||
| 395 | */ | ||
| 396 | info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX); | ||
| 397 | |||
| 398 | /* If the device reports a 0 entry queue, we won't be able to | ||
| 399 | * use it to perform I/O, and vring_new_virtqueue() can't create | ||
| 400 | * empty queues anyway, so don't bother to set up the device. | ||
| 401 | */ | ||
| 402 | if (info->num == 0) { | ||
| 403 | err = -ENOENT; | 384 | err = -ENOENT; |
| 404 | goto error_alloc_pages; | 385 | goto error_new_virtqueue; |
| 405 | } | ||
| 406 | |||
| 407 | while (1) { | ||
| 408 | size = PAGE_ALIGN(vring_size(info->num, | ||
| 409 | VIRTIO_MMIO_VRING_ALIGN)); | ||
| 410 | /* Did the last iter shrink the queue below minimum size? */ | ||
| 411 | if (size < VIRTIO_MMIO_VRING_ALIGN * 2) { | ||
| 412 | err = -ENOMEM; | ||
| 413 | goto error_alloc_pages; | ||
| 414 | } | ||
| 415 | |||
| 416 | info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); | ||
| 417 | if (info->queue) | ||
| 418 | break; | ||
| 419 | |||
| 420 | info->num /= 2; | ||
| 421 | } | 386 | } |
| 422 | 387 | ||
| 423 | /* Create the vring */ | 388 | /* Create the vring */ |
| 424 | vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev, | 389 | vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev, |
| 425 | true, info->queue, vm_notify, callback, name); | 390 | true, true, vm_notify, callback, name); |
| 426 | if (!vq) { | 391 | if (!vq) { |
| 427 | err = -ENOMEM; | 392 | err = -ENOMEM; |
| 428 | goto error_new_virtqueue; | 393 | goto error_new_virtqueue; |
| 429 | } | 394 | } |
| 430 | 395 | ||
| 431 | /* Activate the queue */ | 396 | /* Activate the queue */ |
| 432 | writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); | 397 | writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); |
| 433 | if (vm_dev->version == 1) { | 398 | if (vm_dev->version == 1) { |
| 434 | writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); | 399 | writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); |
| 435 | writel(virt_to_phys(info->queue) >> PAGE_SHIFT, | 400 | writel(virtqueue_get_desc_addr(vq) >> PAGE_SHIFT, |
| 436 | vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); | 401 | vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); |
| 437 | } else { | 402 | } else { |
| 438 | u64 addr; | 403 | u64 addr; |
| 439 | 404 | ||
| 440 | addr = virt_to_phys(info->queue); | 405 | addr = virtqueue_get_desc_addr(vq); |
| 441 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); | 406 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); |
| 442 | writel((u32)(addr >> 32), | 407 | writel((u32)(addr >> 32), |
| 443 | vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); | 408 | vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); |
| 444 | 409 | ||
| 445 | addr = virt_to_phys(virtqueue_get_avail(vq)); | 410 | addr = virtqueue_get_avail_addr(vq); |
| 446 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); | 411 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); |
| 447 | writel((u32)(addr >> 32), | 412 | writel((u32)(addr >> 32), |
| 448 | vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); | 413 | vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); |
| 449 | 414 | ||
| 450 | addr = virt_to_phys(virtqueue_get_used(vq)); | 415 | addr = virtqueue_get_used_addr(vq); |
| 451 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); | 416 | writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); |
| 452 | writel((u32)(addr >> 32), | 417 | writel((u32)(addr >> 32), |
| 453 | vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); | 418 | vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); |
| @@ -471,8 +436,6 @@ error_new_virtqueue: | |||
| 471 | writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); | 436 | writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); |
| 472 | WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); | 437 | WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); |
| 473 | } | 438 | } |
| 474 | free_pages_exact(info->queue, size); | ||
| 475 | error_alloc_pages: | ||
| 476 | kfree(info); | 439 | kfree(info); |
| 477 | error_kmalloc: | 440 | error_kmalloc: |
| 478 | error_available: | 441 | error_available: |
