aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/serio/serio_raw.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 948fd5a045f7..3e243621c0e3 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -165,31 +165,38 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
165 struct serio_raw *serio_raw = client->serio_raw; 165 struct serio_raw *serio_raw = client->serio_raw;
166 char uninitialized_var(c); 166 char uninitialized_var(c);
167 ssize_t read = 0; 167 ssize_t read = 0;
168 int retval; 168 int error = 0;
169 169
170 if (serio_raw->dead) 170 do {
171 return -ENODEV; 171 if (serio_raw->dead)
172 return -ENODEV;
172 173
173 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) 174 if (serio_raw->head == serio_raw->tail &&
174 return -EAGAIN; 175 (file->f_flags & O_NONBLOCK))
176 return -EAGAIN;
175 177
176 retval = wait_event_interruptible(serio_raw->wait, 178 if (count == 0)
177 serio_raw->head != serio_raw->tail || serio_raw->dead); 179 break;
178 if (retval)
179 return retval;
180 180
181 if (serio_raw->dead) 181 while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
182 return -ENODEV; 182 if (put_user(c, buffer++)) {
183 error = -EFAULT;
184 goto out;
185 }
186 read++;
187 }
183 188
184 while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { 189 if (read)
185 if (put_user(c, buffer++)) {
186 retval = -EFAULT;
187 break; 190 break;
188 }
189 read++;
190 }
191 191
192 return read ?: retval; 192 if (!(file->f_flags & O_NONBLOCK))
193 error = wait_event_interruptible(serio_raw->wait,
194 serio_raw->head != serio_raw->tail ||
195 serio_raw->dead);
196 } while (!error);
197
198out:
199 return read ?: error;
193} 200}
194 201
195static ssize_t serio_raw_write(struct file *file, const char __user *buffer, 202static ssize_t serio_raw_write(struct file *file, const char __user *buffer,