aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hidraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r--drivers/hid/hidraw.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 612a655bc9f0..194a5660a389 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -253,6 +253,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
253 unsigned int minor = iminor(inode); 253 unsigned int minor = iminor(inode);
254 struct hidraw *dev; 254 struct hidraw *dev;
255 struct hidraw_list *list; 255 struct hidraw_list *list;
256 unsigned long flags;
256 int err = 0; 257 int err = 0;
257 258
258 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 259 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
@@ -266,11 +267,6 @@ static int hidraw_open(struct inode *inode, struct file *file)
266 goto out_unlock; 267 goto out_unlock;
267 } 268 }
268 269
269 list->hidraw = hidraw_table[minor];
270 mutex_init(&list->read_mutex);
271 list_add_tail(&list->node, &hidraw_table[minor]->list);
272 file->private_data = list;
273
274 dev = hidraw_table[minor]; 270 dev = hidraw_table[minor];
275 if (!dev->open++) { 271 if (!dev->open++) {
276 err = hid_hw_power(dev->hid, PM_HINT_FULLON); 272 err = hid_hw_power(dev->hid, PM_HINT_FULLON);
@@ -283,9 +279,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
283 if (err < 0) { 279 if (err < 0) {
284 hid_hw_power(dev->hid, PM_HINT_NORMAL); 280 hid_hw_power(dev->hid, PM_HINT_NORMAL);
285 dev->open--; 281 dev->open--;
282 goto out_unlock;
286 } 283 }
287 } 284 }
288 285
286 list->hidraw = hidraw_table[minor];
287 mutex_init(&list->read_mutex);
288 spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
289 list_add_tail(&list->node, &hidraw_table[minor]->list);
290 spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
291 file->private_data = list;
289out_unlock: 292out_unlock:
290 mutex_unlock(&minors_lock); 293 mutex_unlock(&minors_lock);
291out: 294out:
@@ -324,10 +327,13 @@ static int hidraw_release(struct inode * inode, struct file * file)
324{ 327{
325 unsigned int minor = iminor(inode); 328 unsigned int minor = iminor(inode);
326 struct hidraw_list *list = file->private_data; 329 struct hidraw_list *list = file->private_data;
330 unsigned long flags;
327 331
328 mutex_lock(&minors_lock); 332 mutex_lock(&minors_lock);
329 333
334 spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
330 list_del(&list->node); 335 list_del(&list->node);
336 spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
331 kfree(list); 337 kfree(list);
332 338
333 drop_ref(hidraw_table[minor], 0); 339 drop_ref(hidraw_table[minor], 0);
@@ -456,7 +462,9 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
456 struct hidraw *dev = hid->hidraw; 462 struct hidraw *dev = hid->hidraw;
457 struct hidraw_list *list; 463 struct hidraw_list *list;
458 int ret = 0; 464 int ret = 0;
465 unsigned long flags;
459 466
467 spin_lock_irqsave(&dev->list_lock, flags);
460 list_for_each_entry(list, &dev->list, node) { 468 list_for_each_entry(list, &dev->list, node) {
461 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); 469 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
462 470
@@ -471,6 +479,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
471 list->head = new_head; 479 list->head = new_head;
472 kill_fasync(&list->fasync, SIGIO, POLL_IN); 480 kill_fasync(&list->fasync, SIGIO, POLL_IN);
473 } 481 }
482 spin_unlock_irqrestore(&dev->list_lock, flags);
474 483
475 wake_up_interruptible(&dev->wait); 484 wake_up_interruptible(&dev->wait);
476 return ret; 485 return ret;
@@ -519,6 +528,7 @@ int hidraw_connect(struct hid_device *hid)
519 528
520 mutex_unlock(&minors_lock); 529 mutex_unlock(&minors_lock);
521 init_waitqueue_head(&dev->wait); 530 init_waitqueue_head(&dev->wait);
531 spin_lock_init(&dev->list_lock);
522 INIT_LIST_HEAD(&dev->list); 532 INIT_LIST_HEAD(&dev->list);
523 533
524 dev->hid = hid; 534 dev->hid = hid;