summaryrefslogtreecommitdiff
path: root/drivers/char/n_hdlc.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-04-30 00:53:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 08:29:40 -0700
commit04f378b198da233ca0aca341b113dc6579d46123 (patch)
tree696e7bd401125cee71ecaa2047c4273f38732554 /drivers/char/n_hdlc.c
parente52384426064bca0669a954736206adca7595d48 (diff)
downloadkernel-common-04f378b198da233ca0aca341b113dc6579d46123.tar.gz
kernel-common-04f378b198da233ca0aca341b113dc6579d46123.tar.bz2
kernel-common-04f378b198da233ca0aca341b113dc6579d46123.zip
tty: BKL pushdown
- Push the BKL down into the line disciplines - Switch the tty layer to unlocked_ioctl - Introduce a new ctrl_lock spin lock for the control bits - Eliminate much of the lock_kernel use in n_tty - Prepare to (but don't yet) call the drivers with the lock dropped on the paths that historically held the lock BKL now primarily protects open/close/ldisc change in the tty layer [jirislaby@gmail.com: a couple of fixes] Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/n_hdlc.c')
-rw-r--r--drivers/char/n_hdlc.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 06803ed5568c..a07c0af4819e 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -578,26 +578,36 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
return -EFAULT;
}
+ lock_kernel();
+
for (;;) {
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+ unlock_kernel();
return -EIO;
+ }
n_hdlc = tty2n_hdlc (tty);
if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
- tty != n_hdlc->tty)
+ tty != n_hdlc->tty) {
+ unlock_kernel();
return 0;
+ }
rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
if (rbuf)
break;
/* no data */
- if (file->f_flags & O_NONBLOCK)
+ if (file->f_flags & O_NONBLOCK) {
+ unlock_kernel();
return -EAGAIN;
+ }
interruptible_sleep_on (&tty->read_wait);
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ unlock_kernel();
return -EINTR;
+ }
}
if (rbuf->count > nr)
@@ -618,7 +628,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
kfree(rbuf);
else
n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
-
+ unlock_kernel();
return ret;
} /* end of n_hdlc_tty_read() */
@@ -661,6 +671,8 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
count = maxframe;
}
+ lock_kernel();
+
add_wait_queue(&tty->write_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
@@ -695,7 +707,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
n_hdlc_send_frames(n_hdlc,tty);
}
-
+ unlock_kernel();
return error;
} /* end of n_hdlc_tty_write() */