diff options
Diffstat (limited to 'drivers/uio')
-rw-r--r-- | drivers/uio/uio.c | 16 | ||||
-rw-r--r-- | drivers/uio/uio_pci_generic.c | 17 |
2 files changed, 27 insertions, 6 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 131342280b46..a57698985f9c 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -491,10 +491,10 @@ static int uio_open(struct inode *inode, struct file *filep) if (!idev->info) { mutex_unlock(&idev->info_lock); ret = -EINVAL; - goto err_alloc_listener; + goto err_infoopen; } - if (idev->info && idev->info->open) + if (idev->info->open) ret = idev->info->open(idev->info, inode); mutex_unlock(&idev->info_lock); if (ret) @@ -635,7 +635,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf, goto out; } - if (!idev->info || !idev->info->irq) { + if (!idev->info->irq) { retval = -EIO; goto out; } @@ -940,9 +940,12 @@ int __uio_register_device(struct module *owner, atomic_set(&idev->event, 0); ret = uio_get_minor(idev); - if (ret) + if (ret) { + kfree(idev); return ret; + } + device_initialize(&idev->dev); idev->dev.devt = MKDEV(uio_major, idev->minor); idev->dev.class = &uio_class; idev->dev.parent = parent; @@ -953,7 +956,7 @@ int __uio_register_device(struct module *owner, if (ret) goto err_device_create; - ret = device_register(&idev->dev); + ret = device_add(&idev->dev); if (ret) goto err_device_create; @@ -985,9 +988,10 @@ int __uio_register_device(struct module *owner, err_request_irq: uio_dev_del_attributes(idev); err_uio_dev_add_attributes: - device_unregister(&idev->dev); + device_del(&idev->dev); err_device_create: uio_free_minor(idev); + put_device(&idev->dev); return ret; } EXPORT_SYMBOL_GPL(__uio_register_device); diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index 8773e373ffe5..dde5cbb27178 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -39,6 +39,22 @@ to_uio_pci_generic_dev(struct uio_info *info) return container_of(info, struct uio_pci_generic_dev, info); } +static int release(struct uio_info *info, struct inode *inode) +{ + struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info); + + /* + * This driver is insecure when used with devices doing DMA, but some + * people (mis)use it with such devices. + * Let's at least make sure DMA isn't left enabled after the userspace + * driver closes the fd. + * Note that there's a non-zero chance doing this will wedge the device + * at least until reset. + */ + pci_clear_master(gdev->pdev); + return 0; +} + /* Interrupt handler. Read/modify/write the command register to disable * the interrupt. */ static irqreturn_t irqhandler(int irq, struct uio_info *info) @@ -78,6 +94,7 @@ static int probe(struct pci_dev *pdev, gdev->info.name = "uio_pci_generic"; gdev->info.version = DRIVER_VERSION; + gdev->info.release = release; gdev->pdev = pdev; if (pdev->irq) { gdev->info.irq = pdev->irq; |