Commit d81ed103 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: Remove more special casing and out of place code

Carry on pushing code out of tty_io when it belongs to other drivers. I'm
not 100% happy with some of this and it will be worth revisiting some of the
exports later when the restructuring work is done.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent feebed65
......@@ -23,6 +23,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -332,6 +333,8 @@ int pty_limit = NR_UNIX98_PTY_DEFAULT;
static int pty_limit_min = 0;
static int pty_limit_max = NR_UNIX98_PTY_MAX;
static struct cdev ptmx_cdev;
static struct ctl_table pty_table[] = {
{
.ctl_name = PTY_MAX,
......@@ -408,6 +411,70 @@ static const struct tty_operations ptm_unix98_ops = {
.shutdown = pty_shutdown
};
/**
* ptmx_open - open a unix 98 pty master
* @inode: inode of device file
* @filp: file pointer to tty
*
* Allocate a unix98 pty master device from the ptmx driver.
*
* Locking: tty_mutex protects the init_dev work. tty->count should
* protect the rest.
* allocated_ptys_lock handles the list of free pty numbers
*/
static int __ptmx_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
int retval;
int index;
nonseekable_open(inode, filp);
/* find a device that is not in use. */
index = devpts_new_index();
if (index < 0)
return index;
mutex_lock(&tty_mutex);
retval = tty_init_dev(ptm_driver, index, &tty, 1);
mutex_unlock(&tty_mutex);
if (retval)
goto out;
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
filp->private_data = tty;
file_move(filp, &tty->tty_files);
retval = devpts_pty_new(tty->link);
if (retval)
goto out1;
retval = ptm_driver->ops->open(tty, filp);
if (!retval)
return 0;
out1:
tty_release_dev(filp);
return retval;
out:
devpts_kill_index(index);
return retval;
}
static int ptmx_open(struct inode *inode, struct file *filp)
{
int ret;
lock_kernel();
ret = __ptmx_open(inode, filp);
unlock_kernel();
return ret;
}
static struct file_operations ptmx_fops;
static void __init unix98_pty_init(void)
{
ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
......@@ -459,7 +526,18 @@ static void __init unix98_pty_init(void)
pty_table[1].data = &ptm_driver->refcount;
register_sysctl_table(pty_root_table);
/* Now create the /dev/ptmx special device */
tty_default_fops(&ptmx_fops);
ptmx_fops.open = ptmx_open;
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
}
#else
static inline void unix98_pty_init(void) { }
#endif
......
This diff is collapsed.
......@@ -40,6 +40,15 @@
#define TERMIOS_OLD 8
/**
* tty_chars_in_buffer - characters pending
* @tty: terminal
*
* Return the number of bytes of data in the device private
* output queue. If no private method is supplied there is assumed
* to be no queue on the device.
*/
int tty_chars_in_buffer(struct tty_struct *tty)
{
if (tty->ops->chars_in_buffer)
......@@ -47,26 +56,49 @@ int tty_chars_in_buffer(struct tty_struct *tty)
else
return 0;
}
EXPORT_SYMBOL(tty_chars_in_buffer);
/**
* tty_write_room - write queue space
* @tty: terminal
*
* Return the number of bytes that can be queued to this device
* at the present time. The result should be treated as a guarantee
* and the driver cannot offer a value it later shrinks by more than
* the number of bytes written. If no method is provided 2K is always
* returned and data may be lost as there will be no flow control.
*/
int tty_write_room(struct tty_struct *tty)
{
if (tty->ops->write_room)
return tty->ops->write_room(tty);
return 2048;
}
EXPORT_SYMBOL(tty_write_room);
/**
* tty_driver_flush_buffer - discard internal buffer
* @tty: terminal
*
* Discard the internal output buffer for this device. If no method
* is provided then either the buffer cannot be hardware flushed or
* there is no buffer driver side.
*/
void tty_driver_flush_buffer(struct tty_struct *tty)
{
if (tty->ops->flush_buffer)
tty->ops->flush_buffer(tty);
}
EXPORT_SYMBOL(tty_driver_flush_buffer);
/**
* tty_throttle - flow control
* @tty: terminal
*
* Indicate that a tty should stop transmitting data down the stack.
*/
void tty_throttle(struct tty_struct *tty)
{
/* check TTY_THROTTLED first so it indicates our state */
......@@ -76,6 +108,13 @@ void tty_throttle(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_throttle);
/**
* tty_unthrottle - flow control
* @tty: terminal
*
* Indicate that a tty may continue transmitting data down the stack.
*/
void tty_unthrottle(struct tty_struct *tty)
{
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
......@@ -112,6 +151,11 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
}
EXPORT_SYMBOL(tty_wait_until_sent);
/*
* Termios Helper Methods
*/
static void unset_locked_termios(struct ktermios *termios,
struct ktermios *old,
struct ktermios *locked)
......@@ -346,6 +390,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
}
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
/**
* tty_encode_baud_rate - set baud rate of the tty
* @ibaud: input baud rate
* @obad: output baud rate
*
* Update the current termios data for the tty with the new speed
* settings. The caller must hold the termios_mutex for the tty in
* question.
*/
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
{
tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
......@@ -430,7 +484,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
* is a bit of layering violation here with n_tty in terms of the
* internal knowledge of this function.
*
* Locking: termios_sem
* Locking: termios_mutex
*/
static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
......@@ -508,7 +562,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
* functions before using change_termios to do the actual changes.
*
* Locking:
* Called functions take ldisc and termios_sem locks
* Called functions take ldisc and termios_mutex locks
*/
static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
......@@ -715,7 +769,7 @@ static void set_sgflags(struct ktermios *termios, int flags)
* Updates a terminal from the legacy BSD style terminal information
* structure.
*
* Locking: termios_sem
* Locking: termios_mutex
*/
static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
......
......@@ -100,10 +100,10 @@
#include <linux/font.h>
#include <linux/bitops.h>
#include <linux/notifier.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#define MAX_NR_CON_DRIVER 16
......@@ -2352,8 +2352,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
FLUSH
console_conditional_schedule();
release_console_sem();
out:
notify_update(vc);
return n;
#undef FLUSH
......@@ -2784,13 +2782,6 @@ static int con_open(struct tty_struct *tty, struct file *filp)
return ret;
}
/*
* We take tty_mutex in here to prevent another thread from coming in via init_dev
* and taking a ref against the tty while we're in the process of forgetting
* about it and cleaning things up.
*
* This is because vcs_remove_sysfs() can sleep and will drop the BKL.
*/
static void con_close(struct tty_struct *tty, struct file *filp)
{
/* Nothing to do - we defer to shutdown */
......@@ -2932,8 +2923,16 @@ static const struct tty_operations con_ops = {
.shutdown = con_shutdown
};
int __init vty_init(void)
static struct cdev vc0_cdev;
int __init vty_init(const struct file_operations *console_fops)
{
cdev_init(&vc0_cdev, console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vcs_init();
console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
......@@ -2952,7 +2951,6 @@ int __init vty_init(void)
tty_set_operations(console_driver, &con_ops);
if (tty_register_driver(console_driver))
panic("Couldn't register console driver\n");
kbd_init();
console_map_init();
#ifdef CONFIG_PROM_CONSOLE
......@@ -3446,7 +3444,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
con_driver->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con_driver->node),
NULL, "vtcon%i",
con_driver->node);
......@@ -3557,7 +3555,7 @@ static int __init vtconsole_class_init(void)
struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->dev) {
con->dev = device_create_drvdata(vtconsole_class, NULL,
con->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con->node),
NULL, "vtcon%i",
con->node);
......
......@@ -314,6 +314,8 @@ extern int kmsg_redirect;
extern void console_init(void);
extern int vcs_init(void);
extern struct class *tty_class;
/**
* tty_kref_get - get a tty reference
* @tty: tty device
......@@ -398,6 +400,10 @@ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
extern dev_t tty_devnum(struct tty_struct *tty);
extern void proc_clear_tty(struct task_struct *p);
extern struct tty_struct *get_current_tty(void);
extern void tty_default_fops(struct file_operations *fops);
extern int tty_init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty, int first_ok);
extern void tty_release_dev(struct file *filp);
extern struct mutex tty_mutex;
......
......@@ -96,7 +96,7 @@ void change_console(struct vc_data *new_vc);
void reset_vc(struct vc_data *vc);
extern int unbind_con_driver(const struct consw *csw, int first, int last,
int deflt);
int vty_init(void);
int vty_init(const struct file_operations *console_fops);
/*
* vc_screen.c shares this temporary buffer with the console write code so that
......
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