diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-10-10 21:30:26 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-10-10 21:34:55 -0400 |
commit | 843e784afe164ac8c75a97259d54cf489be74bb9 (patch) | |
tree | c8f4e97ef6889c780f698729ddfc5eae5d33ef85 | |
parent | 7c5bbb2eb7ad047b53c205b1f500bae7b0a88c06 (diff) |
Input: serio_raw - perform proper locking when adding clients to list
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>
-rw-r--r-- | drivers/input/serio/serio_raw.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 6b57ee37efeb..77ce3a6a1599 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -106,7 +106,10 @@ static int serio_raw_open(struct inode *inode, struct file *file) | |||
106 | file->private_data = client; | 106 | file->private_data = client; |
107 | 107 | ||
108 | kref_get(&serio_raw->kref); | 108 | kref_get(&serio_raw->kref); |
109 | |||
110 | serio_pause_rx(serio_raw->serio); | ||
109 | list_add_tail(&client->node, &serio_raw->client_list); | 111 | list_add_tail(&client->node, &serio_raw->client_list); |
112 | serio_continue_rx(serio_raw->serio); | ||
110 | 113 | ||
111 | out: | 114 | out: |
112 | mutex_unlock(&serio_raw_mutex); | 115 | mutex_unlock(&serio_raw_mutex); |
@@ -138,10 +141,9 @@ static int serio_raw_release(struct inode *inode, struct file *file) | |||
138 | 141 | ||
139 | static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) | 142 | static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) |
140 | { | 143 | { |
141 | unsigned long flags; | ||
142 | int empty; | 144 | int empty; |
143 | 145 | ||
144 | spin_lock_irqsave(&serio_raw->serio->lock, flags); | 146 | serio_pause_rx(serio_raw->serio); |
145 | 147 | ||
146 | empty = serio_raw->head == serio_raw->tail; | 148 | empty = serio_raw->head == serio_raw->tail; |
147 | if (!empty) { | 149 | if (!empty) { |
@@ -149,7 +151,7 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) | |||
149 | serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; | 151 | serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; |
150 | } | 152 | } |
151 | 153 | ||
152 | spin_unlock_irqrestore(&serio_raw->serio->lock, flags); | 154 | serio_continue_rx(serio_raw->serio); |
153 | 155 | ||
154 | return !empty; | 156 | return !empty; |
155 | } | 157 | } |