Commit ec79d605 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Greg Kroah-Hartman

tty: replace BKL with a new tty_lock

As a preparation for replacing the big kernel lock
in the TTY layer, wrap all the callers in new
macros tty_lock, tty_lock_nested and tty_unlock.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3f582b8c
...@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, ...@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info,
if (!retinfo) if (!retinfo)
return -EFAULT; return -EFAULT;
memset(&tmp, 0, sizeof(tmp)); memset(&tmp, 0, sizeof(tmp));
lock_kernel(); tty_lock();
tmp.type = state->type; tmp.type = state->type;
tmp.line = state->line; tmp.line = state->line;
tmp.port = state->port; tmp.port = state->port;
...@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, ...@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info,
tmp.close_delay = state->close_delay; tmp.close_delay = state->close_delay;
tmp.closing_wait = state->closing_wait; tmp.closing_wait = state->closing_wait;
tmp.custom_divisor = state->custom_divisor; tmp.custom_divisor = state->custom_divisor;
unlock_kernel(); tty_unlock();
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, ...@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT; return -EFAULT;
lock_kernel(); tty_lock();
state = info->state; state = info->state;
old_state = *state; old_state = *state;
change_irq = new_serial.irq != state->irq; change_irq = new_serial.irq != state->irq;
change_port = (new_serial.port != state->port); change_port = (new_serial.port != state->port);
if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
unlock_kernel(); tty_unlock();
return -EINVAL; return -EINVAL;
} }
...@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, ...@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info,
} }
if (new_serial.baud_base < 9600) { if (new_serial.baud_base < 9600) {
unlock_kernel(); tty_unlock();
return -EINVAL; return -EINVAL;
} }
...@@ -1163,7 +1163,7 @@ static int set_serial_info(struct async_struct * info, ...@@ -1163,7 +1163,7 @@ static int set_serial_info(struct async_struct * info,
} }
} else } else
retval = startup(info); retval = startup(info);
unlock_kernel(); tty_unlock();
return retval; return retval;
} }
...@@ -1538,7 +1538,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1538,7 +1538,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
orig_jiffies = jiffies; orig_jiffies = jiffies;
lock_kernel(); tty_lock_nested(); /* tty_wait_until_sent is called from lots of places */
/* /*
* Set the check interval to be 1/5 of the estimated time to * Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check * send a single character, and make it at least 1. The check
...@@ -1579,7 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1579,7 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
break; break;
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
unlock_kernel(); tty_unlock();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif #endif
......
...@@ -67,15 +67,15 @@ static void set_led(char state) ...@@ -67,15 +67,15 @@ static void set_led(char state)
static int briq_panel_open(struct inode *ino, struct file *filep) static int briq_panel_open(struct inode *ino, struct file *filep)
{ {
lock_kernel(); tty_lock();
/* enforce single access, vfd_is_open is protected by BKL */ /* enforce single access, vfd_is_open is protected by BKL */
if (vfd_is_open) { if (vfd_is_open) {
unlock_kernel(); tty_unlock();
return -EBUSY; return -EBUSY;
} }
vfd_is_open = 1; vfd_is_open = 1;
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
......
...@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, ...@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
return -EFAULT; return -EFAULT;
} }
lock_kernel(); tty_lock();
for (;;) { for (;;) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
unlock_kernel(); tty_unlock();
return -EIO; return -EIO;
} }
n_hdlc = tty2n_hdlc (tty); n_hdlc = tty2n_hdlc (tty);
if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
tty != n_hdlc->tty) { tty != n_hdlc->tty) {
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
...@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, ...@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
/* no data */ /* no data */
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
unlock_kernel(); tty_unlock();
return -EAGAIN; return -EAGAIN;
} }
interruptible_sleep_on (&tty->read_wait); interruptible_sleep_on (&tty->read_wait);
if (signal_pending(current)) { if (signal_pending(current)) {
unlock_kernel(); tty_unlock();
return -EINTR; return -EINTR;
} }
} }
...@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, ...@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
kfree(rbuf); kfree(rbuf);
else else
n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
unlock_kernel(); tty_unlock();
return ret; return ret;
} /* end of n_hdlc_tty_read() */ } /* end of n_hdlc_tty_read() */
...@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, ...@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
count = maxframe; count = maxframe;
} }
lock_kernel(); tty_lock();
add_wait_queue(&tty->write_wait, &wait); add_wait_queue(&tty->write_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
...@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, ...@@ -731,7 +731,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_buf_put(&n_hdlc->tx_buf_list,tbuf);
n_hdlc_send_frames(n_hdlc,tty); n_hdlc_send_frames(n_hdlc,tty);
} }
unlock_kernel(); tty_unlock();
return error; return error;
} /* end of n_hdlc_tty_write() */ } /* end of n_hdlc_tty_write() */
......
...@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, ...@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()"); TRACE_L("read()");
lock_kernel(); tty_lock();
pClient = findClient(pInfo, task_pid(current)); pClient = findClient(pInfo, task_pid(current));
if (pClient) { if (pClient) {
...@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, ...@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
} }
ret = -EPERM; ret = -EPERM;
unlock: unlock:
unlock_kernel(); tty_unlock();
return ret; return ret;
} }
...@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, ...@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0; pHeader->locks = 0;
pHeader->owner = NULL; pHeader->owner = NULL;
lock_kernel(); tty_lock();
pClient = findClient(pInfo, task_pid(current)); pClient = findClient(pInfo, task_pid(current));
if (pClient) { if (pClient) {
...@@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, ...@@ -1177,7 +1177,7 @@ 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);
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
......
...@@ -692,9 +692,9 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -692,9 +692,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
{ {
int ret; int ret;
lock_kernel(); tty_lock();
ret = __ptmx_open(inode, filp); ret = __ptmx_open(inode, filp);
unlock_kernel(); tty_unlock();
return ret; return ret;
} }
......
...@@ -313,7 +313,7 @@ int paste_selection(struct tty_struct *tty) ...@@ -313,7 +313,7 @@ int paste_selection(struct tty_struct *tty)
struct tty_ldisc *ld; struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
lock_kernel(); tty_lock_nested(); /* always called with BTM from vt_ioctl */
acquire_console_sem(); acquire_console_sem();
poke_blanked_console(); poke_blanked_console();
...@@ -338,6 +338,6 @@ int paste_selection(struct tty_struct *tty) ...@@ -338,6 +338,6 @@ int paste_selection(struct tty_struct *tty)
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
tty_ldisc_deref(ld); tty_ldisc_deref(ld);
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
...@@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
#endif #endif
lock_kernel(); tty_lock();
switch (cmd) { switch (cmd) {
case CYGETMON: case CYGETMON:
...@@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
default: default:
ret_val = -ENOIOCTLCMD; ret_val = -ENOIOCTLCMD;
} }
unlock_kernel(); tty_unlock();
#ifdef SERIAL_DEBUG_OTHER #ifdef SERIAL_DEBUG_OTHER
printk("cy_ioctl done\n"); printk("cy_ioctl done\n");
......
...@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, ...@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
if (!capable(CAP_SYS_RAWIO)) if (!capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
lock_kernel(); tty_lock();
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
...@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, ...@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
break; break;
} }
out: out:
unlock_kernel(); tty_unlock();
func_exit(); func_exit();
return rc; return rc;
} }
...@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag) ...@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag)
int rv; int rv;
func_enter(); func_enter();
lock_kernel(); tty_lock();
if (flag) if (flag)
rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
...@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag) ...@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag)
if (rv != 1) if (rv != 1)
printk(KERN_ERR "sx: couldn't send break (%x).\n", printk(KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
unlock_kernel(); tty_unlock();
func_exit(); func_exit();
return 0; return 0;
} }
...@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, ...@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
/* func_enter2(); */ /* func_enter2(); */
rc = 0; rc = 0;
lock_kernel(); tty_lock();
switch (cmd) { switch (cmd) {
case TIOCGSERIAL: case TIOCGSERIAL:
rc = gs_getserial(&port->gs, argp); rc = gs_getserial(&port->gs, argp);
...@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, ...@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
rc = -ENOIOCTLCMD; rc = -ENOIOCTLCMD;
break; break;
} }
unlock_kernel(); tty_unlock();
/* func_exit(); */ /* func_exit(); */
return rc; return rc;
......
...@@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
#else #else
#define tty_compat_ioctl NULL #define tty_compat_ioctl NULL
#endif #endif
static int __tty_fasync(int fd, struct file *filp, int on);
static int tty_fasync(int fd, struct file *filp, int on); static int tty_fasync(int fd, struct file *filp, int on);
static void release_tty(struct tty_struct *tty, int idx); static void release_tty(struct tty_struct *tty, int idx);
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
...@@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); ...@@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* remains intact. * remains intact.
* *
* Locking: * Locking:
* BKL * BTM
* redirect lock for undoing redirection * redirect lock for undoing redirection
* file list lock for manipulating list of ttys * file list lock for manipulating list of ttys
* tty_ldisc_lock from called functions * tty_ldisc_lock from called functions
...@@ -513,8 +514,11 @@ static void do_tty_hangup(struct work_struct *work) ...@@ -513,8 +514,11 @@ static void do_tty_hangup(struct work_struct *work)
} }
spin_unlock(&redirect_lock); spin_unlock(&redirect_lock);
/* inuse_filps is protected by the single kernel lock */ /* inuse_filps is protected by the single tty lock,
lock_kernel(); this really needs to change if we want to flush the
workqueue with the lock held */
tty_lock_nested(); /* called with BTM held from pty_close and
others */
check_tty_count(tty, "do_tty_hangup"); check_tty_count(tty, "do_tty_hangup");
file_list_lock(); file_list_lock();
...@@ -525,7 +529,7 @@ static void do_tty_hangup(struct work_struct *work) ...@@ -525,7 +529,7 @@ static void do_tty_hangup(struct work_struct *work)
if (filp->f_op->write != tty_write) if (filp->f_op->write != tty_write)
continue; continue;
closecount++; closecount++;
tty_fasync(-1, filp, 0); /* can't block */ __tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops; filp->f_op = &hung_up_tty_fops;
} }
file_list_unlock(); file_list_unlock();
...@@ -594,7 +598,7 @@ static void do_tty_hangup(struct work_struct *work) ...@@ -594,7 +598,7 @@ static void do_tty_hangup(struct work_struct *work)
*/ */
set_bit(TTY_HUPPED, &tty->flags); set_bit(TTY_HUPPED, &tty->flags);
tty_ldisc_enable(tty); tty_ldisc_enable(tty);
unlock_kernel(); tty_unlock();
if (f) if (f)
fput(f); fput(f);
} }
...@@ -696,7 +700,8 @@ static void session_clear_tty(struct pid *session) ...@@ -696,7 +700,8 @@ static void session_clear_tty(struct pid *session)
* exiting; it is 0 if called by the ioctl TIOCNOTTY. * exiting; it is 0 if called by the ioctl TIOCNOTTY.
* *
* Locking: * Locking:
* BKL is taken for hysterical raisins * BTM is taken for hysterical raisins, and held when
* called from no_tty().
* tty_mutex is taken to protect tty * tty_mutex is taken to protect tty
* ->siglock is taken to protect ->signal/->sighand * ->siglock is taken to protect ->signal/->sighand
* tasklist_lock is taken to walk process list for sessions * tasklist_lock is taken to walk process list for sessions
...@@ -714,10 +719,10 @@ void disassociate_ctty(int on_exit) ...@@ -714,10 +719,10 @@ void disassociate_ctty(int on_exit)
tty = get_current_tty(); tty = get_current_tty();
if (tty) { if (tty) {
tty_pgrp = get_pid(tty->pgrp); tty_pgrp = get_pid(tty->pgrp);
lock_kernel(); tty_lock_nested(); /* see above */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty); tty_vhangup(tty);
unlock_kernel(); tty_unlock();
tty_kref_put(tty); tty_kref_put(tty);
} else if (on_exit) { } else if (on_exit) {
struct pid *old_pgrp; struct pid *old_pgrp;
...@@ -774,9 +779,9 @@ void disassociate_ctty(int on_exit) ...@@ -774,9 +779,9 @@ void disassociate_ctty(int on_exit)
void no_tty(void) void no_tty(void)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
lock_kernel(); tty_lock();
disassociate_ctty(0); disassociate_ctty(0);
unlock_kernel(); tty_unlock();
proc_clear_tty(tsk); proc_clear_tty(tsk);
} }
...@@ -1013,19 +1018,19 @@ static inline ssize_t do_tty_write( ...@@ -1013,19 +1018,19 @@ static inline ssize_t do_tty_write(
* We don't put it into the syslog queue right now maybe in the future if * We don't put it into the syslog queue right now maybe in the future if
* really needed. * really needed.
* *
* We must still hold the BKL and test the CLOSING flag for the moment. * We must still hold the BTM and test the CLOSING flag for the moment.
*/ */
void tty_write_message(struct tty_struct *tty, char *msg) void tty_write_message(struct tty_struct *tty, char *msg)
{ {
if (tty) { if (tty) {
mutex_lock(&tty->atomic_write_lock); mutex_lock(&tty->atomic_write_lock);
lock_kernel(); tty_lock();
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
unlock_kernel(); tty_unlock();
tty->ops->write(tty, msg, strlen(msg)); tty->ops->write(tty, msg, strlen(msg));
} else } else
unlock_kernel(); tty_unlock();
tty_write_unlock(tty); tty_write_unlock(tty);
} }
return; return;
...@@ -1208,18 +1213,18 @@ static int tty_driver_install_tty(struct tty_driver *driver, ...@@ -1208,18 +1213,18 @@ static int tty_driver_install_tty(struct tty_driver *driver,
int ret; int ret;
if (driver->ops->install) { if (driver->ops->install) {
lock_kernel(); tty_lock_nested(); /* already called with BTM held */
ret = driver->ops->install(driver, tty); ret = driver->ops->install(driver, tty);
unlock_kernel(); tty_unlock();
return ret; return ret;
} }
if (tty_init_termios(tty) == 0) { if (tty_init_termios(tty) == 0) {
lock_kernel(); tty_lock_nested();
tty_driver_kref_get(driver); tty_driver_kref_get(driver);
tty->count++; tty->count++;
driver->ttys[idx] = tty; driver->ttys[idx] = tty;
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
return -ENOMEM; return -ENOMEM;
...@@ -1312,14 +1317,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, ...@@ -1312,14 +1317,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
struct tty_struct *tty; struct tty_struct *tty;
int retval; int retval;
lock_kernel(); tty_lock_nested(); /* always called with tty lock held already */
/* Check if pty master is being opened multiple times */ /* Check if pty master is being opened multiple times */
if (driver->subtype == PTY_TYPE_MASTER && if (driver->subtype == PTY_TYPE_MASTER &&
(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
unlock_kernel(); tty_unlock();
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
unlock_kernel(); tty_unlock();
/* /*
* First time open is complex, especially for PTY devices. * First time open is complex, especially for PTY devices.
...@@ -1363,9 +1369,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, ...@@ -1363,9 +1369,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_INFO "tty_init_dev: ldisc open failed, " printk(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx); "clearing slot %d\n", idx);
lock_kernel(); tty_lock_nested();
release_tty(tty, idx); release_tty(tty, idx);
unlock_kernel(); tty_unlock();
return ERR_PTR(retval); return ERR_PTR(retval);
} }
...@@ -1512,10 +1518,10 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1512,10 +1518,10 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty_paranoia_check(tty, inode, "tty_release_dev")) if (tty_paranoia_check(tty, inode, "tty_release_dev"))
return 0; return 0;
lock_kernel(); tty_lock();
check_tty_count(tty, "tty_release_dev"); check_tty_count(tty, "tty_release_dev");
tty_fasync(-1, filp, 0); __tty_fasync(-1, filp, 0);
idx = tty->index; idx = tty->index;
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
...@@ -1527,18 +1533,18 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1527,18 +1533,18 @@ int tty_release(struct inode *inode, struct file *filp)
if (idx < 0 || idx >= tty->driver->num) { if (idx < 0 || idx >= tty->driver->num) {
printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
"free (%s)\n", tty->name); "free (%s)\n", tty->name);
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
if (!devpts) { if (!devpts) {
if (tty != tty->driver->ttys[idx]) { if (tty != tty->driver->ttys[idx]) {
unlock_kernel(); tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
"for (%s)\n", idx, tty->name); "for (%s)\n", idx, tty->name);
return 0; return 0;
} }
if (tty->termios != tty->driver->termios[idx]) { if (tty->termios != tty->driver->termios[idx]) {
unlock_kernel(); tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
"for (%s)\n", "for (%s)\n",
idx, tty->name); idx, tty->name);
...@@ -1556,21 +1562,21 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1556,21 +1562,21 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->driver->other && if (tty->driver->other &&
!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
if (o_tty != tty->driver->other->ttys[idx]) { if (o_tty != tty->driver->other->ttys[idx]) {
unlock_kernel(); tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->table[%d] " printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
"not o_tty for (%s)\n", "not o_tty for (%s)\n",
idx, tty->name); idx, tty->name);
return 0 ; return 0 ;
} }
if (o_tty->termios != tty->driver->other->termios[idx]) { if (o_tty->termios != tty->driver->other->termios[idx]) {
unlock_kernel(); tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
"not o_termios for (%s)\n", "not o_termios for (%s)\n",
idx, tty->name); idx, tty->name);
return 0; return 0;
} }
if (o_tty->link != tty) { if (o_tty->link != tty) {
unlock_kernel(); tty_unlock();
printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
return 0; return 0;
} }
...@@ -1579,7 +1585,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1579,7 +1585,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close) if (tty->ops->close)
tty->ops->close(tty, filp); tty->ops->close(tty, filp);
unlock_kernel(); tty_unlock();
/* /*
* Sanity check: if tty->count is going to zero, there shouldn't be * Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the * any waiters on tty->read_wait or tty->write_wait. We test the
...@@ -1602,7 +1608,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1602,7 +1608,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */ opens on /dev/tty */
mutex_lock(&tty_mutex); mutex_lock(&tty_mutex);
lock_kernel(); tty_lock();
tty_closing = tty->count <= 1; tty_closing = tty->count <= 1;
o_tty_closing = o_tty && o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0)); (o_tty->count <= (pty_master ? 1 : 0));
...@@ -1633,7 +1639,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1633,7 +1639,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf)); "active!\n", tty_name(tty, buf));
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
schedule(); schedule();
} }
...@@ -1698,7 +1704,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1698,7 +1704,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */ /* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) { if (!tty_closing || (o_tty && !o_tty_closing)) {
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
...@@ -1718,7 +1724,7 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1718,7 +1724,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* Make this pty number available for reallocation */ /* Make this pty number available for reallocation */
if (devpts) if (devpts)
devpts_kill_index(inode, idx); devpts_kill_index(inode, idx);
unlock_kernel(); tty_unlock();
return 0; return 0;
} }
...@@ -1760,12 +1766,12 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1760,12 +1766,12 @@ static int tty_open(struct inode *inode, struct file *filp)
retval = 0; retval = 0;
mutex_lock(&tty_mutex); mutex_lock(&tty_mutex);
lock_kernel(); tty_lock();
if (device == MKDEV(TTYAUX_MAJOR, 0)) { if (device == MKDEV(TTYAUX_MAJOR, 0)) {
tty = get_current_tty(); tty = get_current_tty();
if (!tty) { if (!tty) {
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
return -ENXIO; return -ENXIO;
} }
...@@ -1797,14 +1803,14 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1797,14 +1803,14 @@ static int tty_open(struct inode *inode, struct file *filp)
goto got_driver; goto got_driver;
} }
} }
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
return -ENODEV; return -ENODEV;
} }
driver = get_tty_driver(device, &index); driver = get_tty_driver(device, &index);
if (!driver) { if (!driver) {
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
return -ENODEV; return -ENODEV;
} }
...@@ -1814,7 +1820,7 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1814,7 +1820,7 @@ static int tty_open(struct inode *inode, struct file *filp)
tty = tty_driver_lookup_tty(driver, inode, index); tty = tty_driver_lookup_tty(driver, inode, index);
if (IS_ERR(tty)) { if (IS_ERR(tty)) {
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
return PTR_ERR(tty); return PTR_ERR(tty);
} }
...@@ -1830,7 +1836,7 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1830,7 +1836,7 @@ static int tty_open(struct inode *inode, struct file *filp)
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
tty_driver_kref_put(driver); tty_driver_kref_put(driver);
if (IS_ERR(tty)) { if (IS_ERR(tty)) {
unlock_kernel(); tty_unlock();
return PTR_ERR(tty); return PTR_ERR(tty);
} }
...@@ -1862,11 +1868,11 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1862,11 +1868,11 @@ static int tty_open(struct inode *inode, struct file *filp)
#endif #endif
tty_release(inode, filp); tty_release(inode, filp);
if (retval != -ERESTARTSYS) { if (retval != -ERESTARTSYS) {
unlock_kernel(); tty_unlock();
return retval; return retval;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
unlock_kernel(); tty_unlock();
return retval; return retval;
} }
schedule(); schedule();
...@@ -1875,14 +1881,14 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1875,14 +1881,14 @@ static int tty_open(struct inode *inode, struct file *filp)
*/ */
if (filp->f_op == &hung_up_tty_fops) if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops; filp->f_op = &tty_fops;
unlock_kernel(); tty_unlock();
goto retry_open; goto retry_open;
} }
unlock_kernel(); tty_unlock();
mutex_lock(&tty_mutex); mutex_lock(&tty_mutex);
lock_kernel(); tty_lock();
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
if (!noctty && if (!noctty &&
current->signal->leader && current->signal->leader &&
...@@ -1890,7 +1896,7 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1890,7 +1896,7 @@ static int tty_open(struct inode *inode, struct file *filp)
tty->session == NULL) tty->session == NULL)
__proc_set_tty(current, tty); __proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
unlock_kernel(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
return 0; return 0;
} }
...@@ -1926,13 +1932,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) ...@@ -1926,13 +1932,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
return ret; return ret;
} }
static int tty_fasync(int fd, struct file *filp, int on) static int __tty_fasync(int fd, struct file *filp, int on)
{ {
struct tty_struct *tty; struct tty_struct *tty;
unsigned long flags; unsigned long flags;
int retval = 0; int retval = 0;
lock_kernel();
tty = (struct tty_struct *)filp->private_data; tty = (struct tty_struct *)filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
goto out; goto out;
...@@ -1966,7 +1971,15 @@ static int tty_fasync(int fd, struct file *filp, int on) ...@@ -1966,7 +1971,15 @@ static int tty_fasync(int fd, struct file *filp, int on)
} }
retval = 0; retval = 0;
out: out:
unlock_kernel(); return retval;
}
static int tty_fasync(int fd, struct file *filp, int on)
{
int retval;
tty_lock();
retval = __tty_fasync(fd, filp, on);
tty_unlock();
return retval; return retval;
} }
......
...@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) ...@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
* *
* A helper opening method. Also a convenient debugging and check * A helper opening method. Also a convenient debugging and check
* point. * point.
*
* Locking: always called with BTM already held.
*/ */
static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
...@@ -447,10 +449,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) ...@@ -447,10 +449,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
if (ld->ops->open) { if (ld->ops->open) {
int ret; int ret;
/* BKL here locks verus a hangup event */ /* BTM here locks versus a hangup event */
lock_kernel(); tty_lock_nested(); /* always held here already */
ret = ld->ops->open(tty); ret = ld->ops->open(tty);
unlock_kernel(); tty_unlock();
return ret; return ret;
} }
return 0; return 0;
...@@ -553,7 +555,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -553,7 +555,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc)) if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc); return PTR_ERR(new_ldisc);
lock_kernel(); tty_lock();
/* /*
* We need to look at the tty locking here for pty/tty pairs * We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel. * when both sides try to change in parallel.
...@@ -567,12 +569,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -567,12 +569,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/ */
if (tty->ldisc->ops->num == ldisc) { if (tty->ldisc->ops->num == ldisc) {
unlock_kernel(); tty_unlock();
tty_ldisc_put(new_ldisc); tty_ldisc_put(new_ldisc);
return 0; return 0;
} }
unlock_kernel(); tty_unlock();
/* /*
* Problem: What do we do if this blocks ? * Problem: What do we do if this blocks ?
* We could deadlock here * We could deadlock here
...@@ -594,7 +596,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -594,7 +596,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
mutex_lock(&tty->ldisc_mutex); mutex_lock(&tty->ldisc_mutex);
} }
lock_kernel(); tty_lock();
set_bit(TTY_LDISC_CHANGING, &tty->flags); set_bit(TTY_LDISC_CHANGING, &tty->flags);
...@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc; o_ldisc = tty->ldisc;
unlock_kernel(); tty_unlock();
/* /*
* Make sure we don't change while someone holds a * Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit * reference to the line discipline. The TTY_LDISC bit
...@@ -633,14 +635,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -633,14 +635,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
flush_scheduled_work(); flush_scheduled_work();
mutex_lock(&tty->ldisc_mutex); mutex_lock(&tty->ldisc_mutex);
lock_kernel(); tty_lock();
if (test_bit(TTY_HUPPED, &tty->flags)) { if (test_bit(TTY_HUPPED, &tty->flags)) {
/* We were raced by the hangup method. It will have stomped /* We were raced by the hangup method. It will have stomped
the ldisc data and closed the ldisc down */ the ldisc data and closed the ldisc down */
clear_bit(TTY_LDISC_CHANGING, &tty->flags); clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex); mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc); tty_ldisc_put(new_ldisc);
unlock_kernel(); tty_unlock();
return -EIO; return -EIO;
} }
...@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) ...@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (o_work) if (o_work)
schedule_delayed_work(&o_tty->buf.work, 1); schedule_delayed_work(&o_tty->buf.work, 1);
mutex_unlock(&tty->ldisc_mutex); mutex_unlock(&tty->ldisc_mutex);
unlock_kernel(); tty_unlock();
return retval; return retval;
} }
......
...@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp) ...@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp)
unsigned int currcons = iminor(inode) & 127; unsigned int currcons = iminor(inode) & 127;
int ret = 0; int ret = 0;
lock_kernel(); tty_lock();
if(currcons && !vc_cons_allocated(currcons-1)) if(currcons && !vc_cons_allocated(currcons-1))
ret = -ENXIO; ret = -ENXIO;
unlock_kernel(); tty_unlock();
return ret; return ret;
} }
......
...@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num; console = vc->vc_num;
lock_kernel(); tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */ if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
...@@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
} }
out: out:
unlock_kernel(); tty_unlock();
return ret; return ret;
eperm: eperm:
ret = -EPERM; ret = -EPERM;
...@@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num; console = vc->vc_num;
lock_kernel(); tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */ if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
...@@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
goto fallback; goto fallback;
} }
out: out:
unlock_kernel(); tty_unlock();
return ret; return ret;
fallback: fallback:
unlock_kernel(); tty_unlock();
return vt_ioctl(tty, file, cmd, arg); return vt_ioctl(tty, file, cmd, arg);
} }
......
...@@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
printk("jiff=%lu...", jiffies); printk("jiff=%lu...", jiffies);
#endif #endif
lock_kernel(); tty_lock_nested(); /* always held already since we come from ->close */
/* We go through the loop at least once because we can't tell /* We go through the loop at least once because we can't tell
* exactly when the last character exits the shifter. There can * exactly when the last character exits the shifter. There can
* be at least two characters waiting to be sent after the buffers * be at least two characters waiting to be sent after the buffers
...@@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
bdp--; bdp--;
} while (bdp->status & BD_SC_READY); } while (bdp->status & BD_SC_READY);
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
unlock_kernel(); tty_unlock();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif #endif
......
...@@ -3935,7 +3935,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -3935,7 +3935,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
* R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
*/ */
lock_kernel(); tty_lock_nested(); /* locked already when coming from close */
orig_jiffies = jiffies; orig_jiffies = jiffies;
while (info->xmit.head != info->xmit.tail || /* More in send queue */ while (info->xmit.head != info->xmit.tail || /* More in send queue */
(*info->ostatusadr & 0x007f) || /* more in FIFO */ (*info->ostatusadr & 0x007f) || /* more in FIFO */
...@@ -3952,7 +3952,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -3952,7 +3952,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
curr_time_usec - info->last_tx_active_usec; curr_time_usec - info->last_tx_active_usec;
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
unlock_kernel(); tty_unlock();
} }
/* /*
......
...@@ -1274,7 +1274,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1274,7 +1274,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
struct uart_port *uport; struct uart_port *uport;
unsigned long flags; unsigned long flags;
BUG_ON(!kernel_locked()); BUG_ON(!tty_locked());
if (!state) if (!state)
return; return;
...@@ -1382,7 +1382,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1382,7 +1382,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
if (port->type == PORT_UNKNOWN || port->fifosize == 0) if (port->type == PORT_UNKNOWN || port->fifosize == 0)
return; return;
lock_kernel(); tty_lock_nested(); /* already locked when coming from close */
/* /*
* Set the check interval to be 1/5 of the estimated time to * Set the check interval to be 1/5 of the estimated time to
...@@ -1429,7 +1429,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -1429,7 +1429,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
break; break;
} }
set_current_state(TASK_RUNNING); /* might not be needed */ set_current_state(TASK_RUNNING); /* might not be needed */
unlock_kernel(); tty_unlock();
} }
/* /*
...@@ -1444,7 +1444,7 @@ static void uart_hangup(struct tty_struct *tty) ...@@ -1444,7 +1444,7 @@ static void uart_hangup(struct tty_struct *tty)
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
unsigned long flags; unsigned long flags;
BUG_ON(!kernel_locked()); BUG_ON(!tty_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line); pr_debug("uart_hangup(%d)\n", state->uart_port->line);
mutex_lock(&port->mutex); mutex_lock(&port->mutex);
...@@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) ...@@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
struct tty_port *port; struct tty_port *port;
int retval, line = tty->index; int retval, line = tty->index;
BUG_ON(!kernel_locked()); BUG_ON(!tty_locked());
pr_debug("uart_open(%d) called\n", line); pr_debug("uart_open(%d) called\n", line);
/* /*
......
...@@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) ...@@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 4 * cmapsz; charmap += 4 * cmapsz;
#endif #endif
unlock_kernel(); tty_unlock();
spin_lock_irq(&vga_lock); spin_lock_irq(&vga_lock);
/* First, the Sequencer */ /* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
...@@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) ...@@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
} }
spin_unlock_irq(&vga_lock); spin_unlock_irq(&vga_lock);
lock_kernel(); tty_lock();
return 0; return 0;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/tty_driver.h> #include <linux/tty_driver.h>
#include <linux/tty_ldisc.h> #include <linux/tty_ldisc.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/smp_lock.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -576,5 +577,35 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file, ...@@ -576,5 +577,35 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,
extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
/* functions for preparation of BKL removal */
/*
* tty_lock_nested get the tty_lock while potentially holding it
*
* The Big TTY Mutex is a recursive lock, meaning you can take it
* from a thread that is already holding it.
* This is bad for a number of reasons, so tty_lock_nested should
* really be used as rarely as possible. If a code location can
* be shown to never get called with this held already, it should
* use tty_lock() instead.
*/
static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock)
{
lock_kernel();
}
static inline void tty_lock(void) __acquires(kernel_lock)
{
#ifdef CONFIG_LOCK_KERNEL
/* kernel_locked is 1 for !CONFIG_LOCK_KERNEL */
WARN_ON(kernel_locked());
#endif
lock_kernel();
}
static inline void tty_unlock(void) __releases(kernel_lock)
{
unlock_kernel();
}
#define tty_locked() (kernel_locked())
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
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