diff options
Diffstat (limited to 'drivers')
-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 | }; |