aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-12-19 12:17:13 -0500
committerAlex Williamson <alex.williamson@redhat.com>2013-12-19 12:17:13 -0500
commitd10999016f4164e9b80f1b3dece3842087cfa3bb (patch)
tree8c739c70480d451e1c0e62c1cf1f8f695f4071ce
parent8dcf94bcff5bf3b54380ae2a17b034fb3b9d58e5 (diff)
vfio: Convert control interface to misc driver
This change allows us to support module auto loading using devname support in userspace tools. With this, /dev/vfio/vfio will always be present and opening it will cause the vfio module to load. This should avoid needing to configure the system to statically load vfio in order to get libvirt to correctly detect support for it. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r--drivers/vfio/vfio.c70
1 files changed, 33 insertions, 37 deletions
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 */
143static int vfio_alloc_group_minor(struct vfio_group *group) 142static 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
149static void vfio_free_group_minor(int minor) 147static 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 */
1420static char *vfio_devnode(struct device *dev, umode_t *mode) 1419static 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
1424static 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
1428static int __init vfio_init(void) 1432static 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
1481err_groups_cdev: 1479err_cdev_add:
1482 device_destroy(vfio.class, vfio.devt); 1480 unregister_chrdev_region(vfio.group_devt, MINORMASK);
1483err_base_dev: 1481err_alloc_chrdev:
1484 cdev_del(&vfio.cdev);
1485err_base_cdev:
1486 unregister_chrdev_region(vfio.devt, MINORMASK);
1487err_base_chrdev:
1488 class_destroy(vfio.class); 1482 class_destroy(vfio.class);
1489 vfio.class = NULL; 1483 vfio.class = NULL;
1490err_class: 1484err_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
1507module_init(vfio_init); 1501module_init(vfio_init);
@@ -1511,3 +1505,5 @@ MODULE_VERSION(DRIVER_VERSION);
1511MODULE_LICENSE("GPL v2"); 1505MODULE_LICENSE("GPL v2");
1512MODULE_AUTHOR(DRIVER_AUTHOR); 1506MODULE_AUTHOR(DRIVER_AUTHOR);
1513MODULE_DESCRIPTION(DRIVER_DESC); 1507MODULE_DESCRIPTION(DRIVER_DESC);
1508MODULE_ALIAS_MISCDEV(VFIO_MINOR);
1509MODULE_ALIAS("devname:vfio/vfio");