Input: serio_raw - perform proper locking when adding clients to list
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 11 Oct 2011 01:30:26 +0000 (18:30 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 11 Oct 2011 01:34:55 +0000 (18:34 -0700)
Make sure we hold serio lock when adding clients to client list so that
we do not race with serio_raw_release() removing clients from the same
list.

Reviewed-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/serio/serio_raw.c

index 6b57ee3..77ce3a6 100644 (file)
@@ -106,7 +106,10 @@ static int serio_raw_open(struct inode *inode, struct file *file)
        file->private_data = client;
 
        kref_get(&serio_raw->kref);
+
+       serio_pause_rx(serio_raw->serio);
        list_add_tail(&client->node, &serio_raw->client_list);
+       serio_continue_rx(serio_raw->serio);
 
 out:
        mutex_unlock(&serio_raw_mutex);
@@ -138,10 +141,9 @@ static int serio_raw_release(struct inode *inode, struct file *file)
 
 static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
 {
-       unsigned long flags;
        int empty;
 
-       spin_lock_irqsave(&serio_raw->serio->lock, flags);
+       serio_pause_rx(serio_raw->serio);
 
        empty = serio_raw->head == serio_raw->tail;
        if (!empty) {
@@ -149,7 +151,7 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
                serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
        }
 
-       spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+       serio_continue_rx(serio_raw->serio);
 
        return !empty;
 }