- 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:
commit
2d08cd0ef8
|
@ -409,6 +409,7 @@ Your cooperation is appreciated.
|
|||
193 = /dev/d7s SPARC 7-segment display
|
||||
194 = /dev/zkshim Zero-Knowledge network shim control
|
||||
195 = /dev/elographics/e2201 Elographics touchscreen E271-2201
|
||||
196 = /dev/vfio/vfio VFIO userspace driver interface
|
||||
198 = /dev/sexec Signed executable interface
|
||||
199 = /dev/scanners/cuecat :CueCat barcode scanner
|
||||
200 = /dev/net/tun TAP/TUN network device
|
||||
|
|
|
@ -872,9 +872,13 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
|
|||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
mutex_lock(&vdev->igate);
|
||||
|
||||
if (vdev->err_trigger)
|
||||
eventfd_signal(vdev->err_trigger, 1);
|
||||
|
||||
mutex_unlock(&vdev->igate);
|
||||
|
||||
vfio_device_put(device);
|
||||
|
||||
return PCI_ERS_RESULT_CAN_RECOVER;
|
||||
|
|
|
@ -749,54 +749,37 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
|
|||
unsigned count, uint32_t flags, void *data)
|
||||
{
|
||||
int32_t fd = *(int32_t *)data;
|
||||
struct pci_dev *pdev = vdev->pdev;
|
||||
|
||||
if ((index != VFIO_PCI_ERR_IRQ_INDEX) ||
|
||||
!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
|
||||
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 */
|
||||
|
||||
if (flags & VFIO_IRQ_SET_DATA_NONE) {
|
||||
device_lock(&pdev->dev);
|
||||
if (vdev->err_trigger)
|
||||
eventfd_signal(vdev->err_trigger, 1);
|
||||
device_unlock(&pdev->dev);
|
||||
return 0;
|
||||
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
|
||||
uint8_t trigger = *(uint8_t *)data;
|
||||
device_lock(&pdev->dev);
|
||||
if (trigger && vdev->err_trigger)
|
||||
eventfd_signal(vdev->err_trigger, 1);
|
||||
device_unlock(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle SET_DATA_EVENTFD */
|
||||
|
||||
if (fd == -1) {
|
||||
device_lock(&pdev->dev);
|
||||
if (vdev->err_trigger)
|
||||
eventfd_ctx_put(vdev->err_trigger);
|
||||
vdev->err_trigger = NULL;
|
||||
device_unlock(&pdev->dev);
|
||||
return 0;
|
||||
} else if (fd >= 0) {
|
||||
struct eventfd_ctx *efdctx;
|
||||
efdctx = eventfd_ctx_fdget(fd);
|
||||
if (IS_ERR(efdctx))
|
||||
return PTR_ERR(efdctx);
|
||||
device_lock(&pdev->dev);
|
||||
if (vdev->err_trigger)
|
||||
eventfd_ctx_put(vdev->err_trigger);
|
||||
vdev->err_trigger = efdctx;
|
||||
device_unlock(&pdev->dev);
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/idr.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rwsem.h>
|
||||
|
@ -45,9 +46,7 @@ static struct vfio {
|
|||
struct idr group_idr;
|
||||
struct mutex group_lock;
|
||||
struct cdev group_cdev;
|
||||
struct device *dev;
|
||||
dev_t devt;
|
||||
struct cdev cdev;
|
||||
dev_t group_devt;
|
||||
wait_queue_head_t release_q;
|
||||
} vfio;
|
||||
|
||||
|
@ -142,8 +141,7 @@ EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
|
|||
*/
|
||||
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, 1, MINORMASK + 1, GFP_KERNEL);
|
||||
return idr_alloc(&vfio.group_idr, group, 0, MINORMASK + 1, GFP_KERNEL);
|
||||
}
|
||||
|
||||
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));
|
||||
if (IS_ERR(dev)) {
|
||||
vfio_free_group_minor(minor);
|
||||
|
@ -268,7 +267,7 @@ static void vfio_group_release(struct kref *kref)
|
|||
|
||||
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);
|
||||
vfio_free_group_minor(group->minor);
|
||||
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)
|
||||
{
|
||||
if (mode && (MINOR(dev->devt) == 0))
|
||||
*mode = S_IRUGO | S_IWUGO;
|
||||
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1436,6 +1440,13 @@ static int __init vfio_init(void)
|
|||
INIT_LIST_HEAD(&vfio.iommu_drivers_list);
|
||||
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");
|
||||
if (IS_ERR(vfio.class)) {
|
||||
ret = PTR_ERR(vfio.class);
|
||||
|
@ -1444,27 +1455,14 @@ static int __init vfio_init(void)
|
|||
|
||||
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)
|
||||
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);
|
||||
ret = cdev_add(&vfio.group_cdev,
|
||||
MKDEV(MAJOR(vfio.devt), 1), MINORMASK - 1);
|
||||
ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK);
|
||||
if (ret)
|
||||
goto err_groups_cdev;
|
||||
goto err_cdev_add;
|
||||
|
||||
pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
|
||||
|
@ -1478,16 +1476,13 @@ static int __init vfio_init(void)
|
|||
|
||||
return 0;
|
||||
|
||||
err_groups_cdev:
|
||||
device_destroy(vfio.class, vfio.devt);
|
||||
err_base_dev:
|
||||
cdev_del(&vfio.cdev);
|
||||
err_base_cdev:
|
||||
unregister_chrdev_region(vfio.devt, MINORMASK);
|
||||
err_base_chrdev:
|
||||
err_cdev_add:
|
||||
unregister_chrdev_region(vfio.group_devt, MINORMASK);
|
||||
err_alloc_chrdev:
|
||||
class_destroy(vfio.class);
|
||||
vfio.class = NULL;
|
||||
err_class:
|
||||
misc_deregister(&vfio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1497,11 +1492,10 @@ static void __exit vfio_cleanup(void)
|
|||
|
||||
idr_destroy(&vfio.group_idr);
|
||||
cdev_del(&vfio.group_cdev);
|
||||
device_destroy(vfio.class, vfio.devt);
|
||||
cdev_del(&vfio.cdev);
|
||||
unregister_chrdev_region(vfio.devt, MINORMASK);
|
||||
unregister_chrdev_region(vfio.group_devt, MINORMASK);
|
||||
class_destroy(vfio.class);
|
||||
vfio.class = NULL;
|
||||
misc_deregister(&vfio_dev);
|
||||
}
|
||||
|
||||
module_init(vfio_init);
|
||||
|
@ -1511,3 +1505,5 @@ MODULE_VERSION(DRIVER_VERSION);
|
|||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_ALIAS_MISCDEV(VFIO_MINOR);
|
||||
MODULE_ALIAS("devname:vfio/vfio");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define STORE_QUEUE_MINOR 155
|
||||
#define I2O_MINOR 166
|
||||
#define MICROCODE_MINOR 184
|
||||
#define VFIO_MINOR 196
|
||||
#define TUN_MINOR 200
|
||||
#define CUSE_MINOR 203
|
||||
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */
|
||||
|
|
Loading…
Reference in New Issue