aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
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-24 19:29:53 -0400
commitcfe6b7c79daa0efa27f474f1fe2a88fd7af5cc47 (patch)
tree5030f25d83451e3b3e579bac4b9a2e561990048d /arch/um
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')
-rw-r--r--arch/um/drivers/line.c37
-rw-r--r--arch/um/drivers/line.h9
-rw-r--r--arch/um/drivers/ssl.c17
-rw-r--r--arch/um/drivers/stdio_console.c19
4 files changed, 40 insertions, 42 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 1a8d6591c20..015209a9881 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,
485 const struct chan_opts *opts, char **error_out) 485 const struct chan_opts *opts, char **error_out)
486{ 486{
487 struct line *line = &lines[n]; 487 struct line *line = &lines[n];
488 struct tty_driver *driver = line->driver->driver;
488 int err = -EINVAL; 489 int err = -EINVAL;
489 490
490 mutex_lock(&line->count_lock); 491 mutex_lock(&line->count_lock);
@@ -498,6 +499,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
498 if (line->valid) { 499 if (line->valid) {
499 line->valid = 0; 500 line->valid = 0;
500 kfree(line->init_str); 501 kfree(line->init_str);
502 tty_unregister_device(driver, n);
501 parse_chan_pair(NULL, line, n, opts, error_out); 503 parse_chan_pair(NULL, line, n, opts, error_out);
502 err = 0; 504 err = 0;
503 } 505 }
@@ -507,9 +509,19 @@ static int setup_one_line(struct line *lines, int n, char *init,
507 *error_out = "Failed to allocate memory"; 509 *error_out = "Failed to allocate memory";
508 return -ENOMEM; 510 return -ENOMEM;
509 } 511 }
512 if (line->valid)
513 tty_unregister_device(driver, n);
510 line->init_str = new; 514 line->init_str = new;
511 line->valid = 1; 515 line->valid = 1;
512 err = parse_chan_pair(new, line, n, opts, error_out); 516 err = parse_chan_pair(new, line, n, opts, error_out);
517 if (!err) {
518 struct device *d = tty_register_device(driver, n, NULL);
519 if (IS_ERR(d)) {
520 *error_out = "Failed to register device";
521 err = PTR_ERR(d);
522 parse_chan_pair(NULL, line, n, opts, error_out);
523 }
524 }
513 if (err) { 525 if (err) {
514 line->init_str = NULL; 526 line->init_str = NULL;
515 line->valid = 0; 527 line->valid = 0;
@@ -640,15 +652,15 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
640 return setup_one_line(lines, n, "none", NULL, error_out); 652 return setup_one_line(lines, n, "none", NULL, error_out);
641} 653}
642 654
643struct tty_driver *register_lines(struct line_driver *line_driver, 655int register_lines(struct line_driver *line_driver,
644 const struct tty_operations *ops, 656 const struct tty_operations *ops,
645 struct line *lines, int nlines) 657 struct line *lines, int nlines)
646{ 658{
647 int i;
648 struct tty_driver *driver = alloc_tty_driver(nlines); 659 struct tty_driver *driver = alloc_tty_driver(nlines);
660 int err;
649 661
650 if (!driver) 662 if (!driver)
651 return NULL; 663 return -ENOMEM;
652 664
653 driver->driver_name = line_driver->name; 665 driver->driver_name = line_driver->name;
654 driver->name = line_driver->device_name; 666 driver->name = line_driver->device_name;
@@ -656,24 +668,21 @@ struct tty_driver *register_lines(struct line_driver *line_driver,
656 driver->minor_start = line_driver->minor_start; 668 driver->minor_start = line_driver->minor_start;
657 driver->type = line_driver->type; 669 driver->type = line_driver->type;
658 driver->subtype = line_driver->subtype; 670 driver->subtype = line_driver->subtype;
659 driver->flags = TTY_DRIVER_REAL_RAW; 671 driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
660 driver->init_termios = tty_std_termios; 672 driver->init_termios = tty_std_termios;
661 tty_set_operations(driver, ops); 673 tty_set_operations(driver, ops);
662 674
663 if (tty_register_driver(driver)) { 675 err = tty_register_driver(driver);
676 if (err) {
664 printk(KERN_ERR "register_lines : can't register %s driver\n", 677 printk(KERN_ERR "register_lines : can't register %s driver\n",
665 line_driver->name); 678 line_driver->name);
666 put_tty_driver(driver); 679 put_tty_driver(driver);
667 return NULL; 680 return err;
668 }
669
670 for(i = 0; i < nlines; i++) {
671 if (!lines[i].valid)
672 tty_unregister_device(driver, i);
673 } 681 }
674 682
683 line_driver->driver = driver;
675 mconsole_register_dev(&line_driver->mc); 684 mconsole_register_dev(&line_driver->mc);
676 return driver; 685 return 0;
677} 686}
678 687
679static DEFINE_SPINLOCK(winch_handler_lock); 688static DEFINE_SPINLOCK(winch_handler_lock);
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 471f477b271..e3f86065e04 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -15,7 +15,7 @@
15#include "chan_user.h" 15#include "chan_user.h"
16#include "mconsole_kern.h" 16#include "mconsole_kern.h"
17 17
18/* There's only one modifiable field in this - .mc.list */ 18/* There's only two modifiable fields in this - .mc.list and .driver */
19struct line_driver { 19struct line_driver {
20 const char *name; 20 const char *name;
21 const char *device_name; 21 const char *device_name;
@@ -28,6 +28,7 @@ struct line_driver {
28 const int write_irq; 28 const int write_irq;
29 const char *write_irq_name; 29 const char *write_irq_name;
30 struct mc_device mc; 30 struct mc_device mc;
31 struct tty_driver *driver;
31}; 32};
32 33
33struct line { 34struct line {
@@ -78,9 +79,9 @@ extern char *add_xterm_umid(char *base);
78extern int line_setup_irq(int fd, int input, int output, struct line *line, 79extern int line_setup_irq(int fd, int input, int output, struct line *line,
79 void *data); 80 void *data);
80extern void line_close_chan(struct line *line); 81extern void line_close_chan(struct line *line);
81extern struct tty_driver *register_lines(struct line_driver *line_driver, 82extern int register_lines(struct line_driver *line_driver,
82 const struct tty_operations *driver, 83 const struct tty_operations *driver,
83 struct line *lines, int nlines); 84 struct line *lines, int nlines);
84extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); 85extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
85extern void close_lines(struct line *lines, int nlines); 86extern void close_lines(struct line *lines, int nlines);
86 87
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 23cffd6d85a..6398a47d035 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -20,12 +20,6 @@
20 20
21static const int ssl_version = 1; 21static const int ssl_version = 1;
22 22
23/* Referenced only by tty_driver below - presumably it's locked correctly
24 * by the tty driver.
25 */
26
27static struct tty_driver *ssl_driver;
28
29#define NR_PORTS 64 23#define NR_PORTS 64
30 24
31static void ssl_announce(char *dev_name, int dev) 25static void ssl_announce(char *dev_name, int dev)
@@ -164,7 +158,7 @@ static void ssl_console_write(struct console *c, const char *string,
164static struct tty_driver *ssl_console_device(struct console *c, int *index) 158static struct tty_driver *ssl_console_device(struct console *c, int *index)
165{ 159{
166 *index = c->index; 160 *index = c->index;
167 return ssl_driver; 161 return driver.driver;
168} 162}
169 163
170static int ssl_console_setup(struct console *co, char *options) 164static int ssl_console_setup(struct console *co, char *options)
@@ -187,6 +181,7 @@ static struct console ssl_cons = {
187static int ssl_init(void) 181static int ssl_init(void)
188{ 182{
189 char *new_title; 183 char *new_title;
184 int err;
190 int i; 185 int i;
191 186
192 printk(KERN_INFO "Initializing software serial port version %d\n", 187 printk(KERN_INFO "Initializing software serial port version %d\n",
@@ -196,16 +191,16 @@ static int ssl_init(void)
196 char *s = conf[i]; 191 char *s = conf[i];
197 if (!s) 192 if (!s)
198 s = def_conf; 193 s = def_conf;
199 if (s && strcmp(s, "none") != 0) { 194 if (s && strcmp(s, "none") != 0)
200 serial_lines[i].init_str = s; 195 serial_lines[i].init_str = s;
201 serial_lines[i].valid = 1;
202 }
203 spin_lock_init(&serial_lines[i].lock); 196 spin_lock_init(&serial_lines[i].lock);
204 mutex_init(&serial_lines[i].count_lock); 197 mutex_init(&serial_lines[i].count_lock);
205 serial_lines[i].driver = &driver; 198 serial_lines[i].driver = &driver;
206 } 199 }
207 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, 200 err = register_lines(&driver, &ssl_ops, serial_lines,
208 ARRAY_SIZE(serial_lines)); 201 ARRAY_SIZE(serial_lines));
202 if (err)
203 return err;
209 204
210 new_title = add_xterm_umid(opts.xterm_title); 205 new_title = add_xterm_umid(opts.xterm_title);
211 if (new_title != NULL) 206 if (new_title != NULL)
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index f8d4325b28b..32bd040138f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -27,12 +27,6 @@
27 27
28#define MAX_TTYS (16) 28#define MAX_TTYS (16)
29 29
30/* Referenced only by tty_driver below - presumably it's locked correctly
31 * by the tty driver.
32 */
33
34static struct tty_driver *console_driver;
35
36static void stdio_announce(char *dev_name, int dev) 30static void stdio_announce(char *dev_name, int dev)
37{ 31{
38 printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, 32 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,
137static struct tty_driver *uml_console_device(struct console *c, int *index) 131static struct tty_driver *uml_console_device(struct console *c, int *index)
138{ 132{
139 *index = c->index; 133 *index = c->index;
140 return console_driver; 134 return driver.driver;
141} 135}
142 136
143static int uml_console_setup(struct console *co, char *options) 137static int uml_console_setup(struct console *co, char *options)
@@ -160,6 +154,7 @@ static struct console stdiocons = {
160static int stdio_init(void) 154static int stdio_init(void)
161{ 155{
162 char *new_title; 156 char *new_title;
157 int err;
163 int i; 158 int i;
164 159
165 for (i = 0; i < MAX_TTYS; i++) { 160 for (i = 0; i < MAX_TTYS; i++) {
@@ -168,18 +163,16 @@ static int stdio_init(void)
168 s = def_conf; 163 s = def_conf;
169 if (!s) 164 if (!s)
170 s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN; 165 s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN;
171 if (s && strcmp(s, "none") != 0) { 166 if (s && strcmp(s, "none") != 0)
172 vts[i].init_str = s; 167 vts[i].init_str = s;
173 vts[i].valid = 1;
174 }
175 spin_lock_init(&vts[i].lock); 168 spin_lock_init(&vts[i].lock);
176 mutex_init(&vts[i].count_lock); 169 mutex_init(&vts[i].count_lock);
177 vts[i].driver = &driver; 170 vts[i].driver = &driver;
178 } 171 }
179 console_driver = register_lines(&driver, &console_ops, vts, 172 err = register_lines(&driver, &console_ops, vts,
180 ARRAY_SIZE(vts)); 173 ARRAY_SIZE(vts));
181 if (console_driver == NULL) 174 if (err)
182 return -1; 175 return err;
183 printk(KERN_INFO "Initialized stdio console driver\n"); 176 printk(KERN_INFO "Initialized stdio console driver\n");
184 177
185 new_title = add_xterm_umid(opts.xterm_title); 178 new_title = add_xterm_umid(opts.xterm_title);