aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-10-10 21:30:26 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-10-10 21:34:55 -0400
commit843e784afe164ac8c75a97259d54cf489be74bb9 (patch)
treec8f4e97ef6889c780f698729ddfc5eae5d33ef85
parent7c5bbb2eb7ad047b53c205b1f500bae7b0a88c06 (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.c8
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
111out: 114out:
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
139static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) 142static 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}