Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −14
Original line number Original line Diff line number Diff line
@@ -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,
		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,
			*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)
	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,
	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);
+5 −4
Original line number Original line Diff line number Diff line
@@ -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 {
	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,7 +79,7 @@ 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);
+6 −11
Original line number Original line Diff line number Diff line
@@ -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,
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 = {
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)
		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)
+6 −13
Original line number Original line Diff line number Diff line
@@ -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,
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 = {
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)
			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);