diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2014-12-07 11:03:49 -0500 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 14:42:03 -0500 |
| commit | b09f00bbfe8755c0de9e4950816f4b283ddbca16 (patch) | |
| tree | 912470e0d2906e898b3a42c44a4c9b6faff6fa10 | |
| parent | 5386cef200ae0ac79cdcd160772989e8f5c47a4f (diff) | |
virtio_pci: setup vqs indirectly
VQ setup is mostly version-specific, add another level of indirection to
split the version-independent code out.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 133978c6bd85..68023e509fcc 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -82,6 +82,12 @@ struct virtio_pci_device { | |||
| 82 | /* Whether we have vector per vq */ | 82 | /* Whether we have vector per vq */ |
| 83 | bool per_vq_vectors; | 83 | bool per_vq_vectors; |
| 84 | 84 | ||
| 85 | struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, | ||
| 86 | struct virtio_pci_vq_info *info, | ||
| 87 | unsigned idx, | ||
| 88 | void (*callback)(struct virtqueue *vq), | ||
| 89 | const char *name, | ||
| 90 | u16 msix_vec); | ||
| 85 | void (*del_vq)(struct virtio_pci_vq_info *info); | 91 | void (*del_vq)(struct virtio_pci_vq_info *info); |
| 86 | }; | 92 | }; |
| 87 | 93 | ||
| @@ -389,15 +395,15 @@ static int vp_request_intx(struct virtio_device *vdev) | |||
| 389 | return err; | 395 | return err; |
| 390 | } | 396 | } |
| 391 | 397 | ||
| 392 | static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | 398 | static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, |
| 399 | struct virtio_pci_vq_info *info, | ||
| 400 | unsigned index, | ||
| 393 | void (*callback)(struct virtqueue *vq), | 401 | void (*callback)(struct virtqueue *vq), |
| 394 | const char *name, | 402 | const char *name, |
| 395 | u16 msix_vec) | 403 | u16 msix_vec) |
| 396 | { | 404 | { |
| 397 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | ||
| 398 | struct virtio_pci_vq_info *info; | ||
| 399 | struct virtqueue *vq; | 405 | struct virtqueue *vq; |
| 400 | unsigned long flags, size; | 406 | unsigned long size; |
| 401 | u16 num; | 407 | u16 num; |
| 402 | int err; | 408 | int err; |
| 403 | 409 | ||
| @@ -409,28 +415,21 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 409 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) | 415 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) |
| 410 | return ERR_PTR(-ENOENT); | 416 | return ERR_PTR(-ENOENT); |
| 411 | 417 | ||
| 412 | /* allocate and fill out our structure the represents an active | ||
| 413 | * queue */ | ||
| 414 | info = kmalloc(sizeof(struct virtio_pci_vq_info), GFP_KERNEL); | ||
| 415 | if (!info) | ||
| 416 | return ERR_PTR(-ENOMEM); | ||
| 417 | |||
| 418 | info->num = num; | 418 | info->num = num; |
| 419 | info->msix_vector = msix_vec; | 419 | info->msix_vector = msix_vec; |
| 420 | 420 | ||
| 421 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); | 421 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); |
| 422 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | 422 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); |
| 423 | if (info->queue == NULL) { | 423 | if (info->queue == NULL) |
| 424 | err = -ENOMEM; | 424 | return ERR_PTR(-ENOMEM); |
| 425 | goto out_info; | ||
| 426 | } | ||
| 427 | 425 | ||
| 428 | /* activate the queue */ | 426 | /* activate the queue */ |
| 429 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, | 427 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, |
| 430 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 428 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 431 | 429 | ||
| 432 | /* create the vring */ | 430 | /* create the vring */ |
| 433 | vq = vring_new_virtqueue(index, info->num, VIRTIO_PCI_VRING_ALIGN, vdev, | 431 | vq = vring_new_virtqueue(index, info->num, |
| 432 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, | ||
| 434 | true, info->queue, vp_notify, callback, name); | 433 | true, info->queue, vp_notify, callback, name); |
| 435 | if (!vq) { | 434 | if (!vq) { |
| 436 | err = -ENOMEM; | 435 | err = -ENOMEM; |
| @@ -438,7 +437,6 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 438 | } | 437 | } |
| 439 | 438 | ||
| 440 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; | 439 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; |
| 441 | info->vq = vq; | ||
| 442 | 440 | ||
| 443 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { | 441 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { |
| 444 | iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | 442 | iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); |
| @@ -449,6 +447,35 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 449 | } | 447 | } |
| 450 | } | 448 | } |
| 451 | 449 | ||
| 450 | return vq; | ||
| 451 | |||
| 452 | out_assign: | ||
| 453 | vring_del_virtqueue(vq); | ||
| 454 | out_activate_queue: | ||
| 455 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | ||
| 456 | free_pages_exact(info->queue, size); | ||
| 457 | return ERR_PTR(err); | ||
| 458 | } | ||
| 459 | |||
| 460 | static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, | ||
| 461 | void (*callback)(struct virtqueue *vq), | ||
| 462 | const char *name, | ||
| 463 | u16 msix_vec) | ||
| 464 | { | ||
| 465 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | ||
| 466 | struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL); | ||
| 467 | struct virtqueue *vq; | ||
| 468 | unsigned long flags; | ||
| 469 | |||
| 470 | /* fill out our structure that represents an active queue */ | ||
| 471 | if (!info) | ||
| 472 | return ERR_PTR(-ENOMEM); | ||
| 473 | |||
| 474 | vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, msix_vec); | ||
| 475 | if (IS_ERR(vq)) | ||
| 476 | goto out_info; | ||
| 477 | |||
| 478 | info->vq = vq; | ||
| 452 | if (callback) { | 479 | if (callback) { |
| 453 | spin_lock_irqsave(&vp_dev->lock, flags); | 480 | spin_lock_irqsave(&vp_dev->lock, flags); |
| 454 | list_add(&info->node, &vp_dev->virtqueues); | 481 | list_add(&info->node, &vp_dev->virtqueues); |
| @@ -460,14 +487,9 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
| 460 | vp_dev->vqs[index] = info; | 487 | vp_dev->vqs[index] = info; |
| 461 | return vq; | 488 | return vq; |
| 462 | 489 | ||
| 463 | out_assign: | ||
| 464 | vring_del_virtqueue(vq); | ||
| 465 | out_activate_queue: | ||
| 466 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | ||
| 467 | free_pages_exact(info->queue, size); | ||
| 468 | out_info: | 490 | out_info: |
| 469 | kfree(info); | 491 | kfree(info); |
| 470 | return ERR_PTR(err); | 492 | return vq; |
| 471 | } | 493 | } |
| 472 | 494 | ||
| 473 | static void del_vq(struct virtio_pci_vq_info *info) | 495 | static void del_vq(struct virtio_pci_vq_info *info) |
| @@ -578,7 +600,7 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
| 578 | msix_vec = allocated_vectors++; | 600 | msix_vec = allocated_vectors++; |
| 579 | else | 601 | else |
| 580 | msix_vec = VP_MSIX_VQ_VECTOR; | 602 | msix_vec = VP_MSIX_VQ_VECTOR; |
| 581 | vqs[i] = setup_vq(vdev, i, callbacks[i], names[i], msix_vec); | 603 | vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], msix_vec); |
| 582 | if (IS_ERR(vqs[i])) { | 604 | if (IS_ERR(vqs[i])) { |
| 583 | err = PTR_ERR(vqs[i]); | 605 | err = PTR_ERR(vqs[i]); |
| 584 | goto error_find; | 606 | goto error_find; |
| @@ -748,6 +770,7 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, | |||
| 748 | vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; | 770 | vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; |
| 749 | vp_dev->vdev.id.device = pci_dev->subsystem_device; | 771 | vp_dev->vdev.id.device = pci_dev->subsystem_device; |
| 750 | 772 | ||
| 773 | vp_dev->setup_vq = setup_vq; | ||
| 751 | vp_dev->del_vq = del_vq; | 774 | vp_dev->del_vq = del_vq; |
| 752 | 775 | ||
| 753 | /* finally register the virtio device */ | 776 | /* finally register the virtio device */ |
