diff options
Diffstat (limited to 'arch/um/drivers')
-rw-r--r-- | arch/um/drivers/line.c | 102 | ||||
-rw-r--r-- | arch/um/drivers/line.h | 6 | ||||
-rw-r--r-- | arch/um/drivers/ssl.c | 15 | ||||
-rw-r--r-- | arch/um/drivers/stdio_console.c | 20 |
4 files changed, 65 insertions, 78 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 131129aec249..95d5e7803bc7 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -296,43 +296,14 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | |||
296 | return err; | 296 | return err; |
297 | } | 297 | } |
298 | 298 | ||
299 | /* | 299 | static int line_activate(struct tty_port *port, struct tty_struct *tty) |
300 | * Normally, a driver like this can rely mostly on the tty layer | ||
301 | * locking, particularly when it comes to the driver structure. | ||
302 | * However, in this case, mconsole requests can come in "from the | ||
303 | * side", and race with opens and closes. | ||
304 | * | ||
305 | * mconsole config requests will want to be sure the device isn't in | ||
306 | * use, and get_config, open, and close will want a stable | ||
307 | * configuration. The checking and modification of the configuration | ||
308 | * is done under a spinlock. Checking whether the device is in use is | ||
309 | * line->tty->count > 1, also under the spinlock. | ||
310 | * | ||
311 | * line->count serves to decide whether the device should be enabled or | ||
312 | * disabled on the host. If it's equal to 0, then we are doing the | ||
313 | * first open or last close. Otherwise, open and close just return. | ||
314 | */ | ||
315 | |||
316 | int line_open(struct line *lines, struct tty_struct *tty) | ||
317 | { | 300 | { |
318 | struct line *line = &lines[tty->index]; | 301 | int ret; |
319 | int err = -ENODEV; | 302 | struct line *line = tty->driver_data; |
320 | |||
321 | mutex_lock(&line->count_lock); | ||
322 | if (!line->valid) | ||
323 | goto out_unlock; | ||
324 | |||
325 | err = 0; | ||
326 | if (line->port.count++) | ||
327 | goto out_unlock; | ||
328 | |||
329 | BUG_ON(tty->driver_data); | ||
330 | tty->driver_data = line; | ||
331 | tty_port_tty_set(&line->port, tty); | ||
332 | 303 | ||
333 | err = enable_chan(line); | 304 | ret = enable_chan(line); |
334 | if (err) /* line_close() will be called by our caller */ | 305 | if (ret) |
335 | goto out_unlock; | 306 | return ret; |
336 | 307 | ||
337 | if (!line->sigio) { | 308 | if (!line->sigio) { |
338 | chan_enable_winch(line->chan_out, tty); | 309 | chan_enable_winch(line->chan_out, tty); |
@@ -340,44 +311,60 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
340 | } | 311 | } |
341 | 312 | ||
342 | chan_window_size(line, &tty->winsize.ws_row, | 313 | chan_window_size(line, &tty->winsize.ws_row, |
343 | &tty->winsize.ws_col); | 314 | &tty->winsize.ws_col); |
344 | out_unlock: | 315 | |
345 | mutex_unlock(&line->count_lock); | 316 | return 0; |
346 | return err; | ||
347 | } | 317 | } |
348 | 318 | ||
349 | static void unregister_winch(struct tty_struct *tty); | 319 | static const struct tty_port_operations line_port_ops = { |
320 | .activate = line_activate, | ||
321 | }; | ||
350 | 322 | ||
351 | void line_close(struct tty_struct *tty, struct file * filp) | 323 | int line_open(struct tty_struct *tty, struct file *filp) |
352 | { | 324 | { |
353 | struct line *line = tty->driver_data; | 325 | struct line *line = tty->driver_data; |
354 | 326 | ||
355 | /* | 327 | return tty_port_open(&line->port, tty, filp); |
356 | * If line_open fails (and tty->driver_data is never set), | 328 | } |
357 | * tty_open will call line_close. So just return in this case. | ||
358 | */ | ||
359 | if (line == NULL) | ||
360 | return; | ||
361 | 329 | ||
362 | /* We ignore the error anyway! */ | 330 | int line_install(struct tty_driver *driver, struct tty_struct *tty, |
363 | flush_buffer(line); | 331 | struct line *line) |
332 | { | ||
333 | int ret; | ||
364 | 334 | ||
365 | mutex_lock(&line->count_lock); | 335 | ret = tty_standard_install(driver, tty); |
366 | BUG_ON(!line->valid); | 336 | if (ret) |
337 | return ret; | ||
338 | |||
339 | tty->driver_data = line; | ||
367 | 340 | ||
368 | if (--line->port.count) | 341 | return 0; |
369 | goto out_unlock; | 342 | } |
343 | |||
344 | static void unregister_winch(struct tty_struct *tty); | ||
370 | 345 | ||
371 | tty_port_tty_set(&line->port, NULL); | 346 | void line_cleanup(struct tty_struct *tty) |
372 | tty->driver_data = NULL; | 347 | { |
348 | struct line *line = tty->driver_data; | ||
373 | 349 | ||
374 | if (line->sigio) { | 350 | if (line->sigio) { |
375 | unregister_winch(tty); | 351 | unregister_winch(tty); |
376 | line->sigio = 0; | 352 | line->sigio = 0; |
377 | } | 353 | } |
354 | } | ||
378 | 355 | ||
379 | out_unlock: | 356 | void line_close(struct tty_struct *tty, struct file * filp) |
380 | mutex_unlock(&line->count_lock); | 357 | { |
358 | struct line *line = tty->driver_data; | ||
359 | |||
360 | tty_port_close(&line->port, tty, filp); | ||
361 | } | ||
362 | |||
363 | void line_hangup(struct tty_struct *tty) | ||
364 | { | ||
365 | struct line *line = tty->driver_data; | ||
366 | |||
367 | tty_port_hangup(&line->port); | ||
381 | } | 368 | } |
382 | 369 | ||
383 | void close_lines(struct line *lines, int nlines) | 370 | void close_lines(struct line *lines, int nlines) |
@@ -589,6 +576,7 @@ int register_lines(struct line_driver *line_driver, | |||
589 | 576 | ||
590 | for (i = 0; i < nlines; i++) { | 577 | for (i = 0; i < nlines; i++) { |
591 | tty_port_init(&lines[i].port); | 578 | tty_port_init(&lines[i].port); |
579 | lines[i].port.ops = &line_port_ops; | ||
592 | spin_lock_init(&lines[i].lock); | 580 | spin_lock_init(&lines[i].lock); |
593 | mutex_init(&lines[i].count_lock); | 581 | mutex_init(&lines[i].count_lock); |
594 | lines[i].driver = line_driver; | 582 | lines[i].driver = line_driver; |
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h index 6c3b252bf480..ad00f3e11ecc 100644 --- a/arch/um/drivers/line.h +++ b/arch/um/drivers/line.h | |||
@@ -58,7 +58,11 @@ struct line { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | extern void line_close(struct tty_struct *tty, struct file * filp); | 60 | extern void line_close(struct tty_struct *tty, struct file * filp); |
61 | extern int line_open(struct line *lines, struct tty_struct *tty); | 61 | extern int line_open(struct tty_struct *tty, struct file *filp); |
62 | extern int line_install(struct tty_driver *driver, struct tty_struct *tty, | ||
63 | struct line *line); | ||
64 | extern void line_cleanup(struct tty_struct *tty); | ||
65 | extern void line_hangup(struct tty_struct *tty); | ||
62 | extern int line_setup(char **conf, unsigned nlines, char **def, | 66 | extern int line_setup(char **conf, unsigned nlines, char **def, |
63 | char *init, char *name); | 67 | char *init, char *name); |
64 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, | 68 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index cba95d959af1..7e86f0070123 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
@@ -87,19 +87,13 @@ static int ssl_remove(int n, char **error_out) | |||
87 | error_out); | 87 | error_out); |
88 | } | 88 | } |
89 | 89 | ||
90 | static int ssl_open(struct tty_struct *tty, struct file *filp) | 90 | static int ssl_install(struct tty_driver *driver, struct tty_struct *tty) |
91 | { | 91 | { |
92 | int err = line_open(serial_lines, tty); | 92 | return line_install(driver, tty, &serial_lines[tty->index]); |
93 | |||
94 | if (err) | ||
95 | printk(KERN_ERR "Failed to open serial line %d, err = %d\n", | ||
96 | tty->index, err); | ||
97 | |||
98 | return err; | ||
99 | } | 93 | } |
100 | 94 | ||
101 | static const struct tty_operations ssl_ops = { | 95 | static const struct tty_operations ssl_ops = { |
102 | .open = ssl_open, | 96 | .open = line_open, |
103 | .close = line_close, | 97 | .close = line_close, |
104 | .write = line_write, | 98 | .write = line_write, |
105 | .put_char = line_put_char, | 99 | .put_char = line_put_char, |
@@ -110,6 +104,9 @@ static const struct tty_operations ssl_ops = { | |||
110 | .set_termios = line_set_termios, | 104 | .set_termios = line_set_termios, |
111 | .throttle = line_throttle, | 105 | .throttle = line_throttle, |
112 | .unthrottle = line_unthrottle, | 106 | .unthrottle = line_unthrottle, |
107 | .install = ssl_install, | ||
108 | .cleanup = line_cleanup, | ||
109 | .hangup = line_hangup, | ||
113 | }; | 110 | }; |
114 | 111 | ||
115 | /* Changed by ssl_init and referenced by ssl_exit, which are both serialized | 112 | /* Changed by ssl_init and referenced by ssl_exit, which are both serialized |
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 5cefdba2e3bf..929b99a261f3 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
@@ -89,21 +89,17 @@ static int con_remove(int n, char **error_out) | |||
89 | return line_remove(vts, ARRAY_SIZE(vts), n, error_out); | 89 | return line_remove(vts, ARRAY_SIZE(vts), n, error_out); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int con_open(struct tty_struct *tty, struct file *filp) | ||
93 | { | ||
94 | int err = line_open(vts, tty); | ||
95 | if (err) | ||
96 | printk(KERN_ERR "Failed to open console %d, err = %d\n", | ||
97 | tty->index, err); | ||
98 | |||
99 | return err; | ||
100 | } | ||
101 | |||
102 | /* Set in an initcall, checked in an exitcall */ | 92 | /* Set in an initcall, checked in an exitcall */ |
103 | static int con_init_done = 0; | 93 | static int con_init_done = 0; |
104 | 94 | ||
95 | static int con_install(struct tty_driver *driver, struct tty_struct *tty) | ||
96 | { | ||
97 | return line_install(driver, tty, &vts[tty->index]); | ||
98 | } | ||
99 | |||
105 | static const struct tty_operations console_ops = { | 100 | static const struct tty_operations console_ops = { |
106 | .open = con_open, | 101 | .open = line_open, |
102 | .install = con_install, | ||
107 | .close = line_close, | 103 | .close = line_close, |
108 | .write = line_write, | 104 | .write = line_write, |
109 | .put_char = line_put_char, | 105 | .put_char = line_put_char, |
@@ -114,6 +110,8 @@ static const struct tty_operations console_ops = { | |||
114 | .set_termios = line_set_termios, | 110 | .set_termios = line_set_termios, |
115 | .throttle = line_throttle, | 111 | .throttle = line_throttle, |
116 | .unthrottle = line_unthrottle, | 112 | .unthrottle = line_unthrottle, |
113 | .cleanup = line_cleanup, | ||
114 | .hangup = line_hangup, | ||
117 | }; | 115 | }; |
118 | 116 | ||
119 | static void uml_console_write(struct console *console, const char *string, | 117 | static void uml_console_write(struct console *console, const char *string, |