diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-09-09 19:45:42 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2012-03-25 00:29:53 +0100 |
commit | cfe6b7c79daa0efa27f474f1fe2a88fd7af5cc47 (patch) | |
tree | 5030f25d83451e3b3e579bac4b9a2e561990048d /arch/um/drivers/line.c | |
parent | 31efcebb7d7196adcee73027f513d7c0bf572b47 (diff) |
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: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r-- | arch/um/drivers/line.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 1a8d6591c204..015209a98815 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -485,6 +485,7 @@ static int setup_one_line(struct line *lines, int n, char *init, const struct chan_opts *opts, char **error_out) { struct line *line = &lines[n]; + struct tty_driver *driver = line->driver->driver; int err = -EINVAL; mutex_lock(&line->count_lock); @@ -498,6 +499,7 @@ static int setup_one_line(struct line *lines, int n, char *init, if (line->valid) { line->valid = 0; kfree(line->init_str); + tty_unregister_device(driver, n); parse_chan_pair(NULL, line, n, opts, error_out); err = 0; } @@ -507,9 +509,19 @@ static int setup_one_line(struct line *lines, int n, char *init, *error_out = "Failed to allocate memory"; return -ENOMEM; } + if (line->valid) + tty_unregister_device(driver, n); line->init_str = new; line->valid = 1; 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) { line->init_str = NULL; line->valid = 0; @@ -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); } -struct tty_driver *register_lines(struct line_driver *line_driver, - const struct tty_operations *ops, - struct line *lines, int nlines) +int register_lines(struct line_driver *line_driver, + const struct tty_operations *ops, + struct line *lines, int nlines) { - int i; struct tty_driver *driver = alloc_tty_driver(nlines); + int err; if (!driver) - return NULL; + return -ENOMEM; driver->driver_name = line_driver->name; driver->name = line_driver->device_name; @@ -656,24 +668,21 @@ struct tty_driver *register_lines(struct line_driver *line_driver, driver->minor_start = line_driver->minor_start; driver->type = line_driver->type; 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; 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", line_driver->name); put_tty_driver(driver); - return NULL; - } - - for(i = 0; i < nlines; i++) { - if (!lines[i].valid) - tty_unregister_device(driver, i); + return err; } + line_driver->driver = driver; mconsole_register_dev(&line_driver->mc); - return driver; + return 0; } static DEFINE_SPINLOCK(winch_handler_lock); |