diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 20:42:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 20:42:31 -0500 |
commit | 2d08cd0ef89a24f5eb6c6801c48cd06bca230d6d (patch) | |
tree | d9bbec83fa54dd5338144089b6dcb570a40237e7 /drivers | |
parent | 5c85121bf618aece49155f6eea0d0b2c14c1a121 (diff) | |
parent | 3be3a074cf5ba641529d8fdae0e05ca642f23e12 (diff) |
Merge tag 'vfio-v3.14-rc1' of git://github.com/awilliam/linux-vfio
Pull vfio update from Alex Williamson:
- convert to misc driver to support module auto loading
- remove unnecessary and dangerous use of device_lock
* tag 'vfio-v3.14-rc1' of git://github.com/awilliam/linux-vfio:
vfio-pci: Don't use device_lock around AER interrupt setup
vfio: Convert control interface to misc driver
misc: Reserve minor for VFIO
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 4 | ||||
-rw-r--r-- | drivers/vfio/pci/vfio_pci_intrs.c | 17 | ||||
-rw-r--r-- | drivers/vfio/vfio.c | 70 |
3 files changed, 37 insertions, 54 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 2319d206f630..7ba042498857 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -872,9 +872,13 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, | |||
872 | return PCI_ERS_RESULT_DISCONNECT; | 872 | return PCI_ERS_RESULT_DISCONNECT; |
873 | } | 873 | } |
874 | 874 | ||
875 | mutex_lock(&vdev->igate); | ||
876 | |||
875 | if (vdev->err_trigger) | 877 | if (vdev->err_trigger) |
876 | eventfd_signal(vdev->err_trigger, 1); | 878 | eventfd_signal(vdev->err_trigger, 1); |
877 | 879 | ||
880 | mutex_unlock(&vdev->igate); | ||
881 | |||
878 | vfio_device_put(device); | 882 | vfio_device_put(device); |
879 | 883 | ||
880 | return PCI_ERS_RESULT_CAN_RECOVER; | 884 | return PCI_ERS_RESULT_CAN_RECOVER; |
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 641bc87bdb96..210357691dc0 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c | |||
@@ -749,54 +749,37 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev, | |||
749 | unsigned count, uint32_t flags, void *data) | 749 | unsigned count, uint32_t flags, void *data) |
750 | { | 750 | { |
751 | int32_t fd = *(int32_t *)data; | 751 | int32_t fd = *(int32_t *)data; |
752 | struct pci_dev *pdev = vdev->pdev; | ||
753 | 752 | ||
754 | if ((index != VFIO_PCI_ERR_IRQ_INDEX) || | 753 | if ((index != VFIO_PCI_ERR_IRQ_INDEX) || |
755 | !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK)) | 754 | !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK)) |
756 | return -EINVAL; | 755 | return -EINVAL; |
757 | 756 | ||
758 | /* | ||
759 | * device_lock synchronizes setting and checking of | ||
760 | * err_trigger. The vfio_pci_aer_err_detected() is also | ||
761 | * called with device_lock held. | ||
762 | */ | ||
763 | |||
764 | /* DATA_NONE/DATA_BOOL enables loopback testing */ | 757 | /* DATA_NONE/DATA_BOOL enables loopback testing */ |
765 | |||
766 | if (flags & VFIO_IRQ_SET_DATA_NONE) { | 758 | if (flags & VFIO_IRQ_SET_DATA_NONE) { |
767 | device_lock(&pdev->dev); | ||
768 | if (vdev->err_trigger) | 759 | if (vdev->err_trigger) |
769 | eventfd_signal(vdev->err_trigger, 1); | 760 | eventfd_signal(vdev->err_trigger, 1); |
770 | device_unlock(&pdev->dev); | ||
771 | return 0; | 761 | return 0; |
772 | } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { | 762 | } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { |
773 | uint8_t trigger = *(uint8_t *)data; | 763 | uint8_t trigger = *(uint8_t *)data; |
774 | device_lock(&pdev->dev); | ||
775 | if (trigger && vdev->err_trigger) | 764 | if (trigger && vdev->err_trigger) |
776 | eventfd_signal(vdev->err_trigger, 1); | 765 | eventfd_signal(vdev->err_trigger, 1); |
777 | device_unlock(&pdev->dev); | ||
778 | return 0; | 766 | return 0; |
779 | } | 767 | } |
780 | 768 | ||
781 | /* Handle SET_DATA_EVENTFD */ | 769 | /* Handle SET_DATA_EVENTFD */ |
782 | |||
783 | if (fd == -1) { | 770 | if (fd == -1) { |
784 | device_lock(&pdev->dev); | ||
785 | if (vdev->err_trigger) | 771 | if (vdev->err_trigger) |
786 | eventfd_ctx_put(vdev->err_trigger); | 772 | eventfd_ctx_put(vdev->err_trigger); |
787 | vdev->err_trigger = NULL; | 773 | vdev->err_trigger = NULL; |
788 | device_unlock(&pdev->dev); | ||
789 | return 0; | 774 | return 0; |
790 | } else if (fd >= 0) { | 775 | } else if (fd >= 0) { |
791 | struct eventfd_ctx *efdctx; | 776 | struct eventfd_ctx *efdctx; |
792 | efdctx = eventfd_ctx_fdget(fd); | 777 | efdctx = eventfd_ctx_fdget(fd); |
793 | if (IS_ERR(efdctx)) | 778 | if (IS_ERR(efdctx)) |
794 | return PTR_ERR(efdctx); | 779 | return PTR_ERR(efdctx); |
795 | device_lock(&pdev->dev); | ||
796 | if (vdev->err_trigger) | 780 | if (vdev->err_trigger) |
797 | eventfd_ctx_put(vdev->err_trigger); | 781 | eventfd_ctx_put(vdev->err_trigger); |
798 | vdev->err_trigger = efdctx; | 782 | vdev->err_trigger = efdctx; |
799 | device_unlock(&pdev->dev); | ||
800 | return 0; | 783 | return 0; |
801 | } else | 784 | } else |
802 | return -EINVAL; | 785 | return -EINVAL; |
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 1eab4ace0671..21271d8df023 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/idr.h> | 22 | #include <linux/idr.h> |
23 | #include <linux/iommu.h> | 23 | #include <linux/iommu.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/miscdevice.h> | ||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
27 | #include <linux/rwsem.h> | 28 | #include <linux/rwsem.h> |
@@ -45,9 +46,7 @@ static struct vfio { | |||
45 | struct idr group_idr; | 46 | struct idr group_idr; |
46 | struct mutex group_lock; | 47 | struct mutex group_lock; |
47 | struct cdev group_cdev; | 48 | struct cdev group_cdev; |
48 | struct device *dev; | 49 | dev_t group_devt; |
49 | dev_t devt; | ||
50 | struct cdev cdev; | ||
51 | wait_queue_head_t release_q; | 50 | wait_queue_head_t release_q; |
52 | } vfio; | 51 | } vfio; |
53 | 52 | ||
@@ -142,8 +141,7 @@ EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); | |||
142 | */ | 141 | */ |
143 | static int vfio_alloc_group_minor(struct vfio_group *group) | 142 | static int vfio_alloc_group_minor(struct vfio_group *group) |
144 | { | 143 | { |
145 | /* index 0 is used by /dev/vfio/vfio */ | 144 | return idr_alloc(&vfio.group_idr, group, 0, MINORMASK + 1, GFP_KERNEL); |
146 | return idr_alloc(&vfio.group_idr, group, 1, MINORMASK + 1, GFP_KERNEL); | ||
147 | } | 145 | } |
148 | 146 | ||
149 | static void vfio_free_group_minor(int minor) | 147 | static void vfio_free_group_minor(int minor) |
@@ -243,7 +241,8 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
243 | } | 241 | } |
244 | } | 242 | } |
245 | 243 | ||
246 | dev = device_create(vfio.class, NULL, MKDEV(MAJOR(vfio.devt), minor), | 244 | dev = device_create(vfio.class, NULL, |
245 | MKDEV(MAJOR(vfio.group_devt), minor), | ||
247 | group, "%d", iommu_group_id(iommu_group)); | 246 | group, "%d", iommu_group_id(iommu_group)); |
248 | if (IS_ERR(dev)) { | 247 | if (IS_ERR(dev)) { |
249 | vfio_free_group_minor(minor); | 248 | vfio_free_group_minor(minor); |
@@ -268,7 +267,7 @@ static void vfio_group_release(struct kref *kref) | |||
268 | 267 | ||
269 | WARN_ON(!list_empty(&group->device_list)); | 268 | WARN_ON(!list_empty(&group->device_list)); |
270 | 269 | ||
271 | device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); | 270 | device_destroy(vfio.class, MKDEV(MAJOR(vfio.group_devt), group->minor)); |
272 | list_del(&group->vfio_next); | 271 | list_del(&group->vfio_next); |
273 | vfio_free_group_minor(group->minor); | 272 | vfio_free_group_minor(group->minor); |
274 | vfio_group_unlock_and_free(group); | 273 | vfio_group_unlock_and_free(group); |
@@ -1419,12 +1418,17 @@ EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id); | |||
1419 | */ | 1418 | */ |
1420 | static char *vfio_devnode(struct device *dev, umode_t *mode) | 1419 | static char *vfio_devnode(struct device *dev, umode_t *mode) |
1421 | { | 1420 | { |
1422 | if (mode && (MINOR(dev->devt) == 0)) | ||
1423 | *mode = S_IRUGO | S_IWUGO; | ||
1424 | |||
1425 | return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev)); | 1421 | return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev)); |
1426 | } | 1422 | } |
1427 | 1423 | ||
1424 | static struct miscdevice vfio_dev = { | ||
1425 | .minor = VFIO_MINOR, | ||
1426 | .name = "vfio", | ||
1427 | .fops = &vfio_fops, | ||
1428 | .nodename = "vfio/vfio", | ||
1429 | .mode = S_IRUGO | S_IWUGO, | ||
1430 | }; | ||
1431 | |||
1428 | static int __init vfio_init(void) | 1432 | static int __init vfio_init(void) |
1429 | { | 1433 | { |
1430 | int ret; | 1434 | int ret; |
@@ -1436,6 +1440,13 @@ static int __init vfio_init(void) | |||
1436 | INIT_LIST_HEAD(&vfio.iommu_drivers_list); | 1440 | INIT_LIST_HEAD(&vfio.iommu_drivers_list); |
1437 | init_waitqueue_head(&vfio.release_q); | 1441 | init_waitqueue_head(&vfio.release_q); |
1438 | 1442 | ||
1443 | ret = misc_register(&vfio_dev); | ||
1444 | if (ret) { | ||
1445 | pr_err("vfio: misc device register failed\n"); | ||
1446 | return ret; | ||
1447 | } | ||
1448 | |||
1449 | /* /dev/vfio/$GROUP */ | ||
1439 | vfio.class = class_create(THIS_MODULE, "vfio"); | 1450 | vfio.class = class_create(THIS_MODULE, "vfio"); |
1440 | if (IS_ERR(vfio.class)) { | 1451 | if (IS_ERR(vfio.class)) { |
1441 | ret = PTR_ERR(vfio.class); | 1452 | ret = PTR_ERR(vfio.class); |
@@ -1444,27 +1455,14 @@ static int __init vfio_init(void) | |||
1444 | 1455 | ||
1445 | vfio.class->devnode = vfio_devnode; | 1456 | vfio.class->devnode = vfio_devnode; |
1446 | 1457 | ||
1447 | ret = alloc_chrdev_region(&vfio.devt, 0, MINORMASK, "vfio"); | 1458 | ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio"); |
1448 | if (ret) | ||
1449 | goto err_base_chrdev; | ||
1450 | |||
1451 | cdev_init(&vfio.cdev, &vfio_fops); | ||
1452 | ret = cdev_add(&vfio.cdev, vfio.devt, 1); | ||
1453 | if (ret) | 1459 | if (ret) |
1454 | goto err_base_cdev; | 1460 | goto err_alloc_chrdev; |
1455 | 1461 | ||
1456 | vfio.dev = device_create(vfio.class, NULL, vfio.devt, NULL, "vfio"); | ||
1457 | if (IS_ERR(vfio.dev)) { | ||
1458 | ret = PTR_ERR(vfio.dev); | ||
1459 | goto err_base_dev; | ||
1460 | } | ||
1461 | |||
1462 | /* /dev/vfio/$GROUP */ | ||
1463 | cdev_init(&vfio.group_cdev, &vfio_group_fops); | 1462 | cdev_init(&vfio.group_cdev, &vfio_group_fops); |
1464 | ret = cdev_add(&vfio.group_cdev, | 1463 | ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK); |
1465 | MKDEV(MAJOR(vfio.devt), 1), MINORMASK - 1); | ||
1466 | if (ret) | 1464 | if (ret) |
1467 | goto err_groups_cdev; | 1465 | goto err_cdev_add; |
1468 | 1466 | ||
1469 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 1467 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
1470 | 1468 | ||
@@ -1478,16 +1476,13 @@ static int __init vfio_init(void) | |||
1478 | 1476 | ||
1479 | return 0; | 1477 | return 0; |
1480 | 1478 | ||
1481 | err_groups_cdev: | 1479 | err_cdev_add: |
1482 | device_destroy(vfio.class, vfio.devt); | 1480 | unregister_chrdev_region(vfio.group_devt, MINORMASK); |
1483 | err_base_dev: | 1481 | err_alloc_chrdev: |
1484 | cdev_del(&vfio.cdev); | ||
1485 | err_base_cdev: | ||
1486 | unregister_chrdev_region(vfio.devt, MINORMASK); | ||
1487 | err_base_chrdev: | ||
1488 | class_destroy(vfio.class); | 1482 | class_destroy(vfio.class); |
1489 | vfio.class = NULL; | 1483 | vfio.class = NULL; |
1490 | err_class: | 1484 | err_class: |
1485 | misc_deregister(&vfio_dev); | ||
1491 | return ret; | 1486 | return ret; |
1492 | } | 1487 | } |
1493 | 1488 | ||
@@ -1497,11 +1492,10 @@ static void __exit vfio_cleanup(void) | |||
1497 | 1492 | ||
1498 | idr_destroy(&vfio.group_idr); | 1493 | idr_destroy(&vfio.group_idr); |
1499 | cdev_del(&vfio.group_cdev); | 1494 | cdev_del(&vfio.group_cdev); |
1500 | device_destroy(vfio.class, vfio.devt); | 1495 | unregister_chrdev_region(vfio.group_devt, MINORMASK); |
1501 | cdev_del(&vfio.cdev); | ||
1502 | unregister_chrdev_region(vfio.devt, MINORMASK); | ||
1503 | class_destroy(vfio.class); | 1496 | class_destroy(vfio.class); |
1504 | vfio.class = NULL; | 1497 | vfio.class = NULL; |
1498 | misc_deregister(&vfio_dev); | ||
1505 | } | 1499 | } |
1506 | 1500 | ||
1507 | module_init(vfio_init); | 1501 | module_init(vfio_init); |
@@ -1511,3 +1505,5 @@ MODULE_VERSION(DRIVER_VERSION); | |||
1511 | MODULE_LICENSE("GPL v2"); | 1505 | MODULE_LICENSE("GPL v2"); |
1512 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1506 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1513 | MODULE_DESCRIPTION(DRIVER_DESC); | 1507 | MODULE_DESCRIPTION(DRIVER_DESC); |
1508 | MODULE_ALIAS_MISCDEV(VFIO_MINOR); | ||
1509 | MODULE_ALIAS("devname:vfio/vfio"); | ||