Commit aba24888 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

tty: r3964: Replace/remove bogus tty lock use

The tty lock is strictly for serializing tty lifetime events
(open/close/hangup), and not for line discipline serialization.

The tty core already provides serialization of concurrent writes
to the same tty, and line discipline lifetime management (by ldisc
references), so pinning the tty via tty_lock() is unnecessary and
counter-productive; remove tty lock use.

However, the line discipline is responsible for serializing reads
(if required by the line discipline); add read_lock mutex to
serialize calls of r3964_read().
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9b9ab1b3
...@@ -978,6 +978,7 @@ static int r3964_open(struct tty_struct *tty) ...@@ -978,6 +978,7 @@ static int r3964_open(struct tty_struct *tty)
} }
spin_lock_init(&pInfo->lock); spin_lock_init(&pInfo->lock);
mutex_init(&pInfo->read_lock);
pInfo->tty = tty; pInfo->tty = tty;
pInfo->priority = R3964_MASTER; pInfo->priority = R3964_MASTER;
pInfo->rx_first = pInfo->rx_last = NULL; pInfo->rx_first = pInfo->rx_last = NULL;
...@@ -1063,7 +1064,16 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, ...@@ -1063,7 +1064,16 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()"); 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)); pClient = findClient(pInfo, task_pid(current));
if (pClient) { if (pClient) {
...@@ -1075,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, ...@@ -1075,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock; goto unlock;
} }
/* block until there is a message: */ /* 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))); (pMsg = remove_msg(pInfo, pClient)));
} }
...@@ -1105,7 +1115,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, ...@@ -1105,7 +1115,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
} }
ret = -EPERM; ret = -EPERM;
unlock: unlock:
tty_unlock(tty); mutex_unlock(&pInfo->read_lock);
return ret; return ret;
} }
...@@ -1154,8 +1164,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, ...@@ -1154,8 +1164,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0; pHeader->locks = 0;
pHeader->owner = NULL; pHeader->owner = NULL;
tty_lock(tty);
pClient = findClient(pInfo, task_pid(current)); pClient = findClient(pInfo, task_pid(current));
if (pClient) { if (pClient) {
pHeader->owner = pClient; pHeader->owner = pClient;
...@@ -1173,8 +1181,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, ...@@ -1173,8 +1181,6 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader); add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo); trigger_transmit(pInfo);
tty_unlock(tty);
return 0; return 0;
} }
......
...@@ -161,8 +161,9 @@ struct r3964_info { ...@@ -161,8 +161,9 @@ struct r3964_info {
unsigned char last_rx; unsigned char last_rx;
unsigned char bcc; unsigned char bcc;
unsigned int blocks_in_rx_queue; unsigned int blocks_in_rx_queue;
struct mutex read_lock; /* serialize r3964_read */
struct r3964_client_info *firstClient; struct r3964_client_info *firstClient;
unsigned int state; unsigned int state;
unsigned int flags; unsigned int flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment