- 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
|
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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue