diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 6fdef921cdb7..345111467b85 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -978,6 +978,7 @@ static int r3964_open(struct tty_struct *tty) } spin_lock_init(&pInfo->lock); + mutex_init(&pInfo->read_lock); pInfo->tty = tty; pInfo->priority = R3964_MASTER; pInfo->rx_first = pInfo->rx_last = NULL; @@ -1063,7 +1064,16 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - tty_lock(tty); + /* + * Internal serialization of reads. + */ + if (file->f_flags & O_NONBLOCK) { + if (!mutex_trylock(&pInfo->read_lock)) + return -EAGAIN; + } else { + if (mutex_lock_interruptible(&pInfo->read_lock)) + return -ERESTARTSYS; + } pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1075,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; } /* block until there is a message: */ - wait_event_interruptible_tty(tty, tty->read_wait, + wait_event_interruptible(tty->read_wait, (pMsg = remove_msg(pInfo, pClient))); } @@ -1105,7 +1115,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - tty_unlock(tty); + mutex_unlock(&pInfo->read_lock); return ret; } @@ -1154,8 +1164,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - tty_lock(tty); - pClient = findClient(pInfo, task_pid(current)); if (pClient) { pHeader->owner = pClient; @@ -1173,8 +1181,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - tty_unlock(tty); - return 0; } diff --git a/include/linux/n_r3964.h b/include/linux/n_r3964.h index e9adb4226224..90a803aa42e8 100644 --- a/include/linux/n_r3964.h +++ b/include/linux/n_r3964.h @@ -161,8 +161,9 @@ struct r3964_info { unsigned char last_rx; unsigned char bcc; unsigned int blocks_in_rx_queue; - - + + struct mutex read_lock; /* serialize r3964_read */ + struct r3964_client_info *firstClient; unsigned int state; unsigned int flags;