diff options
| -rw-r--r-- | drivers/usb/core/devices.c | 66 | 
1 files changed, 24 insertions, 42 deletions
| diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index c83c975152a6..6053a8b730cd 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
| @@ -117,9 +117,21 @@ static const char *format_endpt = | |||
| 117 | * However, these will come from functions that return ptrs to each of them. | 117 | * However, these will come from functions that return ptrs to each of them. | 
| 118 | */ | 118 | */ | 
| 119 | 119 | ||
| 120 | static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq); | 120 | /* | 
| 121 | /* guarded by usbfs_mutex */ | 121 | * Wait for an connect/disconnect event to happen. We initialize | 
| 122 | static unsigned int conndiscevcnt; | 122 | * the event counter with an odd number, and each event will increment | 
| 123 | * the event counter by two, so it will always _stay_ odd. That means | ||
| 124 | * that it will never be zero, so "event 0" will never match a current | ||
| 125 | * event, and thus 'poll' will always trigger as readable for the first | ||
| 126 | * time it gets called. | ||
| 127 | */ | ||
| 128 | static struct device_connect_event { | ||
| 129 | atomic_t count; | ||
| 130 | wait_queue_head_t wait; | ||
| 131 | } device_event = { | ||
| 132 | .count = ATOMIC_INIT(1), | ||
| 133 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(device_event.wait) | ||
| 134 | }; | ||
| 123 | 135 | ||
| 124 | /* this struct stores the poll state for <mountpoint>/devices pollers */ | 136 | /* this struct stores the poll state for <mountpoint>/devices pollers */ | 
| 125 | struct usb_device_status { | 137 | struct usb_device_status { | 
| @@ -157,10 +169,8 @@ static const struct class_info clas_info[] = | |||
| 157 | 169 | ||
| 158 | void usbfs_conn_disc_event(void) | 170 | void usbfs_conn_disc_event(void) | 
| 159 | { | 171 | { | 
| 160 | mutex_lock(&usbfs_mutex); | 172 | atomic_add(2, &device_event.count); | 
| 161 | conndiscevcnt++; | 173 | wake_up(&device_event.wait); | 
| 162 | mutex_unlock(&usbfs_mutex); | ||
| 163 | wake_up(&deviceconndiscwq); | ||
| 164 | } | 174 | } | 
| 165 | 175 | ||
| 166 | static const char *class_decode(const int class) | 176 | static const char *class_decode(const int class) | 
| @@ -632,42 +642,16 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, | |||
| 632 | static unsigned int usb_device_poll(struct file *file, | 642 | static unsigned int usb_device_poll(struct file *file, | 
| 633 | struct poll_table_struct *wait) | 643 | struct poll_table_struct *wait) | 
| 634 | { | 644 | { | 
| 635 | struct usb_device_status *st; | 645 | unsigned int event_count; | 
| 636 | unsigned int mask = 0; | ||
| 637 | |||
| 638 | mutex_lock(&usbfs_mutex); | ||
| 639 | st = file->private_data; | ||
| 640 | if (!st) { | ||
| 641 | st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL); | ||
| 642 | if (!st) { | ||
| 643 | mutex_unlock(&usbfs_mutex); | ||
| 644 | return POLLIN; | ||
| 645 | } | ||
| 646 | |||
| 647 | st->lastev = conndiscevcnt; | ||
| 648 | file->private_data = st; | ||
| 649 | mask = POLLIN; | ||
| 650 | } | ||
| 651 | 646 | ||
| 652 | if (file->f_mode & FMODE_READ) | 647 | poll_wait(file, &device_event.wait, wait); | 
| 653 | poll_wait(file, &deviceconndiscwq, wait); | ||
| 654 | if (st->lastev != conndiscevcnt) | ||
| 655 | mask |= POLLIN; | ||
| 656 | st->lastev = conndiscevcnt; | ||
| 657 | mutex_unlock(&usbfs_mutex); | ||
| 658 | return mask; | ||
| 659 | } | ||
| 660 | 648 | ||
| 661 | static int usb_device_open(struct inode *inode, struct file *file) | 649 | event_count = atomic_read(&device_event.count); | 
| 662 | { | 650 | if (file->f_version != event_count) { | 
| 663 | file->private_data = NULL; | 651 | file->f_version = event_count; | 
| 664 | return 0; | 652 | return POLLIN | POLLRDNORM; | 
| 665 | } | 653 | } | 
| 666 | 654 | ||
| 667 | static int usb_device_release(struct inode *inode, struct file *file) | ||
| 668 | { | ||
| 669 | kfree(file->private_data); | ||
| 670 | file->private_data = NULL; | ||
| 671 | return 0; | 655 | return 0; | 
| 672 | } | 656 | } | 
| 673 | 657 | ||
| @@ -699,6 +683,4 @@ const struct file_operations usbfs_devices_fops = { | |||
| 699 | .llseek = usb_device_lseek, | 683 | .llseek = usb_device_lseek, | 
| 700 | .read = usb_device_read, | 684 | .read = usb_device_read, | 
| 701 | .poll = usb_device_poll, | 685 | .poll = usb_device_poll, | 
| 702 | .open = usb_device_open, | ||
| 703 | .release = usb_device_release, | ||
| 704 | }; | 686 | }; | 
