aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio/virtio_pci_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/virtio/virtio_pci_common.c')
-rw-r--r--drivers/virtio/virtio_pci_common.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 9756f21b809e..457cbe29c8c4 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -464,15 +464,80 @@ static const struct pci_device_id virtio_pci_id_table[] = {
464 464
465MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); 465MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
466 466
467static void virtio_pci_release_dev(struct device *_d)
468{
469 struct virtio_device *vdev = dev_to_virtio(_d);
470 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
471
472 /* As struct device is a kobject, it's not safe to
473 * free the memory (including the reference counter itself)
474 * until it's release callback. */
475 kfree(vp_dev);
476}
477
467static int virtio_pci_probe(struct pci_dev *pci_dev, 478static int virtio_pci_probe(struct pci_dev *pci_dev,
468 const struct pci_device_id *id) 479 const struct pci_device_id *id)
469{ 480{
470 return virtio_pci_legacy_probe(pci_dev, id); 481 struct virtio_pci_device *vp_dev;
482 int rc;
483
484 /* allocate our structure and fill it out */
485 vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
486 if (!vp_dev)
487 return -ENOMEM;
488
489 pci_set_drvdata(pci_dev, vp_dev);
490 vp_dev->vdev.dev.parent = &pci_dev->dev;
491 vp_dev->vdev.dev.release = virtio_pci_release_dev;
492 vp_dev->pci_dev = pci_dev;
493 INIT_LIST_HEAD(&vp_dev->virtqueues);
494 spin_lock_init(&vp_dev->lock);
495
496 /* Disable MSI/MSIX to bring device to a known good state. */
497 pci_msi_off(pci_dev);
498
499 /* enable the device */
500 rc = pci_enable_device(pci_dev);
501 if (rc)
502 goto err_enable_device;
503
504 rc = pci_request_regions(pci_dev, "virtio-pci");
505 if (rc)
506 goto err_request_regions;
507
508 rc = virtio_pci_legacy_probe(vp_dev);
509 if (rc)
510 goto err_probe;
511
512 pci_set_master(pci_dev);
513
514 rc = register_virtio_device(&vp_dev->vdev);
515 if (rc)
516 goto err_register;
517
518 return 0;
519
520err_register:
521 virtio_pci_legacy_remove(vp_dev);
522err_probe:
523 pci_release_regions(pci_dev);
524err_request_regions:
525 pci_disable_device(pci_dev);
526err_enable_device:
527 kfree(vp_dev);
528 return rc;
471} 529}
472 530
473static void virtio_pci_remove(struct pci_dev *pci_dev) 531static void virtio_pci_remove(struct pci_dev *pci_dev)
474{ 532{
475 virtio_pci_legacy_remove(pci_dev); 533 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
534
535 unregister_virtio_device(&vp_dev->vdev);
536
537 virtio_pci_legacy_remove(pci_dev);
538
539 pci_release_regions(pci_dev);
540 pci_disable_device(pci_dev);
476} 541}
477 542
478static struct pci_driver virtio_pci_driver = { 543static struct pci_driver virtio_pci_driver = {