Commit 2d08cd0ef89a24f5eb6c6801c48cd06bca230d6d
Exists in
master
and in
16 other branches
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
Showing 5 changed files Side-by-side Diff
Documentation/devices.txt
... | ... | @@ -409,6 +409,7 @@ |
409 | 409 | 193 = /dev/d7s SPARC 7-segment display |
410 | 410 | 194 = /dev/zkshim Zero-Knowledge network shim control |
411 | 411 | 195 = /dev/elographics/e2201 Elographics touchscreen E271-2201 |
412 | + 196 = /dev/vfio/vfio VFIO userspace driver interface | |
412 | 413 | 198 = /dev/sexec Signed executable interface |
413 | 414 | 199 = /dev/scanners/cuecat :CueCat barcode scanner |
414 | 415 | 200 = /dev/net/tun TAP/TUN network device |
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_intrs.c
... | ... | @@ -749,54 +749,37 @@ |
749 | 749 | unsigned count, uint32_t flags, void *data) |
750 | 750 | { |
751 | 751 | int32_t fd = *(int32_t *)data; |
752 | - struct pci_dev *pdev = vdev->pdev; | |
753 | 752 | |
754 | 753 | if ((index != VFIO_PCI_ERR_IRQ_INDEX) || |
755 | 754 | !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK)) |
756 | 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 | 757 | /* DATA_NONE/DATA_BOOL enables loopback testing */ |
765 | - | |
766 | 758 | if (flags & VFIO_IRQ_SET_DATA_NONE) { |
767 | - device_lock(&pdev->dev); | |
768 | 759 | if (vdev->err_trigger) |
769 | 760 | eventfd_signal(vdev->err_trigger, 1); |
770 | - device_unlock(&pdev->dev); | |
771 | 761 | return 0; |
772 | 762 | } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { |
773 | 763 | uint8_t trigger = *(uint8_t *)data; |
774 | - device_lock(&pdev->dev); | |
775 | 764 | if (trigger && vdev->err_trigger) |
776 | 765 | eventfd_signal(vdev->err_trigger, 1); |
777 | - device_unlock(&pdev->dev); | |
778 | 766 | return 0; |
779 | 767 | } |
780 | 768 | |
781 | 769 | /* Handle SET_DATA_EVENTFD */ |
782 | - | |
783 | 770 | if (fd == -1) { |
784 | - device_lock(&pdev->dev); | |
785 | 771 | if (vdev->err_trigger) |
786 | 772 | eventfd_ctx_put(vdev->err_trigger); |
787 | 773 | vdev->err_trigger = NULL; |
788 | - device_unlock(&pdev->dev); | |
789 | 774 | return 0; |
790 | 775 | } else if (fd >= 0) { |
791 | 776 | struct eventfd_ctx *efdctx; |
792 | 777 | efdctx = eventfd_ctx_fdget(fd); |
793 | 778 | if (IS_ERR(efdctx)) |
794 | 779 | return PTR_ERR(efdctx); |
795 | - device_lock(&pdev->dev); | |
796 | 780 | if (vdev->err_trigger) |
797 | 781 | eventfd_ctx_put(vdev->err_trigger); |
798 | 782 | vdev->err_trigger = efdctx; |
799 | - device_unlock(&pdev->dev); | |
800 | 783 | return 0; |
801 | 784 | } else |
802 | 785 | return -EINVAL; |
drivers/vfio/vfio.c
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | #include <linux/idr.h> |
23 | 23 | #include <linux/iommu.h> |
24 | 24 | #include <linux/list.h> |
25 | +#include <linux/miscdevice.h> | |
25 | 26 | #include <linux/module.h> |
26 | 27 | #include <linux/mutex.h> |
27 | 28 | #include <linux/rwsem.h> |
... | ... | @@ -45,9 +46,7 @@ |
45 | 46 | struct idr group_idr; |
46 | 47 | struct mutex group_lock; |
47 | 48 | struct cdev group_cdev; |
48 | - struct device *dev; | |
49 | - dev_t devt; | |
50 | - struct cdev cdev; | |
49 | + dev_t group_devt; | |
51 | 50 | wait_queue_head_t release_q; |
52 | 51 | } vfio; |
53 | 52 | |
... | ... | @@ -142,8 +141,7 @@ |
142 | 141 | */ |
143 | 142 | static int vfio_alloc_group_minor(struct vfio_group *group) |
144 | 143 | { |
145 | - /* index 0 is used by /dev/vfio/vfio */ | |
146 | - return idr_alloc(&vfio.group_idr, group, 1, MINORMASK + 1, GFP_KERNEL); | |
144 | + return idr_alloc(&vfio.group_idr, group, 0, MINORMASK + 1, GFP_KERNEL); | |
147 | 145 | } |
148 | 146 | |
149 | 147 | static void vfio_free_group_minor(int minor) |
... | ... | @@ -243,7 +241,8 @@ |
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 | 246 | group, "%d", iommu_group_id(iommu_group)); |
248 | 247 | if (IS_ERR(dev)) { |
249 | 248 | vfio_free_group_minor(minor); |
... | ... | @@ -268,7 +267,7 @@ |
268 | 267 | |
269 | 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 | 271 | list_del(&group->vfio_next); |
273 | 272 | vfio_free_group_minor(group->minor); |
274 | 273 | vfio_group_unlock_and_free(group); |
275 | 274 | |
... | ... | @@ -1419,12 +1418,17 @@ |
1419 | 1418 | */ |
1420 | 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 | 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 | 1432 | static int __init vfio_init(void) |
1429 | 1433 | { |
1430 | 1434 | int ret; |
... | ... | @@ -1436,6 +1440,13 @@ |
1436 | 1440 | INIT_LIST_HEAD(&vfio.iommu_drivers_list); |
1437 | 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 | 1450 | vfio.class = class_create(THIS_MODULE, "vfio"); |
1440 | 1451 | if (IS_ERR(vfio.class)) { |
1441 | 1452 | ret = PTR_ERR(vfio.class); |
1442 | 1453 | |
1443 | 1454 | |
1444 | 1455 | |
1445 | 1456 | |
... | ... | @@ -1444,27 +1455,14 @@ |
1444 | 1455 | |
1445 | 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 | 1459 | if (ret) |
1449 | - goto err_base_chrdev; | |
1460 | + goto err_alloc_chrdev; | |
1450 | 1461 | |
1451 | - cdev_init(&vfio.cdev, &vfio_fops); | |
1452 | - ret = cdev_add(&vfio.cdev, vfio.devt, 1); | |
1453 | - if (ret) | |
1454 | - goto err_base_cdev; | |
1455 | - | |
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 | 1462 | cdev_init(&vfio.group_cdev, &vfio_group_fops); |
1464 | - ret = cdev_add(&vfio.group_cdev, | |
1465 | - MKDEV(MAJOR(vfio.devt), 1), MINORMASK - 1); | |
1463 | + ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK); | |
1466 | 1464 | if (ret) |
1467 | - goto err_groups_cdev; | |
1465 | + goto err_cdev_add; | |
1468 | 1466 | |
1469 | 1467 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
1470 | 1468 | |
1471 | 1469 | |
... | ... | @@ -1478,16 +1476,13 @@ |
1478 | 1476 | |
1479 | 1477 | return 0; |
1480 | 1478 | |
1481 | -err_groups_cdev: | |
1482 | - device_destroy(vfio.class, vfio.devt); | |
1483 | -err_base_dev: | |
1484 | - cdev_del(&vfio.cdev); | |
1485 | -err_base_cdev: | |
1486 | - unregister_chrdev_region(vfio.devt, MINORMASK); | |
1487 | -err_base_chrdev: | |
1479 | +err_cdev_add: | |
1480 | + unregister_chrdev_region(vfio.group_devt, MINORMASK); | |
1481 | +err_alloc_chrdev: | |
1488 | 1482 | class_destroy(vfio.class); |
1489 | 1483 | vfio.class = NULL; |
1490 | 1484 | err_class: |
1485 | + misc_deregister(&vfio_dev); | |
1491 | 1486 | return ret; |
1492 | 1487 | } |
1493 | 1488 | |
1494 | 1489 | |
... | ... | @@ -1497,11 +1492,10 @@ |
1497 | 1492 | |
1498 | 1493 | idr_destroy(&vfio.group_idr); |
1499 | 1494 | cdev_del(&vfio.group_cdev); |
1500 | - device_destroy(vfio.class, vfio.devt); | |
1501 | - cdev_del(&vfio.cdev); | |
1502 | - unregister_chrdev_region(vfio.devt, MINORMASK); | |
1495 | + unregister_chrdev_region(vfio.group_devt, MINORMASK); | |
1503 | 1496 | class_destroy(vfio.class); |
1504 | 1497 | vfio.class = NULL; |
1498 | + misc_deregister(&vfio_dev); | |
1505 | 1499 | } |
1506 | 1500 | |
1507 | 1501 | module_init(vfio_init); |
... | ... | @@ -1511,4 +1505,6 @@ |
1511 | 1505 | MODULE_LICENSE("GPL v2"); |
1512 | 1506 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1513 | 1507 | MODULE_DESCRIPTION(DRIVER_DESC); |
1508 | +MODULE_ALIAS_MISCDEV(VFIO_MINOR); | |
1509 | +MODULE_ALIAS("devname:vfio/vfio"); |
include/linux/miscdevice.h