aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/virtio/virtio_pci.c69
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
392static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, 398static 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
452out_assign:
453 vring_del_virtqueue(vq);
454out_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
460static 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
463out_assign:
464 vring_del_virtqueue(vq);
465out_activate_queue:
466 iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
467 free_pages_exact(info->queue, size);
468out_info: 490out_info:
469 kfree(info); 491 kfree(info);
470 return ERR_PTR(err); 492 return vq;
471} 493}
472 494
473static void del_vq(struct virtio_pci_vq_info *info) 495static 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 */