- Convert to misc driver to support module auto loading

- Remove unnecessary and dangerous use of device_lock
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJS4T1aAAoJECObm247sIsiLMkQAKn11qSLk880dJO+cfW2VpqL
 vm3WreShOxNsKTEQfcbrnJtS+kYGkiyo8+Vve377QDIg+xeXpNZa0PbAEfh4HyuJ
 NH+vn0FYDf3rzF4Z9snm2HOHWCAsqLCE0guyMwwhUYH+fks4+YTJWCm4YWZOXbIS
 aI++G+5LBxGzMRbotoovqUhQy474fpQN/GFIlIZHP2bGtdeXiRuH0qH3BxVKafOF
 50RtAgJsLm1Nb+S20Umsz+llL3sop1wcPLKOlgCXqd+545CJAoq/qqEPjUtOrr+S
 qXvXhb0XM7zo73H2WzkVmS09HZWX4sMoHBYp8D6ToOIFF01LOVsXBKduPCPpTD7E
 zohhjgag9/RQ99l2B153IIIv0Bsg7b4YXBQ6qkWFoJolPL94LTq1PXk0f9mNhyPo
 mSqatcAeI5qtjqu9ncSd4YYTdBgp7SJcgwji8fI44tvzzpz8iheVUrpwcU1UumAK
 TpXLBoTLXllK1op3u9xgFrF4ISBMl7lZeZp3c1/1YRga7Ch6SdlB0tcLPfuSBRF0
 1Qb5jQrWz4qt/oZSkapcFALXQDgwoK8am9I0a5YXdhy9gSYm+o/TLwG5pTEnF4In
 xxuibmmJAmNcTJ9q6rUKjLLU/TqRKin+vyqW6is41IredgvNX8XDS3YokA5Fgv01
 mu1s7odFi08xjPRuYvmq
 =t9+R
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2014-01-24 17:42:31 -08:00
commit 2d08cd0ef8
5 changed files with 39 additions and 54 deletions

View File

@ -409,6 +409,7 @@ Your cooperation is appreciated.
193 = /dev/d7s SPARC 7-segment display 193 = /dev/d7s SPARC 7-segment display
194 = /dev/zkshim Zero-Knowledge network shim control 194 = /dev/zkshim Zero-Knowledge network shim control
195 = /dev/elographics/e2201 Elographics touchscreen E271-2201 195 = /dev/elographics/e2201 Elographics touchscreen E271-2201
196 = /dev/vfio/vfio VFIO userspace driver interface
198 = /dev/sexec Signed executable interface 198 = /dev/sexec Signed executable interface
199 = /dev/scanners/cuecat :CueCat barcode scanner 199 = /dev/scanners/cuecat :CueCat barcode scanner
200 = /dev/net/tun TAP/TUN network device 200 = /dev/net/tun TAP/TUN network device

View File

@ -872,9 +872,13 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_DISCONNECT; return PCI_ERS_RESULT_DISCONNECT;
} }
mutex_lock(&vdev->igate);
if (vdev->err_trigger) if (vdev->err_trigger)
eventfd_signal(vdev->err_trigger, 1); eventfd_signal(vdev->err_trigger, 1);
mutex_unlock(&vdev->igate);
vfio_device_put(device); vfio_device_put(device);
return PCI_ERS_RESULT_CAN_RECOVER; return PCI_ERS_RESULT_CAN_RECOVER;

View File

@ -749,54 +749,37 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
unsigned count, uint32_t flags, void *data) unsigned count, uint32_t flags, void *data)
{ {
int32_t fd = *(int32_t *)data; int32_t fd = *(int32_t *)data;
struct pci_dev *pdev = vdev->pdev;
if ((index != VFIO_PCI_ERR_IRQ_INDEX) || if ((index != VFIO_PCI_ERR_IRQ_INDEX) ||
!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK)) !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
return -EINVAL; return -EINVAL;
/*
* device_lock synchronizes setting and checking of
* err_trigger. The vfio_pci_aer_err_detected() is also
* called with device_lock held.
*/
/* DATA_NONE/DATA_BOOL enables loopback testing */ /* DATA_NONE/DATA_BOOL enables loopback testing */
if (flags & VFIO_IRQ_SET_DATA_NONE) { if (flags & VFIO_IRQ_SET_DATA_NONE) {
device_lock(&pdev->dev);
if (vdev->err_trigger) if (vdev->err_trigger)
eventfd_signal(vdev->err_trigger, 1); eventfd_signal(vdev->err_trigger, 1);
device_unlock(&pdev->dev);
return 0; return 0;
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) { } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
uint8_t trigger = *(uint8_t *)data; uint8_t trigger = *(uint8_t *)data;
device_lock(&pdev->dev);
if (trigger && vdev->err_trigger) if (trigger && vdev->err_trigger)
eventfd_signal(vdev->err_trigger, 1); eventfd_signal(vdev->err_trigger, 1);
device_unlock(&pdev->dev);
return 0; return 0;
} }
/* Handle SET_DATA_EVENTFD */ /* Handle SET_DATA_EVENTFD */
if (fd == -1) { if (fd == -1) {
device_lock(&pdev->dev);
if (vdev->err_trigger) if (vdev->err_trigger)
eventfd_ctx_put(vdev->err_trigger); eventfd_ctx_put(vdev->err_trigger);
vdev->err_trigger = NULL; vdev->err_trigger = NULL;
device_unlock(&pdev->dev);
return 0; return 0;
} else if (fd >= 0) { } else if (fd >= 0) {
struct eventfd_ctx *efdctx; struct eventfd_ctx *efdctx;
efdctx = eventfd_ctx_fdget(fd); efdctx = eventfd_ctx_fdget(fd);
if (IS_ERR(efdctx)) if (IS_ERR(efdctx))
return PTR_ERR(efdctx); return PTR_ERR(efdctx);
device_lock(&pdev->dev);
if (vdev->err_trigger) if (vdev->err_trigger)
eventfd_ctx_put(vdev->err_trigger); eventfd_ctx_put(vdev->err_trigger);
vdev->err_trigger = efdctx; vdev->err_trigger = efdctx;
device_unlock(&pdev->dev);
return 0; return 0;
} else } else
return -EINVAL; return -EINVAL;

View File

@ -22,6 +22,7 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/miscdevice.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
@ -45,9 +46,7 @@ static struct vfio {
struct idr group_idr; struct idr group_idr;
struct mutex group_lock; struct mutex group_lock;
struct cdev group_cdev; struct cdev group_cdev;
struct device *dev; dev_t group_devt;
dev_t devt;
struct cdev cdev;
wait_queue_head_t release_q; wait_queue_head_t release_q;
} vfio; } vfio;
@ -142,8 +141,7 @@ EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
*/ */
static int vfio_alloc_group_minor(struct vfio_group *group) static int vfio_alloc_group_minor(struct vfio_group *group)
{ {
/* index 0 is used by /dev/vfio/vfio */ return idr_alloc(&vfio.group_idr, group, 0, MINORMASK + 1, GFP_KERNEL);
return idr_alloc(&vfio.group_idr, group, 1, MINORMASK + 1, GFP_KERNEL);
} }
static void vfio_free_group_minor(int minor) static void vfio_free_group_minor(int minor)
@ -243,7 +241,8 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
} }
} }
dev = device_create(vfio.class, NULL, MKDEV(MAJOR(vfio.devt), minor), dev = device_create(vfio.class, NULL,
MKDEV(MAJOR(vfio.group_devt), minor),
group, "%d", iommu_group_id(iommu_group)); group, "%d", iommu_group_id(iommu_group));
if (IS_ERR(dev)) { if (IS_ERR(dev)) {
vfio_free_group_minor(minor); vfio_free_group_minor(minor);
@ -268,7 +267,7 @@ static void vfio_group_release(struct kref *kref)
WARN_ON(!list_empty(&group->device_list)); WARN_ON(!list_empty(&group->device_list));
device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); device_destroy(vfio.class, MKDEV(MAJOR(vfio.group_devt), group->minor));
list_del(&group->vfio_next); list_del(&group->vfio_next);
vfio_free_group_minor(group->minor); vfio_free_group_minor(group->minor);
vfio_group_unlock_and_free(group); vfio_group_unlock_and_free(group);
@ -1419,12 +1418,17 @@ EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id);
*/ */
static char *vfio_devnode(struct device *dev, umode_t *mode) static char *vfio_devnode(struct device *dev, umode_t *mode)
{ {
if (mode && (MINOR(dev->devt) == 0))
*mode = S_IRUGO | S_IWUGO;
return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev)); return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev));
} }
static struct miscdevice vfio_dev = {
.minor = VFIO_MINOR,
.name = "vfio",
.fops = &vfio_fops,
.nodename = "vfio/vfio",
.mode = S_IRUGO | S_IWUGO,
};
static int __init vfio_init(void) static int __init vfio_init(void)
{ {
int ret; int ret;
@ -1436,6 +1440,13 @@ static int __init vfio_init(void)
INIT_LIST_HEAD(&vfio.iommu_drivers_list); INIT_LIST_HEAD(&vfio.iommu_drivers_list);
init_waitqueue_head(&vfio.release_q); init_waitqueue_head(&vfio.release_q);
ret = misc_register(&vfio_dev);
if (ret) {
pr_err("vfio: misc device register failed\n");
return ret;
}
/* /dev/vfio/$GROUP */
vfio.class = class_create(THIS_MODULE, "vfio"); vfio.class = class_create(THIS_MODULE, "vfio");
if (IS_ERR(vfio.class)) { if (IS_ERR(vfio.class)) {
ret = PTR_ERR(vfio.class); ret = PTR_ERR(vfio.class);
@ -1444,27 +1455,14 @@ static int __init vfio_init(void)
vfio.class->devnode = vfio_devnode; vfio.class->devnode = vfio_devnode;
ret = alloc_chrdev_region(&vfio.devt, 0, MINORMASK, "vfio"); ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio");
if (ret) if (ret)
goto err_base_chrdev; goto err_alloc_chrdev;
cdev_init(&vfio.cdev, &vfio_fops);
ret = cdev_add(&vfio.cdev, vfio.devt, 1);
if (ret)
goto err_base_cdev;
vfio.dev = device_create(vfio.class, NULL, vfio.devt, NULL, "vfio");
if (IS_ERR(vfio.dev)) {
ret = PTR_ERR(vfio.dev);
goto err_base_dev;
}
/* /dev/vfio/$GROUP */
cdev_init(&vfio.group_cdev, &vfio_group_fops); cdev_init(&vfio.group_cdev, &vfio_group_fops);
ret = cdev_add(&vfio.group_cdev, ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK);
MKDEV(MAJOR(vfio.devt), 1), MINORMASK - 1);
if (ret) if (ret)
goto err_groups_cdev; goto err_cdev_add;
pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
@ -1478,16 +1476,13 @@ static int __init vfio_init(void)
return 0; return 0;
err_groups_cdev: err_cdev_add:
device_destroy(vfio.class, vfio.devt); unregister_chrdev_region(vfio.group_devt, MINORMASK);
err_base_dev: err_alloc_chrdev:
cdev_del(&vfio.cdev);
err_base_cdev:
unregister_chrdev_region(vfio.devt, MINORMASK);
err_base_chrdev:
class_destroy(vfio.class); class_destroy(vfio.class);
vfio.class = NULL; vfio.class = NULL;
err_class: err_class:
misc_deregister(&vfio_dev);
return ret; return ret;
} }
@ -1497,11 +1492,10 @@ static void __exit vfio_cleanup(void)
idr_destroy(&vfio.group_idr); idr_destroy(&vfio.group_idr);
cdev_del(&vfio.group_cdev); cdev_del(&vfio.group_cdev);
device_destroy(vfio.class, vfio.devt); unregister_chrdev_region(vfio.group_devt, MINORMASK);
cdev_del(&vfio.cdev);
unregister_chrdev_region(vfio.devt, MINORMASK);
class_destroy(vfio.class); class_destroy(vfio.class);
vfio.class = NULL; vfio.class = NULL;
misc_deregister(&vfio_dev);
} }
module_init(vfio_init); module_init(vfio_init);
@ -1511,3 +1505,5 @@ MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS_MISCDEV(VFIO_MINOR);
MODULE_ALIAS("devname:vfio/vfio");

View File

@ -30,6 +30,7 @@
#define STORE_QUEUE_MINOR 155 #define STORE_QUEUE_MINOR 155
#define I2O_MINOR 166 #define I2O_MINOR 166
#define MICROCODE_MINOR 184 #define MICROCODE_MINOR 184
#define VFIO_MINOR 196
#define TUN_MINOR 200 #define TUN_MINOR 200
#define CUSE_MINOR 203 #define CUSE_MINOR 203
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */ #define MWAVE_MINOR 219 /* ACP/Mwave Modem */