summaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c404
1 files changed, 192 insertions, 212 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index b3cfc8b..47a6eac 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -109,13 +109,15 @@
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
-struct termios tty_std_termios = { /* for the benefit of tty drivers */
+struct ktermios tty_std_termios = { /* for the benefit of tty drivers */
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN,
- .c_cc = INIT_C_CC
+ .c_cc = INIT_C_CC,
+ .c_ispeed = 38400,
+ .c_ospeed = 38400
};
EXPORT_SYMBOL(tty_std_termios);
@@ -126,7 +128,7 @@ EXPORT_SYMBOL(tty_std_termios);
LIST_HEAD(tty_drivers); /* linked list of tty drivers */
-/* Semaphore to protect creating and releasing a tty. This is shared with
+/* Mutex to protect creating and releasing a tty. This is shared with
vt.c for deeply disgusting hack reasons */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);
@@ -250,7 +252,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
"!= #fd's(%d) in %s\n",
tty->name, tty->count, count, routine);
return count;
- }
+ }
#endif
return 0;
}
@@ -259,18 +261,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
* Tty buffer allocation management
*/
-
-/**
- * tty_buffer_free_all - free buffers used by a tty
- * @tty: tty to free from
- *
- * Remove all the buffers pending on a tty whether queued with data
- * or in the free ring. Must be called when the tty is no longer in use
- *
- * Locking: none
- */
-
-
/**
* tty_buffer_free_all - free buffers used by a tty
* @tty: tty to free from
@@ -614,7 +604,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
* they are not on hot paths so a little discipline won't do
* any harm.
*
- * Locking: takes termios_sem
+ * Locking: takes termios_mutex
*/
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -915,7 +905,7 @@ static void tty_ldisc_enable(struct tty_struct *tty)
* context.
*
* Locking: takes tty_ldisc_lock.
- * called functions take termios_sem
+ * called functions take termios_mutex
*/
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -1251,6 +1241,22 @@ void tty_ldisc_flush(struct tty_struct *tty)
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
+ * tty_reset_termios - reset terminal state
+ * @tty: tty to reset
+ *
+ * Restore a terminal to the driver default state
+ */
+
+static void tty_reset_termios(struct tty_struct *tty)
+{
+ mutex_lock(&tty->termios_mutex);
+ *tty->termios = tty->driver->init_termios;
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+ mutex_unlock(&tty->termios_mutex);
+}
/**
* do_tty_hangup - actual handler for hangup events
@@ -1267,12 +1273,12 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
*
* Locking:
* BKL
- * redirect lock for undoing redirection
- * file list lock for manipulating list of ttys
- * tty_ldisc_lock from called functions
- * termios_sem resetting termios data
- * tasklist_lock to walk task list for hangup event
- *
+ * redirect lock for undoing redirection
+ * file list lock for manipulating list of ttys
+ * tty_ldisc_lock from called functions
+ * termios_mutex resetting termios data
+ * tasklist_lock to walk task list for hangup event
+ * ->siglock to protect ->signal/->sighand
*/
static void do_tty_hangup(struct work_struct *work)
{
@@ -1339,11 +1345,7 @@ static void do_tty_hangup(struct work_struct *work)
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
- {
- mutex_lock(&tty->termios_mutex);
- *tty->termios = tty->driver->init_termios;
- mutex_unlock(&tty->termios_mutex);
- }
+ tty_reset_termios(tty);
/* Defer ldisc switch */
/* tty_deferred_ldisc_switch(N_TTY);
@@ -1354,14 +1356,18 @@ static void do_tty_hangup(struct work_struct *work)
read_lock(&tasklist_lock);
if (tty->session > 0) {
do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty)
p->signal->tty = NULL;
- if (!p->signal->leader)
+ if (!p->signal->leader) {
+ spin_unlock_irq(&p->sighand->siglock);
continue;
- group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ }
+ __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
if (tty->pgrp > 0)
p->signal->tty_old_pgrp = tty->pgrp;
+ spin_unlock_irq(&p->sighand->siglock);
} while_each_task_pid(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
@@ -1453,6 +1459,14 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
+static void session_clear_tty(pid_t session)
+{
+ struct task_struct *p;
+ do_each_task_pid(session, PIDTYPE_SID, p) {
+ proc_clear_tty(p);
+ } while_each_task_pid(session, PIDTYPE_SID, p);
+}
+
/**
* disassociate_ctty - disconnect controlling tty
* @on_exit: true if exiting so need to "hang up" the session
@@ -1469,31 +1483,35 @@ EXPORT_SYMBOL(tty_hung_up_p);
* The argument on_exit is set to 1 if called when a process is
* exiting; it is 0 if called by the ioctl TIOCNOTTY.
*
- * Locking: tty_mutex is taken to protect current->signal->tty
+ * Locking:
* BKL is taken for hysterical raisins
- * Tasklist lock is taken (under tty_mutex) to walk process
- * lists for the session.
+ * tty_mutex is taken to protect tty
+ * ->siglock is taken to protect ->signal/->sighand
+ * tasklist_lock is taken to walk process list for sessions
+ * ->siglock is taken to protect ->signal/->sighand
*/
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
- struct task_struct *p;
int tty_pgrp = -1;
+ int session;
lock_kernel();
mutex_lock(&tty_mutex);
- tty = current->signal->tty;
+ tty = get_current_tty();
if (tty) {
tty_pgrp = tty->pgrp;
mutex_unlock(&tty_mutex);
+ /* XXX: here we race, there is nothing protecting tty */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
} else {
- if (current->signal->tty_old_pgrp) {
- kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
- kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+ pid_t old_pgrp = current->signal->tty_old_pgrp;
+ if (old_pgrp) {
+ kill_pg(old_pgrp, SIGHUP, on_exit);
+ kill_pg(old_pgrp, SIGCONT, on_exit);
}
mutex_unlock(&tty_mutex);
unlock_kernel();
@@ -1505,19 +1523,29 @@ void disassociate_ctty(int on_exit)
kill_pg(tty_pgrp, SIGCONT, on_exit);
}
- /* Must lock changes to tty_old_pgrp */
- mutex_lock(&tty_mutex);
+ spin_lock_irq(&current->sighand->siglock);
current->signal->tty_old_pgrp = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ session = process_session(current);
+ spin_unlock_irq(&current->sighand->siglock);
+
+ mutex_lock(&tty_mutex);
+ /* It is possible that do_tty_hangup has free'd this tty */
+ tty = get_current_tty();
+ if (tty) {
+ tty->session = 0;
+ tty->pgrp = 0;
+ } else {
+#ifdef TTY_DEBUG_HANGUP
+ printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+ " = NULL", tty);
+#endif
+ }
+ mutex_unlock(&tty_mutex);
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
- do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+ session_clear_tty(session);
read_unlock(&tasklist_lock);
- mutex_unlock(&tty_mutex);
unlock_kernel();
}
@@ -1615,7 +1643,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
struct tty_ldisc *ld;
tty = (struct tty_struct *)file->private_data;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1718,7 +1746,7 @@ static inline ssize_t do_tty_write(
cond_resched();
}
if (written) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
inode->i_mtime = current_fs_time(inode->i_sb);
ret = written;
}
@@ -1749,7 +1777,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou
loff_t *ppos)
{
struct tty_struct * tty;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t ret;
struct tty_ldisc *ld;
@@ -1856,8 +1884,8 @@ static int init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty)
{
struct tty_struct *tty, *o_tty;
- struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
+ struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
+ struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
int retval = 0;
/* check whether we're reopening an existing tty */
@@ -1904,7 +1932,7 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*tp_loc) {
- tp = (struct termios *) kmalloc(sizeof(struct termios),
+ tp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!tp)
goto free_mem_out;
@@ -1912,11 +1940,11 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*ltp_loc) {
- ltp = (struct termios *) kmalloc(sizeof(struct termios),
+ ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!ltp)
goto free_mem_out;
- memset(ltp, 0, sizeof(struct termios));
+ memset(ltp, 0, sizeof(struct ktermios));
}
if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -1937,19 +1965,19 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*o_tp_loc) {
- o_tp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_tp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_tp)
goto free_mem_out;
*o_tp = driver->other->init_termios;
}
if (!*o_ltp_loc) {
- o_ltp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_ltp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_ltp)
goto free_mem_out;
- memset(o_ltp, 0, sizeof(struct termios));
+ memset(o_ltp, 0, sizeof(struct ktermios));
}
/*
@@ -1988,6 +2016,9 @@ static int init_dev(struct tty_driver *driver, int idx,
*ltp_loc = ltp;
tty->termios = *tp_loc;
tty->termios_locked = *ltp_loc;
+ /* Compatibility until drivers always set this */
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
driver->refcount++;
tty->count++;
@@ -2090,7 +2121,7 @@ release_mem_out:
static void release_mem(struct tty_struct *tty, int idx)
{
struct tty_struct *o_tty;
- struct termios *tp;
+ struct ktermios *tp;
int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
if ((o_tty = tty->link) != NULL) {
@@ -2156,7 +2187,7 @@ static void release_dev(struct file * filp)
unsigned long flags;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev"))
return;
check_tty_count(tty, "release_dev");
@@ -2337,16 +2368,10 @@ static void release_dev(struct file * filp)
* tty.
*/
if (tty_closing || o_tty_closing) {
- struct task_struct *p;
-
read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ session_clear_tty(tty->session);
if (o_tty)
- do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+ session_clear_tty(o_tty->session);
read_unlock(&tasklist_lock);
}
@@ -2443,9 +2468,9 @@ static void release_dev(struct file * filp)
* The termios state of a pty is reset on first open so that
* settings don't persist across reuse.
*
- * Locking: tty_mutex protects current->signal->tty, get_tty_driver and
- * init_dev work. tty->count should protect the rest.
- * task_lock is held to update task details for sessions
+ * Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ * tty->count should protect the rest.
+ * ->siglock protects ->signal/->sighand
*/
static int tty_open(struct inode * inode, struct file * filp)
@@ -2467,12 +2492,13 @@ retry_open:
mutex_lock(&tty_mutex);
if (device == MKDEV(TTYAUX_MAJOR,0)) {
- if (!current->signal->tty) {
+ tty = get_current_tty();
+ if (!tty) {
mutex_unlock(&tty_mutex);
return -ENXIO;
}
- driver = current->signal->tty->driver;
- index = current->signal->tty->index;
+ driver = tty->driver;
+ index = tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
goto got_driver;
@@ -2547,17 +2573,16 @@ got_driver:
filp->f_op = &tty_fops;
goto retry_open;
}
+
+ mutex_lock(&tty_mutex);
+ spin_lock_irq(&current->sighand->siglock);
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
- tty->session == 0) {
- task_lock(current);
- current->signal->tty = tty;
- task_unlock(current);
- current->signal->tty_old_pgrp = 0;
- tty->session = current->signal->session;
- tty->pgrp = process_group(current);
- }
+ tty->session == 0)
+ __proc_set_tty(current, tty);
+ spin_unlock_irq(&current->sighand->siglock);
+ mutex_unlock(&tty_mutex);
return 0;
}
@@ -2672,7 +2697,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait)
int ret = 0;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
ld = tty_ldisc_ref_wait(tty);
@@ -2688,7 +2713,7 @@ static int tty_fasync(int fd, struct file * filp, int on)
int retval;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
return 0;
retval = fasync_helper(fd, filp, on, &tty->fasync);
@@ -2747,7 +2772,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
*
* Copies the kernel idea of the window size into the user buffer.
*
- * Locking: tty->termios_sem is taken to ensure the winsize data
+ * Locking: tty->termios_mutex is taken to ensure the winsize data
* is consistent.
*/
@@ -2774,8 +2799,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
* Locking:
* Called function use the console_sem is used to ensure we do
* not try and resize the console twice at once.
- * The tty->termios_sem is used to ensure we don't double
- * resize and get confused. Lock order - tty->termios.sem before
+ * The tty->termios_mutex is used to ensure we don't double
+ * resize and get confused. Lock order - tty->termios_mutex before
* console sem
*/
@@ -2880,25 +2905,28 @@ static int fionbio(struct file *file, int __user *p)
* leader to set this tty as the controlling tty for the session.
*
* Locking:
- * Takes tasklist lock internally to walk sessions
- * Takes task_lock() when updating signal->tty
* Takes tty_mutex() to protect tty instance
- *
+ * Takes tasklist_lock internally to walk sessions
+ * Takes ->siglock() when updating signal->tty
*/
static int tiocsctty(struct tty_struct *tty, int arg)
{
- struct task_struct *p;
-
+ int ret = 0;
if (current->signal->leader &&
- (current->signal->session == tty->session))
- return 0;
+ (process_session(current) == tty->session))
+ return ret;
+
+ mutex_lock(&tty_mutex);
/*
* The process must be a session leader and
* not have a controlling tty already.
*/
- if (!current->signal->leader || current->signal->tty)
- return -EPERM;
+ if (!current->signal->leader || current->signal->tty) {
+ ret = -EPERM;
+ goto unlock;
+ }
+
if (tty->session > 0) {
/*
* This tty is already the controlling
@@ -2908,24 +2936,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
/*
* Steal it away
*/
-
read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ session_clear_tty(tty->session);
read_unlock(&tasklist_lock);
- } else
- return -EPERM;
+ } else {
+ ret = -EPERM;
+ goto unlock;
+ }
}
- mutex_lock(&tty_mutex);
- task_lock(current);
- current->signal->tty = tty;
- task_unlock(current);
+ proc_set_tty(current, tty);
+unlock:
mutex_unlock(&tty_mutex);
- current->signal->tty_old_pgrp = 0;
- tty->session = current->signal->session;
- tty->pgrp = process_group(current);
- return 0;
+ return ret;
}
/**
@@ -2937,7 +2959,7 @@ static int tiocsctty(struct tty_struct *tty, int arg)
* Obtain the process group of the tty. If there is no process group
* return an error.
*
- * Locking: none. Reference to ->signal->tty is safe.
+ * Locking: none. Reference to current->signal->tty is safe.
*/
static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -2974,13 +2996,13 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return retval;
if (!current->signal->tty ||
(current->signal->tty != real_tty) ||
- (real_tty->session != current->signal->session))
+ (real_tty->session != process_session(current)))
return -ENOTTY;
if (get_user(pgrp, p))
return -EFAULT;
if (pgrp < 0)
return -EINVAL;
- if (session_of_pgrp(pgrp) != current->signal->session)
+ if (session_of_pgrp(pgrp) != process_session(current))
return -EPERM;
real_tty->pgrp = pgrp;
return 0;
@@ -2995,7 +3017,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
* Obtain the session id of the tty. If there is no session
* return an error.
*
- * Locking: none. Reference to ->signal->tty is safe.
+ * Locking: none. Reference to current->signal->tty is safe.
*/
static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3214,14 +3236,11 @@ int tty_ioctl(struct inode * inode, struct file * file,
clear_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCNOTTY:
- /* FIXME: taks lock or tty_mutex ? */
if (current->signal->tty != tty)
return -ENOTTY;
if (current->signal->leader)
disassociate_ctty(0);
- task_lock(current);
- current->signal->tty = NULL;
- task_unlock(current);
+ proc_clear_tty(current);
return 0;
case TIOCSCTTY:
return tiocsctty(tty, arg);
@@ -3316,18 +3335,13 @@ static void __do_SAK(struct work_struct *work)
int session;
int i;
struct file *filp;
- struct tty_ldisc *disc;
struct fdtable *fdt;
if (!tty)
return;
- session = tty->session;
+ session = tty->session;
- /* We don't want an ldisc switch during this */
- disc = tty_ldisc_ref(tty);
- if (disc && disc->flush_buffer)
- disc->flush_buffer(tty);
- tty_ldisc_deref(disc);
+ tty_ldisc_flush(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -3336,7 +3350,7 @@ static void __do_SAK(struct work_struct *work)
/* Kill the entire session */
do_each_task_pid(session, PIDTYPE_SID, p) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): p->signal->session==tty->session\n",
+ " (%s): process_session(p)==tty->session\n",
p->pid, p->comm);
send_sig(SIGKILL, p, 1);
} while_each_task_pid(session, PIDTYPE_SID, p);
@@ -3346,7 +3360,7 @@ static void __do_SAK(struct work_struct *work)
do_each_thread(g, p) {
if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): p->signal->session==tty->session\n",
+ " (%s): process_session(p)==tty->session\n",
p->pid, p->comm);
send_sig(SIGKILL, p, 1);
continue;
@@ -3456,84 +3470,6 @@ static void flush_to_ldisc(struct work_struct *work)
tty_ldisc_deref(disc);
}
-/*
- * Routine which returns the baud rate of the tty
- *
- * Note that the baud_table needs to be kept in sync with the
- * include/asm/termbits.h file.
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800,
-#ifdef __sparc__
- 76800, 153600, 307200, 614400, 921600
-#else
- 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
- 2500000, 3000000, 3500000, 4000000
-#endif
-};
-
-static int n_baud_table = ARRAY_SIZE(baud_table);
-
-/**
- * tty_termios_baud_rate
- * @termios: termios structure
- *
- * Convert termios baud rate data into a speed. This should be called
- * with the termios lock held if this termios is a terminal termios
- * structure. May change the termios data.
- *
- * Locking: none
- */
-
-int tty_termios_baud_rate(struct termios *termios)
-{
- unsigned int cbaud;
-
- cbaud = termios->c_cflag & CBAUD;
-
- if (cbaud & CBAUDEX) {
- cbaud &= ~CBAUDEX;
-
- if (cbaud < 1 || cbaud + 15 > n_baud_table)
- termios->c_cflag &= ~CBAUDEX;
- else
- cbaud += 15;
- }
- return baud_table[cbaud];
-}
-
-EXPORT_SYMBOL(tty_termios_baud_rate);
-
-/**
- * tty_get_baud_rate - get tty bit rates
- * @tty: tty to query
- *
- * Returns the baud rate as an integer for this terminal. The
- * termios lock must be held by the caller and the terminal bit
- * flags may be updated.
- *
- * Locking: none
- */
-
-int tty_get_baud_rate(struct tty_struct *tty)
-{
- int baud = tty_termios_baud_rate(tty->termios);
-
- if (baud == 38400 && tty->alt_speed) {
- if (!tty->warned) {
- printk(KERN_WARNING "Use of setserial/setrocket to "
- "set SPD_* flags is deprecated\n");
- tty->warned = 1;
- }
- baud = tty->alt_speed;
- }
-
- return baud;
-}
-
-EXPORT_SYMBOL(tty_get_baud_rate);
-
/**
* tty_flip_buffer_push - terminal
* @tty: tty to push
@@ -3756,8 +3692,8 @@ int tty_register_driver(struct tty_driver *driver)
if (p) {
driver->ttys = (struct tty_struct **)p;
- driver->termios = (struct termios **)(p + driver->num);
- driver->termios_locked = (struct termios **)(p + driver->num * 2);
+ driver->termios = (struct ktermios **)(p + driver->num);
+ driver->termios_locked = (struct ktermios **)(p + driver->num * 2);
} else {
driver->ttys = NULL;
driver->termios = NULL;
@@ -3796,7 +3732,7 @@ EXPORT_SYMBOL(tty_register_driver);
int tty_unregister_driver(struct tty_driver *driver)
{
int i;
- struct termios *tp;
+ struct ktermios *tp;
void *p;
if (driver->refcount)
@@ -3834,9 +3770,53 @@ int tty_unregister_driver(struct tty_driver *driver)
cdev_del(&driver->cdev);
return 0;
}
-
EXPORT_SYMBOL(tty_unregister_driver);
+dev_t tty_devnum(struct tty_struct *tty)
+{
+ return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
+}
+EXPORT_SYMBOL(tty_devnum);
+
+void proc_clear_tty(struct task_struct *p)
+{
+ spin_lock_irq(&p->sighand->siglock);
+ p->signal->tty = NULL;
+ spin_unlock_irq(&p->sighand->siglock);
+}
+EXPORT_SYMBOL(proc_clear_tty);
+
+void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+ if (tty) {
+ tty->session = process_session(tsk);
+ tty->pgrp = process_group(tsk);
+ }
+ tsk->signal->tty = tty;
+ tsk->signal->tty_old_pgrp = 0;
+}
+
+void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+ spin_lock_irq(&tsk->sighand->siglock);
+ __proc_set_tty(tsk, tty);
+ spin_unlock_irq(&tsk->sighand->siglock);
+}
+
+struct tty_struct *get_current_tty(void)
+{
+ struct tty_struct *tty;
+ WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
+ tty = current->signal->tty;
+ /*
+ * session->tty can be changed/cleared from under us, make sure we
+ * issue the load. The obtained pointer, when not NULL, is valid as
+ * long as we hold tty_mutex.
+ */
+ barrier();
+ return tty;
+}
+EXPORT_SYMBOL_GPL(get_current_tty);
/*
* Initialize the console device. This is called *early*, so
OpenPOWER on IntegriCloud