*/
static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
+/* guarded by usbfs_mutex */
static unsigned int conndiscevcnt;
/* this struct stores the poll state for <mountpoint>/devices pollers */
void usbfs_conn_disc_event(void)
{
+ mutex_lock(&usbfs_mutex);
conndiscevcnt++;
+ mutex_unlock(&usbfs_mutex);
wake_up(&deviceconndiscwq);
}
static unsigned int usb_device_poll(struct file *file,
struct poll_table_struct *wait)
{
- struct usb_device_status *st = file->private_data;
+ struct usb_device_status *st;
unsigned int mask = 0;
- lock_kernel();
+ mutex_lock(&usbfs_mutex);
+ st = file->private_data;
if (!st) {
st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-
- /* we may have dropped BKL -
- * need to check for having lost the race */
- if (file->private_data) {
- kfree(st);
- st = file->private_data;
- goto lost_race;
- }
- /* we haven't lost - check for allocation failure now */
if (!st) {
- unlock_kernel();
+ mutex_unlock(&usbfs_mutex);
return POLLIN;
}
- /*
- * need to prevent the module from being unloaded, since
- * proc_unregister does not call the release method and
- * we would have a memory leak
- */
st->lastev = conndiscevcnt;
file->private_data = st;
mask = POLLIN;
}
-lost_race:
+
if (file->f_mode & FMODE_READ)
poll_wait(file, &deviceconndiscwq, wait);
if (st->lastev != conndiscevcnt)
mask |= POLLIN;
st->lastev = conndiscevcnt;
- unlock_kernel();
+ mutex_unlock(&usbfs_mutex);
return mask;
}