diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/serio_raw.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 3e243621c0e3..59df2e7317a3 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -165,9 +165,9 @@ 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 error = 0; | 168 | int error; |
169 | 169 | ||
170 | do { | 170 | for (;;) { |
171 | if (serio_raw->dead) | 171 | if (serio_raw->dead) |
172 | return -ENODEV; | 172 | return -ENODEV; |
173 | 173 | ||
@@ -179,24 +179,24 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, | |||
179 | break; | 179 | break; |
180 | 180 | ||
181 | while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { | 181 | while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { |
182 | if (put_user(c, buffer++)) { | 182 | if (put_user(c, buffer++)) |
183 | error = -EFAULT; | 183 | return -EFAULT; |
184 | goto out; | ||
185 | } | ||
186 | read++; | 184 | read++; |
187 | } | 185 | } |
188 | 186 | ||
189 | if (read) | 187 | if (read) |
190 | break; | 188 | break; |
191 | 189 | ||
192 | if (!(file->f_flags & O_NONBLOCK)) | 190 | if (!(file->f_flags & O_NONBLOCK)) { |
193 | error = wait_event_interruptible(serio_raw->wait, | 191 | error = wait_event_interruptible(serio_raw->wait, |
194 | serio_raw->head != serio_raw->tail || | 192 | serio_raw->head != serio_raw->tail || |
195 | serio_raw->dead); | 193 | serio_raw->dead); |
196 | } while (!error); | 194 | if (error) |
195 | return error; | ||
196 | } | ||
197 | } | ||
197 | 198 | ||
198 | out: | 199 | return read; |
199 | return read ?: error; | ||
200 | } | 200 | } |
201 | 201 | ||
202 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | 202 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, |
@@ -204,8 +204,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | |||
204 | { | 204 | { |
205 | struct serio_raw_client *client = file->private_data; | 205 | struct serio_raw_client *client = file->private_data; |
206 | struct serio_raw *serio_raw = client->serio_raw; | 206 | struct serio_raw *serio_raw = client->serio_raw; |
207 | ssize_t written = 0; | 207 | int retval = 0; |
208 | int retval; | ||
209 | unsigned char c; | 208 | unsigned char c; |
210 | 209 | ||
211 | retval = mutex_lock_interruptible(&serio_raw_mutex); | 210 | retval = mutex_lock_interruptible(&serio_raw_mutex); |
@@ -225,16 +224,20 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | |||
225 | retval = -EFAULT; | 224 | retval = -EFAULT; |
226 | goto out; | 225 | goto out; |
227 | } | 226 | } |
227 | |||
228 | if (serio_write(serio_raw->serio, c)) { | 228 | if (serio_write(serio_raw->serio, c)) { |
229 | retval = -EIO; | 229 | /* Either signal error or partial write */ |
230 | if (retval == 0) | ||
231 | retval = -EIO; | ||
230 | goto out; | 232 | goto out; |
231 | } | 233 | } |
232 | written++; | 234 | |
235 | retval++; | ||
233 | } | 236 | } |
234 | 237 | ||
235 | out: | 238 | out: |
236 | mutex_unlock(&serio_raw_mutex); | 239 | mutex_unlock(&serio_raw_mutex); |
237 | return written ?: retval; | 240 | return retval; |
238 | } | 241 | } |
239 | 242 | ||
240 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) | 243 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) |