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 @@ static struct vfio {
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 @@ EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
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 @@ 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
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 @@ static void vfio_group_release(struct kref *kref)
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 );
@@ -1419,12 +1418,17 @@ EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id);
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 @@ static int __init vfio_init(void)
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 );
@@ -1444,27 +1455,14 @@ static int __init vfio_init(void)
1444
1455
1445
1456
vfio .class -> devnode = vfio_devnode ;
1446
1457
1447
- ret = alloc_chrdev_region (& vfio .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 );
1458
+ ret = alloc_chrdev_region (& vfio .group_devt , 0 , MINORMASK , "vfio" );
1453
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
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
@@ -1478,16 +1476,13 @@ static int __init vfio_init(void)
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
@@ -1497,11 +1492,10 @@ static void __exit vfio_cleanup(void)
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,3 +1505,5 @@ MODULE_VERSION(DRIVER_VERSION);
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" );
0 commit comments