summaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-09-09 19:45:42 -0400
committerRichard Weinberger <richard@nod.at>2012-03-25 00:29:53 +0100
commitcfe6b7c79daa0efa27f474f1fe2a88fd7af5cc47 (patch)
tree5030f25d83451e3b3e579bac4b9a2e561990048d /arch/um/drivers/line.c
parent31efcebb7d7196adcee73027f513d7c0bf572b47 (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.c37
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);