Commit cfe6b7c7 authored by Al Viro's avatar Al Viro Committed by Richard Weinberger

um: switch line.c tty drivers to dynamic device creation

Current code doesn't update the symlinks in /sys/dev/char when we add/remove
tty lines.  Fixing that allows to stop messing with ->valid before the driver
registration, which is a Good Thing(tm) - we shouldn't have it set before we
really have the things set up and ready for line_open().

We need tty_driver available to call tty_{un,}register_device(), so we just
stash a reference to it into struct line_driver.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 31efcebb
...@@ -485,6 +485,7 @@ static int setup_one_line(struct line *lines, int n, char *init, ...@@ -485,6 +485,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
const struct chan_opts *opts, char **error_out) const struct chan_opts *opts, char **error_out)
{ {
struct line *line = &lines[n]; struct line *line = &lines[n];
struct tty_driver *driver = line->driver->driver;
int err = -EINVAL; int err = -EINVAL;
mutex_lock(&line->count_lock); mutex_lock(&line->count_lock);
...@@ -498,6 +499,7 @@ static int setup_one_line(struct line *lines, int n, char *init, ...@@ -498,6 +499,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
if (line->valid) { if (line->valid) {
line->valid = 0; line->valid = 0;
kfree(line->init_str); kfree(line->init_str);
tty_unregister_device(driver, n);
parse_chan_pair(NULL, line, n, opts, error_out); parse_chan_pair(NULL, line, n, opts, error_out);
err = 0; err = 0;
} }
...@@ -507,9 +509,19 @@ static int setup_one_line(struct line *lines, int n, char *init, ...@@ -507,9 +509,19 @@ static int setup_one_line(struct line *lines, int n, char *init,
*error_out = "Failed to allocate memory"; *error_out = "Failed to allocate memory";
return -ENOMEM; return -ENOMEM;
} }
if (line->valid)
tty_unregister_device(driver, n);
line->init_str = new; line->init_str = new;
line->valid = 1; line->valid = 1;
err = parse_chan_pair(new, line, n, opts, error_out); err = parse_chan_pair(new, line, n, opts, error_out);
if (!err) {
struct device *d = tty_register_device(driver, n, NULL);
if (IS_ERR(d)) {
*error_out = "Failed to register device";
err = PTR_ERR(d);
parse_chan_pair(NULL, line, n, opts, error_out);
}
}
if (err) { if (err) {
line->init_str = NULL; line->init_str = NULL;
line->valid = 0; line->valid = 0;
...@@ -640,15 +652,15 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) ...@@ -640,15 +652,15 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
return setup_one_line(lines, n, "none", NULL, error_out); return setup_one_line(lines, n, "none", NULL, error_out);
} }
struct tty_driver *register_lines(struct line_driver *line_driver, int register_lines(struct line_driver *line_driver,
const struct tty_operations *ops, const struct tty_operations *ops,
struct line *lines, int nlines) struct line *lines, int nlines)
{ {
int i;
struct tty_driver *driver = alloc_tty_driver(nlines); struct tty_driver *driver = alloc_tty_driver(nlines);
int err;
if (!driver) if (!driver)
return NULL; return -ENOMEM;
driver->driver_name = line_driver->name; driver->driver_name = line_driver->name;
driver->name = line_driver->device_name; driver->name = line_driver->device_name;
...@@ -656,24 +668,21 @@ struct tty_driver *register_lines(struct line_driver *line_driver, ...@@ -656,24 +668,21 @@ struct tty_driver *register_lines(struct line_driver *line_driver,
driver->minor_start = line_driver->minor_start; driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type; driver->type = line_driver->type;
driver->subtype = line_driver->subtype; driver->subtype = line_driver->subtype;
driver->flags = TTY_DRIVER_REAL_RAW; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
driver->init_termios = tty_std_termios; driver->init_termios = tty_std_termios;
tty_set_operations(driver, ops); tty_set_operations(driver, ops);
if (tty_register_driver(driver)) { err = tty_register_driver(driver);
if (err) {
printk(KERN_ERR "register_lines : can't register %s driver\n", printk(KERN_ERR "register_lines : can't register %s driver\n",
line_driver->name); line_driver->name);
put_tty_driver(driver); put_tty_driver(driver);
return NULL; return err;
}
for(i = 0; i < nlines; i++) {
if (!lines[i].valid)
tty_unregister_device(driver, i);
} }
line_driver->driver = driver;
mconsole_register_dev(&line_driver->mc); mconsole_register_dev(&line_driver->mc);
return driver; return 0;
} }
static DEFINE_SPINLOCK(winch_handler_lock); static DEFINE_SPINLOCK(winch_handler_lock);
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "chan_user.h" #include "chan_user.h"
#include "mconsole_kern.h" #include "mconsole_kern.h"
/* There's only one modifiable field in this - .mc.list */ /* There's only two modifiable fields in this - .mc.list and .driver */
struct line_driver { struct line_driver {
const char *name; const char *name;
const char *device_name; const char *device_name;
...@@ -28,6 +28,7 @@ struct line_driver { ...@@ -28,6 +28,7 @@ struct line_driver {
const int write_irq; const int write_irq;
const char *write_irq_name; const char *write_irq_name;
struct mc_device mc; struct mc_device mc;
struct tty_driver *driver;
}; };
struct line { struct line {
...@@ -78,9 +79,9 @@ extern char *add_xterm_umid(char *base); ...@@ -78,9 +79,9 @@ extern char *add_xterm_umid(char *base);
extern int line_setup_irq(int fd, int input, int output, struct line *line, extern int line_setup_irq(int fd, int input, int output, struct line *line,
void *data); void *data);
extern void line_close_chan(struct line *line); extern void line_close_chan(struct line *line);
extern struct tty_driver *register_lines(struct line_driver *line_driver, extern int register_lines(struct line_driver *line_driver,
const struct tty_operations *driver, const struct tty_operations *driver,
struct line *lines, int nlines); struct line *lines, int nlines);
extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
extern void close_lines(struct line *lines, int nlines); extern void close_lines(struct line *lines, int nlines);
......
...@@ -20,12 +20,6 @@ ...@@ -20,12 +20,6 @@
static const int ssl_version = 1; static const int ssl_version = 1;
/* Referenced only by tty_driver below - presumably it's locked correctly
* by the tty driver.
*/
static struct tty_driver *ssl_driver;
#define NR_PORTS 64 #define NR_PORTS 64
static void ssl_announce(char *dev_name, int dev) static void ssl_announce(char *dev_name, int dev)
...@@ -164,7 +158,7 @@ static void ssl_console_write(struct console *c, const char *string, ...@@ -164,7 +158,7 @@ static void ssl_console_write(struct console *c, const char *string,
static struct tty_driver *ssl_console_device(struct console *c, int *index) static struct tty_driver *ssl_console_device(struct console *c, int *index)
{ {
*index = c->index; *index = c->index;
return ssl_driver; return driver.driver;
} }
static int ssl_console_setup(struct console *co, char *options) static int ssl_console_setup(struct console *co, char *options)
...@@ -187,6 +181,7 @@ static struct console ssl_cons = { ...@@ -187,6 +181,7 @@ static struct console ssl_cons = {
static int ssl_init(void) static int ssl_init(void)
{ {
char *new_title; char *new_title;
int err;
int i; int i;
printk(KERN_INFO "Initializing software serial port version %d\n", printk(KERN_INFO "Initializing software serial port version %d\n",
...@@ -196,16 +191,16 @@ static int ssl_init(void) ...@@ -196,16 +191,16 @@ static int ssl_init(void)
char *s = conf[i]; char *s = conf[i];
if (!s) if (!s)
s = def_conf; s = def_conf;
if (s && strcmp(s, "none") != 0) { if (s && strcmp(s, "none") != 0)
serial_lines[i].init_str = s; serial_lines[i].init_str = s;
serial_lines[i].valid = 1;
}
spin_lock_init(&serial_lines[i].lock); spin_lock_init(&serial_lines[i].lock);
mutex_init(&serial_lines[i].count_lock); mutex_init(&serial_lines[i].count_lock);
serial_lines[i].driver = &driver; serial_lines[i].driver = &driver;
} }
ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, err = register_lines(&driver, &ssl_ops, serial_lines,
ARRAY_SIZE(serial_lines)); ARRAY_SIZE(serial_lines));
if (err)
return err;
new_title = add_xterm_umid(opts.xterm_title); new_title = add_xterm_umid(opts.xterm_title);
if (new_title != NULL) if (new_title != NULL)
......
...@@ -27,12 +27,6 @@ ...@@ -27,12 +27,6 @@
#define MAX_TTYS (16) #define MAX_TTYS (16)
/* Referenced only by tty_driver below - presumably it's locked correctly
* by the tty driver.
*/
static struct tty_driver *console_driver;
static void stdio_announce(char *dev_name, int dev) static void stdio_announce(char *dev_name, int dev)
{ {
printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev,
...@@ -137,7 +131,7 @@ static void uml_console_write(struct console *console, const char *string, ...@@ -137,7 +131,7 @@ static void uml_console_write(struct console *console, const char *string,
static struct tty_driver *uml_console_device(struct console *c, int *index) static struct tty_driver *uml_console_device(struct console *c, int *index)
{ {
*index = c->index; *index = c->index;
return console_driver; return driver.driver;
} }
static int uml_console_setup(struct console *co, char *options) static int uml_console_setup(struct console *co, char *options)
...@@ -160,6 +154,7 @@ static struct console stdiocons = { ...@@ -160,6 +154,7 @@ static struct console stdiocons = {
static int stdio_init(void) static int stdio_init(void)
{ {
char *new_title; char *new_title;
int err;
int i; int i;
for (i = 0; i < MAX_TTYS; i++) { for (i = 0; i < MAX_TTYS; i++) {
...@@ -168,18 +163,16 @@ static int stdio_init(void) ...@@ -168,18 +163,16 @@ static int stdio_init(void)
s = def_conf; s = def_conf;
if (!s) if (!s)
s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN; s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN;
if (s && strcmp(s, "none") != 0) { if (s && strcmp(s, "none") != 0)
vts[i].init_str = s; vts[i].init_str = s;
vts[i].valid = 1;
}
spin_lock_init(&vts[i].lock); spin_lock_init(&vts[i].lock);
mutex_init(&vts[i].count_lock); mutex_init(&vts[i].count_lock);
vts[i].driver = &driver; vts[i].driver = &driver;
} }
console_driver = register_lines(&driver, &console_ops, vts, err = register_lines(&driver, &console_ops, vts,
ARRAY_SIZE(vts)); ARRAY_SIZE(vts));
if (console_driver == NULL) if (err)
return -1; return err;
printk(KERN_INFO "Initialized stdio console driver\n"); printk(KERN_INFO "Initialized stdio console driver\n");
new_title = add_xterm_umid(opts.xterm_title); new_title = add_xterm_umid(opts.xterm_title);
......
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