]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/core/devices.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / usb / core / devices.c
index c83c975152a6ae7f2e3fe09d275d4946c6c67ffb..19bc03a9fecf3d8bbaba0bafafaf9f49d472e6b2 100644 (file)
@@ -50,7 +50,7 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/gfp.h>
 #include <linux/poll.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
@@ -117,13 +117,20 @@ static const char *format_endpt =
  * However, these will come from functions that return ptrs to each of them.
  */
 
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-/* guarded by usbfs_mutex */
-static unsigned int conndiscevcnt;
-
-/* this struct stores the poll state for <mountpoint>/devices pollers */
-struct usb_device_status {
-       unsigned int lastev;
+/*
+ * Wait for an connect/disconnect event to happen. We initialize
+ * the event counter with an odd number, and each event will increment
+ * the event counter by two, so it will always _stay_ odd. That means
+ * that it will never be zero, so "event 0" will never match a current
+ * event, and thus 'poll' will always trigger as readable for the first
+ * time it gets called.
+ */
+static struct device_connect_event {
+       atomic_t count;
+       wait_queue_head_t wait;
+} device_event = {
+       .count = ATOMIC_INIT(1),
+       .wait = __WAIT_QUEUE_HEAD_INITIALIZER(device_event.wait)
 };
 
 struct class_info {
@@ -157,10 +164,8 @@ static const struct class_info clas_info[] =
 
 void usbfs_conn_disc_event(void)
 {
-       mutex_lock(&usbfs_mutex);
-       conndiscevcnt++;
-       mutex_unlock(&usbfs_mutex);
-       wake_up(&deviceconndiscwq);
+       atomic_add(2, &device_event.count);
+       wake_up(&device_event.wait);
 }
 
 static const char *class_decode(const int class)
@@ -632,42 +637,16 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
 static unsigned int usb_device_poll(struct file *file,
                                    struct poll_table_struct *wait)
 {
-       struct usb_device_status *st;
-       unsigned int mask = 0;
-
-       mutex_lock(&usbfs_mutex);
-       st = file->private_data;
-       if (!st) {
-               st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-               if (!st) {
-                       mutex_unlock(&usbfs_mutex);
-                       return POLLIN;
-               }
-
-               st->lastev = conndiscevcnt;
-               file->private_data = st;
-               mask = POLLIN;
-       }
+       unsigned int event_count;
 
-       if (file->f_mode & FMODE_READ)
-               poll_wait(file, &deviceconndiscwq, wait);
-       if (st->lastev != conndiscevcnt)
-               mask |= POLLIN;
-       st->lastev = conndiscevcnt;
-       mutex_unlock(&usbfs_mutex);
-       return mask;
-}
+       poll_wait(file, &device_event.wait, wait);
 
-static int usb_device_open(struct inode *inode, struct file *file)
-{
-       file->private_data = NULL;
-       return 0;
-}
+       event_count = atomic_read(&device_event.count);
+       if (file->f_version != event_count) {
+               file->f_version = event_count;
+               return POLLIN | POLLRDNORM;
+       }
 
-static int usb_device_release(struct inode *inode, struct file *file)
-{
-       kfree(file->private_data);
-       file->private_data = NULL;
        return 0;
 }
 
@@ -699,6 +678,4 @@ const struct file_operations usbfs_devices_fops = {
        .llseek =       usb_device_lseek,
        .read =         usb_device_read,
        .poll =         usb_device_poll,
-       .open =         usb_device_open,
-       .release =      usb_device_release,
 };