Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 186448
b: refs/heads/master
c: 7bc80cd
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Mar 7, 2010
1 parent a690b1c commit 8bd027b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 66b89159c25a47d2177743526c61b5ada7acc39e
refs/heads/master: 7bc80cd935a4d5fd8574f6994bd95d0aad273d56
66 changes: 24 additions & 42 deletions trunk/drivers/usb/core/devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,21 @@ 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;
/*
* 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)
};

/* this struct stores the poll state for <mountpoint>/devices pollers */
struct usb_device_status {
Expand Down Expand Up @@ -157,10 +169,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)
Expand Down Expand Up @@ -632,42 +642,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;
}

Expand Down Expand Up @@ -699,6 +683,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,
};

0 comments on commit 8bd027b

Please sign in to comment.