The patch titled revert gregkh-driver-uio has been removed from the -mm tree. Its filename was revert-gregkh-driver-uio.patch This patch was dropped because it was merged into mainline or a subsystem tree ------------------------------------------------------ Subject: revert gregkh-driver-uio From: Andrew Morton <akpm@xxxxxxxx> Alan sayeth We had a discussion a while back about drivers/uio and the fact the stuff was buggy, contained security holes and not really fit/ready for -mm. Since that point nobody has fixed it (in part because they are doing vastly cooler stuff elsewhere in the kernel) so I think its time drivers/uio in -mm talk a walk to the bitbucket until someone makes it secure and resurrects it if needed. So given the elapsed time NACK: drivers/uio This is actually part of Greg's tree so -mm needs an explicit and additional revert patch. Cc: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx> Cc: Greg KH <greg@xxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- Documentation/DocBook/kernel-api.tmpl | 5 drivers/Kconfig | 2 drivers/Makefile | 1 drivers/uio/Kconfig | 15 drivers/uio/Makefile | 4 drivers/uio/uio_base.c | 438 ------------------------ drivers/uio/uio_dev.c | 366 -------------------- drivers/uio/uio_dummy.c | 268 -------------- include/linux/uio_driver.h | 106 ----- 9 files changed, 1205 deletions(-) diff -puN Documentation/DocBook/kernel-api.tmpl~revert-gregkh-driver-uio Documentation/DocBook/kernel-api.tmpl --- a/Documentation/DocBook/kernel-api.tmpl~revert-gregkh-driver-uio +++ a/Documentation/DocBook/kernel-api.tmpl @@ -393,11 +393,6 @@ X!Edrivers/pnp/system.c !Edrivers/pnp/manager.c !Edrivers/pnp/support.c </sect1> - <sect1><title>Industrial IO device driver</title> -!Edrivers/uio/uio_base.c -!Edrivers/uio/uio_dev.c -!Iinclude/linux/uio.h - </sect1> </chapter> <chapter id="blkdev"> diff -puN drivers/Kconfig~revert-gregkh-driver-uio drivers/Kconfig --- a/drivers/Kconfig~revert-gregkh-driver-uio +++ a/drivers/Kconfig @@ -78,6 +78,4 @@ source "drivers/rtc/Kconfig" source "drivers/dma/Kconfig" -source "drivers/uio/Kconfig" - endmenu diff -puN drivers/Makefile~revert-gregkh-driver-uio drivers/Makefile --- a/drivers/Makefile~revert-gregkh-driver-uio +++ a/drivers/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ -obj-$(CONFIG_UIO) += uio/ obj-y += cdrom/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/ diff -puN drivers/uio/Kconfig~revert-gregkh-driver-uio /dev/null --- a/drivers/uio/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -menu "Userspace I/O" -config UIO - tristate "Userspace I/O drivers" - help - Enable this to allow the userspace driver core code to be - built. This code allows userspace programs easy access to - kernel interrupts and memory locations, allowing some drivers - to be written in userspace. Note that a small kernel driver - is also required for interrupt handling to work properly. - -#config UIO_DUMMY -# tristate "Industrial IO dummy driver" -# help -# example/dummy driver for industrial IO -endmenu diff -puN drivers/uio/Makefile~revert-gregkh-driver-uio /dev/null --- a/drivers/uio/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_UIO) += uio.o -obj-$(CONFIG_UIO_DUMMY) += uio_dummy.o - -uio-objs := uio_base.o uio_dev.o diff -puN drivers/uio/uio_base.c~revert-gregkh-driver-uio /dev/null --- a/drivers/uio/uio_base.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * driver/uio/uio_base.c - * - * Copyright(C) 2005, Benedikt Spranger <b.spranger@xxxxxxxxxxxxx> - * Copyright(C) 2005, Thomas Gleixner <tglx@xxxxxxxxxxxxx> - * - * Industrial IO - * - * Base Functions - * - * Licensed under the GPLv2 only. - */ - -#define DEBUG - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/uio_driver.h> -#include <linux/hrtimer.h> - -/* - * The uio class. - */ - -static struct class *uio_class; - -static const char version[] = "0.00"; -static struct list_head uio_devices = LIST_HEAD_INIT(uio_devices); -static struct rw_semaphore uio_list_sem; - -static const char *uio_dev_ext[] = { - "", - "_in", - "_out", - "_event" -}; - -struct uio_class_dev { - struct list_head list; - int dev_nr; - struct class_device *cdev [4]; - dev_t dev; -}; - -extern struct file_operations uio_event_fops; - -/* - * attributes - */ -static ssize_t show_uio_version(struct class *cd, char *buf) -{ - sprintf(buf, "%s\n", version); - return strlen(buf) + 1; -} -static CLASS_ATTR(version, S_IRUGO, show_uio_version, NULL); - -static ssize_t show_addr(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "0x%lx\n", idev->physaddr); -} -static DEVICE_ATTR(physaddr, S_IRUGO, show_addr, NULL); - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "%s\n", idev->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static ssize_t show_read_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "0x%lx\n", idev->read_offset); -} -static DEVICE_ATTR(read_offset, S_IRUGO, show_read_offset, NULL); - -static ssize_t show_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "0x%lx\n", idev->size); -} -static DEVICE_ATTR(size, S_IRUGO, show_size, NULL); - -static ssize_t show_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "%s\n", idev->version); -} -static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); - -static ssize_t show_write_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "0x%lx\n", idev->write_offset); -} -static DEVICE_ATTR(write_offset, S_IRUGO, show_write_offset, NULL); - -static ssize_t show_listener(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "%ld\n", idev->event_listener); -} -static DEVICE_ATTR(listener, S_IRUGO, show_listener, NULL); - -static ssize_t show_event(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uio_device *idev = to_uio_device(dev); - return sprintf(buf, "%d\n", atomic_read(&idev->event)); -} -static DEVICE_ATTR(event, S_IRUGO, show_event, NULL); - -/* - * device functions - */ -static void uio_dev_release(struct device *dev) -{ - pr_debug("%s\n", __FUNCTION__); -} - -static void uio_dev_create(dev_t dev, struct uio_device *idev) -{ - int ret; - pr_debug("%s\n", __FUNCTION__); - - cdev_init(&idev->cdev, idev->fops); - idev->cdev.owner = THIS_MODULE; - idev->cdev.ops = idev->fops; - ret = cdev_add(&idev->cdev, dev, 3); - if (ret) - printk(KERN_ERR "%s: cdev_add failed (%d)\n", __FUNCTION__, ret); - - cdev_init(&idev->event_cdev, &uio_event_fops); - idev->event_cdev.owner = THIS_MODULE; - idev->event_cdev.ops = &uio_event_fops; - ret = cdev_add(&idev->event_cdev, dev + 3, 1); - if (ret) - printk(KERN_ERR "%s: cdev_add failed (%d)\n", __FUNCTION__, ret); -} - -static void uio_dev_remove(struct uio_device *idev) -{ - pr_debug("%s\n", __FUNCTION__); - - cdev_del(&idev->cdev); - cdev_del(&idev->event_cdev); -} - -static void uio_dev_add_attributes(struct uio_device *idev) -{ - int ret; - - pr_debug("%s\n", __FUNCTION__); - - ret = device_create_file(&idev->dev, &dev_attr_name); - ret |= device_create_file(&idev->dev, &dev_attr_version); - ret |= device_create_file(&idev->dev, &dev_attr_listener); - ret |= device_create_file(&idev->dev, &dev_attr_event); - if (idev->physaddr) - ret |= device_create_file(&idev->dev, &dev_attr_physaddr); - if (idev->size) - ret |= device_create_file(&idev->dev, &dev_attr_size); - if (idev->read_offset >= 0) - ret |= device_create_file(&idev->dev, &dev_attr_read_offset); - if (idev->write_offset >= 0) - ret |= device_create_file(&idev->dev, &dev_attr_write_offset); - if (ret) - pr_debug("%s: error creating sysfs files\n", __FUNCTION__); -} - -static void uio_dev_del_attributes(struct uio_device *idev) -{ - pr_debug("%s\n", __FUNCTION__); - - device_remove_file(&idev->dev, &dev_attr_name); - device_remove_file(&idev->dev, &dev_attr_version); - device_remove_file(&idev->dev, &dev_attr_listener); - device_remove_file(&idev->dev, &dev_attr_event); - if (idev->physaddr) - device_remove_file(&idev->dev, &dev_attr_physaddr); - if (idev->size) - device_remove_file(&idev->dev, &dev_attr_size); - if (idev->read_offset >= 0) - device_remove_file(&idev->dev, &dev_attr_read_offset); - if (idev->write_offset >= 0) - device_remove_file(&idev->dev, &dev_attr_write_offset); -} - -/* - * polling mode - */ - -static void uio_do_poll(unsigned long data) -{ - struct uio_device *idev = (struct uio_device *)data; - - uio_interrupt(-1, idev); - mod_timer(&idev->poll_timer, jiffies + idev->freq); -} - - -#ifdef CONFIG_HIGH_RES_TIMERS -/* - * one shot mode - */ - -int uio_do_oneshot(void *data) -{ - struct uio_device *idev = (struct uio_device *)data; -// struct timespec next; - - atomic_inc(&idev->running); - daemonize("uio_oneshot"); - set_user_nice(current, -10); - current->flags |= PF_NOFREEZE; -//FIXME: Bene: new API -# if 0 - while (!atomic_read(&idev->terminate)) { - while (ktime_cmp_val(idev->next_event, == , KTIME_ZERO)) - schedule(); - ktime_to_timespec(&next, idev->next_event); - ktimer_nanosleep(&next, NULL, KTIMER_ABS); - ktime_set_scalar(idev->next_event, KTIME_ZERO); - uio_interrupt(-2, idev); - } -# endif - atomic_dec(&idev->running); - return 0; -} -#endif -/* - * class device functions - */ - -static int uio_assign_free_devnr(void) -{ - int dev_nr = 0; - struct uio_class_dev *entry; - - pr_debug("%s\n", __FUNCTION__); - - if (list_empty(&uio_devices)) - goto out; - - list_for_each_entry(entry, &uio_devices, list) { - if ((entry->dev_nr > dev_nr + 1) && (dev_nr != 0)) - break; - dev_nr = entry->dev_nr; - } -out: - return dev_nr + 1; -} - -/** - * uio_register_device - register a new industrial IO device - * - * @parent: parent device - * @idev: device capabilities - * - * returns UIO device driver identifier - */ - -int __devinit uio_register_device(struct device *parent, - struct uio_device *idev) { - int i, ret = -ENOMEM; - struct uio_class_dev *cdev; - - pr_debug("%s\n", __FUNCTION__); - - if (!idev->name || !idev->version) - return -EINVAL; - - cdev = kmalloc(sizeof(struct uio_class_dev), GFP_KERNEL); - if (!cdev) - goto out; - - if (parent) { - idev->dev.bus = parent->bus; - idev->dev.parent = parent; - } - idev->dev.release = uio_dev_release; - - down_write(&uio_list_sem); - cdev->dev_nr = uio_assign_free_devnr(); - - sprintf(idev->dev.bus_id, "uio%d", cdev->dev_nr); - if ((ret = device_register(&idev->dev))) - goto no_dev; - - alloc_chrdev_region(&cdev->dev, 0, 4, idev->dev.bus_id); - uio_dev_create(cdev->dev, idev); - uio_dev_add_attributes(idev); - list_add_tail(&cdev->list, &uio_devices); - - for (i = 0; i < 4; i++) { - cdev->cdev [i] = class_device_create(uio_class, NULL, - cdev->dev + i, - &idev->dev, "uio%d%s", - cdev->dev_nr, uio_dev_ext [i]); - if (IS_ERR(cdev->cdev [i])) { - printk(KERN_ERR "UIO: device register_failed\n"); - device_unregister(&idev->dev); - uio_dev_remove(idev); - unregister_chrdev_region(cdev->dev, 4); - ret = PTR_ERR(cdev->cdev [i]); - kfree(cdev); - break; - } - } - -no_dev: - up_write(&uio_list_sem); - - idev->dev.driver_data = (void *)cdev->dev_nr; - atomic_set(&idev->running, 0); - atomic_set(&idev->terminate, 0); - - if (idev->irq && idev->handler) { - init_waitqueue_head(&idev->wait); - atomic_set(&idev->event, 0); - - switch (idev->irq) { -#ifdef CONFIG_HIGH_RES_TIMERS - case -2: /* one shot mode */ - kernel_thread(uio_do_oneshot, idev, CLONE_KERNEL); - break; -#endif - case -1: /* cyclic */ - init_timer(&idev->poll_timer); - idev->poll_timer.data = (unsigned long)idev; - idev->poll_timer.function = uio_do_poll; - mod_timer(&idev->poll_timer, jiffies + idev->freq); - break; - - default: - /* Make this configurable !!! */ - ret = request_irq(idev->irq, uio_interrupt, - IRQF_SHARED, idev->name, idev); - } - } - - if (!ret) - ret = cdev->dev_nr; -out: - return ret; -} -EXPORT_SYMBOL_GPL(uio_register_device); - -/** - * uio_unregister_device - unregister a industrial IO device - * @dev_nr: UIO device driver identifier - * - * returns 0 on success - */ - -int __devexit uio_unregister_device(int dev_nr) -{ - int i, ret = -ENODEV; - struct uio_class_dev *entry, *tmp; - struct uio_device *idev; - - pr_debug("%s (%d)\n", __FUNCTION__, dev_nr); - - down_write(&uio_list_sem); - - list_for_each_entry_safe(entry, tmp, &uio_devices, list) { - if (entry->dev_nr == dev_nr) { - - idev = to_uio_device(entry->cdev [0]->dev); - - atomic_inc(&idev->terminate); - while (atomic_read(&idev->running)) - schedule(); - - if (idev->irq == -1) - del_timer_sync(&idev->poll_timer); - - uio_dev_remove(idev); - unregister_chrdev_region(entry->dev, 4); - uio_dev_del_attributes(idev); - for (i = 0; i < 4; i++) { - class_device_unregister(entry->cdev [i]); - } - device_unregister(&idev->dev); - list_del(&entry->list); - - kfree(entry); - break; - } - } - - up_write(&uio_list_sem); - return ret; -} -EXPORT_SYMBOL_GPL(uio_unregister_device); - -/* - * module - */ - -static int __init uio_init(void) -{ - int ret; - - init_rwsem(&uio_list_sem); - uio_class = class_create(THIS_MODULE, "uio"); - - if (IS_ERR(uio_class)) - return PTR_ERR(uio_class); - - ret = class_create_file(uio_class, &class_attr_version); - if (ret) - class_destroy(uio_class); - return ret; -} - -void __exit uio_exit(void) -{ - class_remove_file(uio_class, &class_attr_version); - class_destroy(uio_class); -} - -module_init(uio_init) -module_exit(uio_exit) - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Benedikt Spranger"); diff -puN drivers/uio/uio_dev.c~revert-gregkh-driver-uio /dev/null --- a/drivers/uio/uio_dev.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * drivers/uio/uio_dev.c - * - * Copyright(C) 2005, Benedikt Spranger <b.spranger@xxxxxxxxxxxxx> - * Copyright(C) 2005, Thomas Gleixner <tglx@xxxxxxxxxxxxx> - * - * Industrial IO - * - * Character Device related functions - * - * Licensed under the GPLv2 only. - */ - -#define DEBUG 1 - -#include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/mman.h> -#include <linux/poll.h> -#include <linux/uio_driver.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - -/** - * uio_lseek - UIO framework lseek implementation - * - */ -loff_t uio_lseek(struct file *filep, loff_t offset, int orig) -{ - struct uio_device *idev = filep->private_data; - - pr_debug("%s\n", __FUNCTION__); - - switch (orig) { - case 0: - filep->f_pos = offset; - break; - case 1: - filep->f_pos += offset; - break; - case 2: - filep->f_pos = idev->size + offset; - break; - } - - return (filep->f_pos >= idev->size) ? -EINVAL : filep->f_pos; -} -EXPORT_SYMBOL_GPL(uio_lseek); - -/** - * uio_read - UIO framework read implementation - * - */ -ssize_t uio_read(struct file *filep, char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = iminor(filep->f_dentry->d_inode); - struct uio_device *idev = filep->private_data; - int offset; - - pr_debug("%s\n", __FUNCTION__); - - switch (minor) { - case 0: if (filep->f_pos + count >= idev->size) - count = idev->size - filep->f_pos; - offset = 0; - break; - case 1: if (filep->f_pos + count >= idev->read_len) - count = idev->read_len - filep->f_pos; - offset = idev->read_offset; - break; - case 2: if (filep->f_pos + count >= idev->write_len) - count = idev->write_len - filep->f_pos; - offset = idev->write_offset; - break; - default: return -EFAULT; - } - - if (count < 0) - return 0; - - if (!idev->virtaddr) { - /* IO Ports */ - size_t i; - - for (i = 0; i < count; i++) - if (__put_user(inb(idev->physaddr + offset + i), - buf + i) < 0) - return -EFAULT; - } else { - /* IO Mem */ - if (copy_to_user(buf, idev->virtaddr + offset + - filep->f_pos, count)) - return -EFAULT; - } - - *ppos += count; - return count; -} -EXPORT_SYMBOL_GPL(uio_read); - -/** - * uio_write - UIO framework write implementation - * - */ -ssize_t uio_write(struct file *filep, const char __user * buf, size_t count, - loff_t *ppos) -{ - unsigned int minor = iminor(filep->f_dentry->d_inode); - struct uio_device *idev = filep->private_data; - int offset; - - pr_debug("%s\n", __FUNCTION__); - - switch (minor) { - case 0: if (filep->f_pos + count >= idev->size) - count = idev->size - filep->f_pos; - offset = 0; - break; - case 1: if (filep->f_pos + count >= idev->read_len) - count = idev->read_len - filep->f_pos; - offset = idev->read_offset; - break; - case 2: if (filep->f_pos + count >= idev->write_len) - count = idev->write_len - filep->f_pos; - offset = idev->write_offset; - break; - default: return -EFAULT; - } - - if (count < 0) - return 0; - - if (!idev->virtaddr) { - /* IO Ports */ - size_t i; - char c; - - for (i = 0; i < count; i++) { - if (__get_user(c, buf + i)) - return -EFAULT; - outb(c, idev->physaddr + offset + i); - } - } else { - /* IO Mem */ - if (copy_from_user(idev->virtaddr + offset + filep->f_pos, - buf, count)) - return -EFAULT; - } - - *ppos += count; - return count; -} -EXPORT_SYMBOL_GPL(uio_write); - -/** - * uio_open - UIO framework open implementation - * - */ -int uio_open(struct inode *inode, struct file *filep) -{ - struct uio_device *idev; - - pr_debug("%s\n", __FUNCTION__); - - idev = container_of(inode->i_cdev, struct uio_device, cdev); - filep->private_data = idev; - - return 0; -} -EXPORT_SYMBOL_GPL(uio_open); - -/** - * uio_mmap - UIO framework mmap implementation - * - */ -int uio_mmap(struct file *filep, struct vm_area_struct *vma) -{ - unsigned int minor = iminor(filep->f_dentry->d_inode); - struct uio_device *idev = filep->private_data; - unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start); - - pr_debug("%s\n", __FUNCTION__); - - switch (minor) { - case 0: if (size > idev->size) - return -EINVAL; - vma->vm_pgoff = idev->physaddr; - break; - case 1: if (size > idev->read_len) - return -EINVAL; - vma->vm_pgoff = idev->physaddr + idev->read_offset; - break; - case 2: if (size > idev->write_len) - return -EINVAL; - vma->vm_pgoff = idev->physaddr + idev->write_offset; - break; - default: return -EINVAL; - } - - vma->vm_flags |= VM_LOCKED | VM_IO; - - return remap_pfn_range(vma, - vma->vm_start, - idev->physaddr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); -} -EXPORT_SYMBOL_GPL(uio_mmap); - -/** - * uio_release - UIO framework release implementation - * - */ -int uio_release(struct inode *inode, struct file *filep) -{ - pr_debug("%s\n", __FUNCTION__); - - return 0; -} -EXPORT_SYMBOL_GPL(uio_release); - - -/* - * event interface - */ -int uio_event_open(struct inode *inode, struct file *filep) -{ - struct uio_device *idev; - - pr_debug("%s\n", __FUNCTION__); - - idev = container_of(inode->i_cdev, struct uio_device, event_cdev); - filep->private_data = idev; - idev->event_listener++; - - return 0; -} - -int uio_event_release(struct inode *inode, struct file *filep) -{ - struct uio_device *idev = filep->private_data; - - pr_debug("%s\n", __FUNCTION__); - - idev->event_listener--; - if (filep->f_flags & FASYNC) { - if (idev->fops->fasync) - idev->fops->fasync(-1, filep, 0); - } - - return 0; -} - -irqreturn_t uio_interrupt(int irq, void *dev_id) -{ - struct uio_device *idev = dev_id; - - if (idev->handler) - idev->handler(irq, dev_id); - - if (idev->event_listener) { - atomic_inc(&idev->event); - wake_up_interruptible(&idev->wait); - kill_fasync(&idev->async_queue, SIGIO, POLL_IN); - } - - return IRQ_HANDLED; -} - -static int uio_event_fasync(int fd, struct file *filep, int on) -{ - struct uio_device *idev = filep->private_data; - - return fasync_helper(fd, filep, on, &idev->async_queue); -} - -static unsigned int uio_event_poll(struct file *filep, poll_table *wait) -{ - struct uio_device *idev = filep->private_data; - - pr_debug("%s\n", __FUNCTION__); - - if (!idev->irq) - return -EIO; - - poll_wait(filep, &idev->wait, wait); - - return POLLIN | POLLRDNORM; -} - -static ssize_t uio_event_read(struct file *filep, char __user *buf, - size_t count, loff_t *ppos) -{ - struct uio_device *idev = filep->private_data; - DECLARE_WAITQUEUE(wait, current); - ssize_t retval; - int event_count; - - if (!idev->irq) - return -EIO; - - if (count > sizeof(int)) - count = sizeof(int); - - add_wait_queue(&idev->wait, &wait); - - do { - __set_current_state(TASK_INTERRUPTIBLE); - - event_count = atomic_read(&idev->event); - if (event_count) - break; - - if (filep->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - goto out; - } - schedule(); - } while (1); - - atomic_dec(&idev->event); - - if (copy_to_user(buf, &event_count, count)) - retval = -EFAULT; - else - retval = sizeof(int); - -out: - current->state = TASK_RUNNING; - remove_wait_queue(&idev->wait, &wait); - - return retval; -} - -ssize_t uio_event_write(struct file *filep, const char __user * buf, - size_t count, loff_t *ppos) -{ - struct uio_device *idev = filep->private_data; - - pr_debug("%s\n", __FUNCTION__); - - if (!idev->event_write) - return -EFAULT; - - return idev->event_write(filep, buf, count, ppos); -} - -struct file_operations uio_event_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = uio_event_read, - .write = uio_event_write, - .poll = uio_event_poll, - .open = uio_event_open, - .release = uio_event_release, - .fasync = uio_event_fasync, -}; diff -puN drivers/uio/uio_dummy.c~revert-gregkh-driver-uio /dev/null --- a/drivers/uio/uio_dummy.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * UIO dummy driver - * - * GPLv2 only. - */ - -#define DEBUG 1 - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/uio_driver.h> - -#include <asm/io.h> - -#define MEMSIZE 8192 - -static irqreturn_t uio_dummy_handler(int irq, void *dev_id); - -static struct file_operations uio_dummy_fops = { - .open = uio_open, - .release = uio_release, - .read = uio_read, - .write = uio_write, - .llseek = uio_lseek, - .mmap = uio_mmap, -}; - -static struct uio_device uio_dummy_idev = { - .name = "UIO_dummy", - .version = "0.00", - .fops = &uio_dummy_fops, - .size = MEMSIZE, - .read_offset = 0, - .read_len = MEMSIZE/2, - .write_offset = MEMSIZE/2, - .write_len = MEMSIZE/2, - .irq = -1, /* cyclic timer */ - .freq = HZ, - .irq_type = UIO_EVENT, - .handler = uio_dummy_handler, -}; - -struct uio_dummy_sig { - long pid; - int it_sigev_notify; /* notify word of sigevent struct */ - int it_sigev_signo; /* signo word of sigevent struct */ - sigval_t it_sigev_value; /* value word of sigevent struct */ - struct task_struct *it_process; /* process to send signal to */ - struct sigqueue *sigq; /* signal queue entry. */ -}; - -static struct uio_dummy_sig uio_dummy_signal; -static long uio_dummy_count; - -static ssize_t show_count(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%ld\n", uio_dummy_count); -} - -static ssize_t store_count(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - uio_dummy_count = simple_strtol(buf, NULL, 10); - return count; -} -static DEVICE_ATTR(count, S_IRUGO|S_IWUSR|S_IWGRP, show_count, store_count); - -static ssize_t show_freq(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%ld\n", uio_dummy_idev.freq); -} -static ssize_t store_freq(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - uio_dummy_idev.freq = simple_strtol(buf, NULL, 10); - return count; -} -static DEVICE_ATTR(freq, S_IRUGO|S_IWUSR|S_IWGRP, show_freq, store_freq); - -static ssize_t show_sig_pid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%ld\n", uio_dummy_signal.pid); -} - -static ssize_t store_sig_pid(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - uio_dummy_signal.pid = simple_strtol(buf, NULL, 10); - if (uio_dummy_signal.pid == 0) { - if (uio_dummy_signal.it_process) { - put_task_struct(uio_dummy_signal.it_process); - uio_dummy_signal.it_process = NULL; - } - - uio_dummy_signal.pid = 0; - return count; - } - - if (uio_dummy_signal.pid == 1) - goto out; - - uio_dummy_signal.it_process = find_task_by_pid(uio_dummy_signal.pid); - if (uio_dummy_signal.it_process) { - get_task_struct(uio_dummy_signal.it_process); - uio_dummy_signal.it_sigev_notify = SIGEV_SIGNAL; - uio_dummy_signal.it_sigev_signo = SIGALRM; - uio_dummy_signal.it_sigev_value.sival_int = 0; - - return count; - } -out: - uio_dummy_signal.pid = 0; - return -EINVAL; -} - -static DEVICE_ATTR(sig_pid, S_IRUGO|S_IWUSR|S_IWGRP, show_sig_pid, store_sig_pid); - -static int uio_dummy_irqsig(struct uio_dummy_sig *io_sig, int si_private) -{ - int ret; - struct task_struct *leader; - - if (!io_sig->it_process || !io_sig->sigq) - return 0; - - memset(&io_sig->sigq->info, 0, sizeof(siginfo_t)); - io_sig->sigq->info.si_sys_private = si_private; - - /* - * Send signal to a process waiting for an interrupt - */ - io_sig->sigq->info.si_signo = io_sig->it_sigev_signo; - io_sig->sigq->info.si_errno = 0; - io_sig->sigq->info.si_code = SI_TIMER; - io_sig->sigq->info.si_value = io_sig->it_sigev_value; - - ret = send_sigqueue(io_sig->it_sigev_signo, io_sig->sigq, - io_sig->it_process); - - if (likely(ret >= 0)) - return ret; - - io_sig->it_sigev_notify = SIGEV_SIGNAL; - leader = io_sig->it_process->group_leader; - put_task_struct(io_sig->it_process); - io_sig->it_process = leader; - - return send_group_sigqueue(io_sig->it_sigev_signo, io_sig->sigq, - io_sig->it_process); -} - -static irqreturn_t uio_dummy_handler(int irq, void *dev_id) -{ - struct uio_device *idev = dev_id; - uio_dummy_count++; - - *((long *) idev->physaddr) = uio_dummy_count; - uio_dummy_irqsig(&uio_dummy_signal, 0); - - return IRQ_HANDLED; -} - -static int __devinit uio_dummy_probe(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - - pr_debug("%s\n", __FUNCTION__); - - uio_dummy_idev.physaddr = (unsigned long)kmalloc(MEMSIZE, GFP_KERNEL); - if (!uio_dummy_idev.physaddr) - return -ENOMEM; - - pdev->dev.driver_data = (void *)uio_register_device(NULL, &uio_dummy_idev); - - uio_dummy_signal.sigq = sigqueue_alloc(); - - return (pdev->dev.driver_data) ? 0 : -ENODEV; -} - -static int __devexit uio_dummy_remove(struct device *dev) -{ - pr_debug("%s\n", __FUNCTION__); - sigqueue_free(uio_dummy_signal.sigq); - uio_dummy_signal.sigq = NULL; - - return 0; -} - -static void uio_dummy_shutdown(struct device *dev) -{ - pr_debug("%s\n", __FUNCTION__); -} - -struct platform_device *uio_dummy_device; - -static struct device_driver uio_dummy_driver = { - .name = "uio_dummy", - .bus = &platform_bus_type, - .probe = uio_dummy_probe, - .remove = __devexit_p(uio_dummy_remove), - .shutdown = uio_dummy_shutdown, -}; - -/* - * Main initialization/remove routines - */ - -static int __init uio_dummy_init(void) -{ - int ret; - - pr_debug("%s\n", __FUNCTION__); - - uio_dummy_device = platform_device_register_simple("uio_dummy", -1, - NULL, 0); - if (IS_ERR(uio_dummy_device)) { - ret = PTR_ERR(uio_dummy_device); - goto out; - } - - ret = device_create_file(&uio_dummy_device->dev, &dev_attr_count); - if (ret) - goto error_register; - ret = device_create_file(&uio_dummy_device->dev, &dev_attr_freq); - if (ret) - goto error_file_count; - ret = device_create_file(&uio_dummy_device->dev, &dev_attr_sig_pid); - if (ret) - goto error_file_freq; - - ret = driver_register(&uio_dummy_driver); - if (ret) - goto error_file_sig; - - goto out; - -error_file_sig: - device_remove_file(&uio_dummy_device->dev, &dev_attr_sig_pid); -error_file_freq: - device_remove_file(&uio_dummy_device->dev, &dev_attr_freq); -error_file_count: - device_remove_file(&uio_dummy_device->dev, &dev_attr_count); -error_register: - platform_device_unregister(uio_dummy_device); -out: - return ret; -} - -void __exit uio_dummy_exit(void) -{ - pr_debug("%s\n", __FUNCTION__); - - uio_unregister_device((int) uio_dummy_device->dev.driver_data); - kfree((void *) uio_dummy_idev.physaddr); - - platform_device_unregister(uio_dummy_device); - driver_unregister(&uio_dummy_driver); -} - -module_init(uio_dummy_init); -module_exit(uio_dummy_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Benedikt Spranger"); -MODULE_DESCRIPTION("UIO dummy driver"); diff -puN include/linux/uio_driver.h~revert-gregkh-driver-uio /dev/null --- a/include/linux/uio_driver.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * include/linux/uio_driver.h - * - * Copyright(C) 2005, Benedikt Spranger <b.spranger@xxxxxxxxxxxxx> - * Copyright(C) 2005, Thomas Gleixner <tglx@xxxxxxxxxxxxx> - * - * Userspace IO driver. - * - * Licensed under the GPLv2 only. - */ - -#ifndef _UIO_DRIVER_H_ -#define _UIO_DRIVER_H_ -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/timer.h> -#include <linux/wait.h> - -enum uio_irq_type { - UIO_EVENT, - UIO_THREADED, - UIO_NODELAY, -}; - -/* - * uio_device - UIO device capabilities - * - * @name: device name - * @version: device driver version - * @physaddr: physical address - * @virtaddr: iomaped address (optional) - * @size: size of IO - * read_offset: offset to inputs - * read_len: input length - * write_offset: offset to outputs - * write_len: output length - * irq: interrupt, -1 for cyclic mode, -2 for oneshot mode - * freq: frequency for cyclic mode - * next_event: next event for oneshot mode - * irq_type: interrupt type - */ - -struct uio_device { - /* internals */ - struct device dev; - struct cdev cdev; - struct cdev event_cdev; - long event_listener; - atomic_t event; - struct timer_list poll_timer; - struct fasync_struct *async_queue; - wait_queue_head_t wait; - atomic_t event_count; - atomic_t waiters; - atomic_t running; - atomic_t terminate; - - /* attributes */ - char *name; - char *version; - unsigned long physaddr; - void *virtaddr; - unsigned long size; - long read_offset; - long read_len; - long write_offset; - long write_len; - long irq; - long freq; - ktime_t next_event; - enum uio_irq_type irq_type; - - /* callbacks */ - irqreturn_t (*handler)(int irq, void *dev_id); - ssize_t (*event_write)(struct file *filep, const char __user * buf, - size_t count, loff_t *ppos); - - /* fops */ - struct file_operations *fops; - - /* driver private */ - void *priv; -}; - -int uio_register_device(struct device *parent, struct uio_device *idev); -int uio_unregister_device(int dev_nr); - -#define to_uio_device(n) container_of(n, struct uio_device, dev) - -/* char device funktions */ - -loff_t uio_lseek(struct file *filep, loff_t offset, int orig); -ssize_t uio_read(struct file *filep, char __user *buf, size_t count, loff_t *ppos); -ssize_t uio_write(struct file *filep, const char __user * buf, size_t count, - loff_t *ppos); -int uio_open(struct inode *inode, struct file *filep); -int uio_mmap(struct file *filep, struct vm_area_struct *vma); -int uio_release(struct inode *inode, struct file *filep); - -/* event */ -irqreturn_t uio_interrupt(int irq, void *dev_id); -extern struct file_operations uio_event_fops; - -#endif /* _LINUX_UIO_DRIVER_H_ */ _ Patches currently in -mm which might be from akpm@xxxxxxxx are origin.patch setup_irq-better-mismatch-debugging.patch revert-pci-quirk-for-ibm-dock-ii-cardbus-controllers.patch git-acpi.patch video-sysfs-support-take-2-add-dev-argument-for-backlight_device_register.patch acpi-asus-s3-resume-fix.patch sony_apci-resume.patch video-sysfs-support-take-2-add-dev-argument-for-backlight_device_register-sony_acpi-fix.patch git-cpufreq-prep.patch git-cpufreq.patch revert-gregkh-driver-acpi-change-acpi-to-use-dev_archdata-instead-of-firmware_data.patch revert-gregkh-driver-driver-core-add-dev_archdata-to-struct-device.patch fix-gregkh-driver-sound-device.patch git-dvb.patch git-ia64.patch git-input.patch git-input-fixup.patch git-libata-all.patch sata_vsc-build-fix.patch via-pata-controller-xfer-fixes-fix.patch git-mtd.patch git-netdev-all.patch libphy-dont-do-that.patch update-smc91x-driver-with-arm-versatile-board-info.patch e1000-linkage-fix.patch drivers-net-ns83820c-add-paramter-to-disable-auto.patch git-net.patch net-uninline-skb_put.patch ioat-warning-fix.patch git-scsi-rc-fixes.patch revert-scsi-ips-soft-lockup-during-reset-initialization.patch scsi-ips-soft-lockup-during-reset-initialization-2.patch drivers-scsi-mca_53c9xc-save_flags-cli-removal.patch nokia-e70-is-an-unusual-device.patch git-watchdog.patch revert-x86_64-mm-try-multiple-timer-pins.patch fix-x86_64-mm-i386-reloc-cleanup-align.patch touchkit-ps-2-touchscreen-driver.patch get-rid-of-zone_table.patch new-scheme-to-preempt-swap-token-tidy.patch balance_pdgat-cleanup.patch radix-tree-rcu-lockless-readside.patch acx1xx-wireless-driver.patch swsusp-add-resume_offset-command-line-parameter-rev-2.patch add-include-linux-freezerh-and-move-definitions-from-ueagle-fix.patch cciss-set-sector_size-to-2048-for-performance-tidy.patch deprecate-smbfs-in-favour-of-cifs.patch edac-new-opteron-athlon64-memory-controller-driver.patch kbuild-dont-put-temp-files-in-the-source-tree.patch lockdep-annotate-nfs-nfsd-in-kernel-sockets-tidy.patch drivers-add-lcd-support-3-Kconfig-fix.patch probe_kernel_address-needs-to-do-set_fs.patch slab-use-probe_kernel_address.patch lockdep-spin_lock_irqsave_nested-fix.patch lockdep-spin_lock_irqsave_nested-fix-2.patch aio-use-prepare_to_wait.patch exar-quad-port-serial-fix.patch vfs_getattr-remove-dead-code.patch ext3-uninline-large-functions.patch ext4-uninline-large-functions.patch uninline-module_put.patch sleep-profiling-fixes.patch sleep-profiling-fix.patch debug-workqueue-locking-sanity-fix.patch pcengines-wrap-led-support-fix.patch driver-base-memoryc-remove-warnings-of.patch remove-kernel-syscalls-x86_64-fix.patch protect-ext2-ioctl-modifying-append_only-immutable-etc-with-i_mutex.patch remove-hash_highmem.patch ext2-reservations-fix.patch ext2-reservations-sequential-read-regression-fix.patch ext2-reservations-filesystem-bogus-ENOSPC-with-reservation-fix.patch ext2-reservations-ext3_clear_inode-avoid-kfree-null.patch ext2-reservations-multile-block-allocate-little-endian-fixes.patch ext2-reservations-mark-group-descriptors-dirty-during-allocation.patch ext2-reservations-nuke-noisy-printk.patch pktcdvd-bio-write-congestion-using-blk_congestion_wait-fix.patch bug-test-1.patch fsstack-introduce-fsstack_copy_attrinode_-tidy.patch log2-implement-a-general-integer-log2-facility-in-the-kernel-fix.patch log2-implement-a-general-integer-log2-facility-in-the-kernel-vs-git-cryptodev.patch log2-implement-a-general-integer-log2-facility-in-the-kernel-ppc-fix.patch add-process_session-helper-routine-deprecate-old-field-tidy.patch add-process_session-helper-routine-deprecate-old-field-fix-warnings.patch add-process_session-helper-routine-deprecate-old-field-fix-warnings-2.patch fs-cache-provide-a-filesystem-specific-syncable-page-bit-ext4.patch fs-cache-make-kafs-use-fs-cache-fix.patch fs-cache-make-kafs-use-fs-cache-vs-streamline-generic_file_-interfaces-and-filemap.patch nfs-use-local-caching-12-fix.patch fs-cache-cachefiles-a-cache-that-backs-onto-a-mounted-filesystem-log2-fix.patch mxser-session-warning-fix.patch tty-switch-to-ktermios-and-new-framework-warning-fix.patch tty-switch-to-ktermios-bluetooth-fix.patch tty_ioctl-use-termios-for-the-old-structure-and-termios2-fix.patch char-istallion-correct-fail-paths-fix.patch drivers-isdn-handcrafted-min-max-macro-removal-fix.patch fault-injection-capabilities-infrastructure-tidy.patch fault-injection-capabilities-infrastructure-tweaks.patch fault-injection-Kconfig-cleanup.patch kernel-schedc-whitespace-cleanups-more.patch swap_prefetch-vs-zoned-counters.patch add-include-linux-freezerh-and-move-definitions-from-prefetch.patch readahead-sysctl-parameters.patch make-copy_from_user_inatomic-not-zero-the-tail-on-i386-vs-reiser4.patch resier4-add-include-linux-freezerh-and-move-definitions-from.patch make-kmem_cache_destroy-return-void-reiser4.patch reiser4-hardirq-include-fix.patch reiser4-run-truncate_inode_pages-in-reiser4_delete_inode.patch reiser4-get_sb_dev-fix.patch reiser4-vs-zoned-allocator.patch hpt3xx-rework-rate-filtering-tidy.patch various-fbdev-files-mark-structs-fix.patch md-allow-reads-that-have-bypassed-the-cache-to-be-retried-on-failure-fix.patch statistics-infrastructure-fix-buffer-overflow-in-histogram-with-linear-tidy.patch gtod-persistent-clock-support-i386.patch updated-hrtimers-state-tracking.patch updated-i386-convert-to-clock-event-devices.patch updated-i386-convert-to-clock-event-devices-fix.patch updated-gtod-mark-tsc-unusable-for-highres-timers.patch round_jiffies-infrastructure-fix.patch clocksource-small-cleanup-2-fix.patch kevent_user_wait-retval-fix.patch kevent-v23-socket-notifications-fix-again.patch kevent-timer-notifications-fix.patch nr_blockdev_pages-in_interrupt-warning.patch device-suspend-debug.patch mutex-subsystem-synchro-test-module-fix.patch slab-leaks3-default-y.patch x86-kmap_atomic-debugging.patch restore-rogue-readahead-printk.patch put_bh-debug.patch e1000-printk-warning-fixes.patch acpi_format_exception-debug.patch jmicron-warning-fix.patch squash-ipc-warnings.patch squash-udf-warnings.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html