diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 3e243621c0e..59df2e7317a 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, struct serio_raw *serio_raw = client->serio_raw; char uninitialized_var(c); ssize_t read = 0; - int error = 0; + int error; - do { + for (;;) { if (serio_raw->dead) return -ENODEV; @@ -179,24 +179,24 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, break; while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { - if (put_user(c, buffer++)) { - error = -EFAULT; - goto out; - } + if (put_user(c, buffer++)) + return -EFAULT; read++; } if (read) break; - if (!(file->f_flags & O_NONBLOCK)) + if (!(file->f_flags & O_NONBLOCK)) { error = wait_event_interruptible(serio_raw->wait, serio_raw->head != serio_raw->tail || serio_raw->dead); - } while (!error); + if (error) + return error; + } + } -out: - return read ?: error; + return read; } 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, { struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; - ssize_t written = 0; - int retval; + int retval = 0; unsigned char c; retval = mutex_lock_interruptible(&serio_raw_mutex); @@ -225,16 +224,20 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, retval = -EFAULT; goto out; } + if (serio_write(serio_raw->serio, c)) { - retval = -EIO; + /* Either signal error or partial write */ + if (retval == 0) + retval = -EIO; goto out; } - written++; + + retval++; } out: mutex_unlock(&serio_raw_mutex); - return written ?: retval; + return retval; } static unsigned int serio_raw_poll(struct file *file, poll_table *wait)