From c0b79a90b1556a7e51d7a49a655eb60306f6258d Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Thu, 22 Sep 2011 16:58:46 +0800 Subject: um: irq: Remove IRQF_DISABLED Since commit [e58aa3d2: genirq: Run irq handlers with interrupts disabled], We run all interrupt handlers with interrupts disabled and we even check and yell when an interrupt handler returns with interrupts enabled (see commit [b738a50a: genirq: Warn when handler enables interrupts]). So now this flag is a NOOP and can be removed. Signed-off-by: Yong Zhang Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index c1cf2206b84b..ac9bcfbbeee1 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -347,8 +347,8 @@ static irqreturn_t line_write_interrupt(int irq, void *data) int err; /* - * Interrupts are disabled here because we registered the interrupt with - * IRQF_DISABLED (see line_setup_irq). + * Interrupts are disabled here because genirq keep irqs disabled when + * calling the action handler. */ spin_lock(&line->lock); @@ -371,7 +371,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) int line_setup_irq(int fd, int input, int output, struct line *line, void *data) { const struct line_driver *driver = line->driver; - int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; + int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, @@ -807,7 +807,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, .stack = stack }); if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, + IRQF_SHARED | IRQF_SAMPLE_RANDOM, "winch", winch) < 0) { printk(KERN_ERR "register_winch_irq - failed to register " "IRQ\n"); -- cgit v1.2.3 From da645f3be912a377ada97268e36360b0a4389ab0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Sep 2011 20:34:52 -0400 Subject: um: switch line_remove() to setup_one_line() Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index ac9bcfbbeee1..08c5fba6db84 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -640,14 +640,11 @@ int line_id(char **str, int *start_out, int *end_out) int line_remove(struct line *lines, unsigned int num, int n, char **error_out) { - int err; - char config[sizeof("conxxxx=none\0")]; - - sprintf(config, "%d=none", n); - err = line_setup(lines, num, config, error_out); - if (err >= 0) - err = 0; - return err; + if (n >= num) { + *error_out = "Device number out of range"; + return -EINVAL; + } + return setup_one_line(lines, n, "none", INIT_ONE, error_out); } struct tty_driver *register_lines(struct line_driver *line_driver, -- cgit v1.2.3 From fe9a6b002988372406baf5aeefc046677782365e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Sep 2011 20:44:06 -0400 Subject: um: switch line_config() to setup_one_line() Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 08c5fba6db84..b0022cf4efbb 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -572,22 +572,32 @@ int line_config(struct line *lines, unsigned int num, char *str, { struct line *line; char *new; - int n; + char *end; + int n, err; if (*str == '=') { *error_out = "Can't configure all devices from mconsole"; return -EINVAL; } - new = kstrdup(str, GFP_KERNEL); + n = simple_strtoul(str, &end, 0); + if (*end++ != '=') { + *error_out = "Couldn't parse device number"; + return -EINVAL; + } + if (n >= num) { + *error_out = "Device number out of range"; + return -EINVAL; + } + + new = kstrdup(end, GFP_KERNEL); if (new == NULL) { *error_out = "Failed to allocate memory"; return -ENOMEM; } - n = line_setup(lines, num, new, error_out); - if (n < 0) - return n; - + err = setup_one_line(lines, n, new, INIT_ONE, error_out); + if (err) + return err; line = &lines[n]; return parse_chan_pair(line->init_str, line, n, opts, error_out); } -- cgit v1.2.3 From 43574c1afea4f798592c03cf4d4ecea4fd0a8416 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 17:25:00 -0400 Subject: um: get rid of the init_prio mess make line_setup() act on a separate array of conf strings + default conf, have lines array initialized explicitly by that data, bury LINE_INIT() macro from hell. Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 69 ++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 41 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index b0022cf4efbb..3eea99e98a11 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -489,7 +489,7 @@ void close_lines(struct line *lines, int nlines) close_chan(&lines[i].chan_list, 0); } -static int setup_one_line(struct line *lines, int n, char *init, int init_prio, +static int setup_one_line(struct line *lines, int n, char *init, char **error_out) { struct line *line = &lines[n]; @@ -502,14 +502,11 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, goto out; } - if (line->init_pri <= init_prio) { - line->init_pri = init_prio; - if (!strcmp(init, "none")) - line->valid = 0; - else { - line->init_str = init; - line->valid = 1; - } + if (!strcmp(init, "none")) + line->valid = 0; + else { + line->init_str = init; + line->valid = 1; } err = 0; out: @@ -524,47 +521,37 @@ out: * @error_out is an error string in the case of failure; */ -int line_setup(struct line *lines, unsigned int num, char *init, - char **error_out) +int line_setup(char **conf, unsigned int num, char **def, + char *init, char *name) { - int i, n, err; - char *end; + char *error; if (*init == '=') { /* * We said con=/ssl= instead of con#=, so we are configuring all * consoles at once. */ - n = -1; - } - else { - n = simple_strtoul(init, &end, 0); + *def = init + 1; + } else { + char *end; + unsigned n = simple_strtoul(init, &end, 0); + if (*end != '=') { - *error_out = "Couldn't parse device number"; - return -EINVAL; + error = "Couldn't parse device number"; + goto out; } - init = end; - } - init++; - - if (n >= (signed int) num) { - *error_out = "Device number out of range"; - return -EINVAL; - } - else if (n >= 0) { - err = setup_one_line(lines, n, init, INIT_ONE, error_out); - if (err) - return err; - } - else { - for(i = 0; i < num; i++) { - err = setup_one_line(lines, i, init, INIT_ALL, - error_out); - if (err) - return err; + if (n >= num) { + error = "Device number out of range"; + goto out; } + conf[n] = end + 1; } - return n == -1 ? num : n; + return 0; + +out: + printk(KERN_ERR "Failed to set up %s with " + "configuration string \"%s\" : %s\n", name, init, error); + return -EINVAL; } int line_config(struct line *lines, unsigned int num, char *str, @@ -595,7 +582,7 @@ int line_config(struct line *lines, unsigned int num, char *str, *error_out = "Failed to allocate memory"; return -ENOMEM; } - err = setup_one_line(lines, n, new, INIT_ONE, error_out); + err = setup_one_line(lines, n, new, error_out); if (err) return err; line = &lines[n]; @@ -654,7 +641,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) *error_out = "Device number out of range"; return -EINVAL; } - return setup_one_line(lines, n, "none", INIT_ONE, error_out); + return setup_one_line(lines, n, "none", error_out); } struct tty_driver *register_lines(struct line_driver *line_driver, -- cgit v1.2.3 From d8c215adbf3901aa7d00a0f17f08d77be689f838 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 17:36:37 -0400 Subject: um: convert count_lock to mutex, fix a race in line_open() If two processes are opening the same line, the second to get into line_open() will decide that it doesn't need to do anything (correctly) or wait for anything. The latter, unfortunately, is incorrect - the first opener might not be through yet. We need to have exclusion covering the entire line_init(), including the blocking parts. Moreover, the next patch will need to widen the exclusion on mconsole side of things, also including the blocking bits, so let's just convert that sucker to mutex... Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 3eea99e98a11..dc7e216df6a5 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -409,7 +409,7 @@ int line_open(struct line *lines, struct tty_struct *tty) struct line *line = &lines[tty->index]; int err = -ENODEV; - spin_lock(&line->count_lock); + mutex_lock(&line->count_lock); if (!line->valid) goto out_unlock; @@ -421,10 +421,9 @@ int line_open(struct line *lines, struct tty_struct *tty) tty->driver_data = line; line->tty = tty; - spin_unlock(&line->count_lock); err = enable_chan(line); if (err) /* line_close() will be called by our caller */ - return err; + goto out_unlock; INIT_DELAYED_WORK(&line->task, line_timer_cb); @@ -435,11 +434,8 @@ int line_open(struct line *lines, struct tty_struct *tty) chan_window_size(&line->chan_list, &tty->winsize.ws_row, &tty->winsize.ws_col); - - return 0; - out_unlock: - spin_unlock(&line->count_lock); + mutex_unlock(&line->count_lock); return err; } @@ -459,7 +455,7 @@ void line_close(struct tty_struct *tty, struct file * filp) /* We ignore the error anyway! */ flush_buffer(line); - spin_lock(&line->count_lock); + mutex_lock(&line->count_lock); BUG_ON(!line->valid); if (--line->count) @@ -468,17 +464,13 @@ void line_close(struct tty_struct *tty, struct file * filp) line->tty = NULL; tty->driver_data = NULL; - spin_unlock(&line->count_lock); - if (line->sigio) { unregister_winch(tty); line->sigio = 0; } - return; - out_unlock: - spin_unlock(&line->count_lock); + mutex_unlock(&line->count_lock); } void close_lines(struct line *lines, int nlines) @@ -495,7 +487,7 @@ static int setup_one_line(struct line *lines, int n, char *init, struct line *line = &lines[n]; int err = -EINVAL; - spin_lock(&line->count_lock); + mutex_lock(&line->count_lock); if (line->count) { *error_out = "Device is already open"; @@ -510,7 +502,7 @@ static int setup_one_line(struct line *lines, int n, char *init, } err = 0; out: - spin_unlock(&line->count_lock); + mutex_unlock(&line->count_lock); return err; } @@ -609,13 +601,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, line = &lines[dev]; - spin_lock(&line->count_lock); + mutex_lock(&line->count_lock); if (!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); else if (line->tty == NULL) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); - spin_unlock(&line->count_lock); + mutex_unlock(&line->count_lock); return n; } -- cgit v1.2.3 From 31efcebb7d7196adcee73027f513d7c0bf572b47 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 19:14:02 -0400 Subject: um: fix races between line_open() and line_config() Pull parse_chan_pair() call into setup_one_line(), under the mutex. We really don't want open() to succeed before parse_chan_pair() had been done (or after it has failed, BTW). We also want "remove con" to free irqs, etc., same as "config con=none". Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 54 ++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index dc7e216df6a5..1a8d6591c204 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -482,7 +482,7 @@ void close_lines(struct line *lines, int nlines) } static int setup_one_line(struct line *lines, int n, char *init, - char **error_out) + const struct chan_opts *opts, char **error_out) { struct line *line = &lines[n]; int err = -EINVAL; @@ -494,13 +494,28 @@ static int setup_one_line(struct line *lines, int n, char *init, goto out; } - if (!strcmp(init, "none")) - line->valid = 0; - else { - line->init_str = init; + if (!strcmp(init, "none")) { + if (line->valid) { + line->valid = 0; + kfree(line->init_str); + parse_chan_pair(NULL, line, n, opts, error_out); + err = 0; + } + } else { + char *new = kstrdup(init, GFP_KERNEL); + if (!new) { + *error_out = "Failed to allocate memory"; + return -ENOMEM; + } + line->init_str = new; line->valid = 1; + err = parse_chan_pair(new, line, n, opts, error_out); + if (err) { + line->init_str = NULL; + line->valid = 0; + kfree(new); + } } - err = 0; out: mutex_unlock(&line->count_lock); return err; @@ -549,10 +564,8 @@ out: int line_config(struct line *lines, unsigned int num, char *str, const struct chan_opts *opts, char **error_out) { - struct line *line; - char *new; char *end; - int n, err; + int n; if (*str == '=') { *error_out = "Can't configure all devices from mconsole"; @@ -569,16 +582,7 @@ int line_config(struct line *lines, unsigned int num, char *str, return -EINVAL; } - new = kstrdup(end, GFP_KERNEL); - if (new == NULL) { - *error_out = "Failed to allocate memory"; - return -ENOMEM; - } - err = setup_one_line(lines, n, new, error_out); - if (err) - return err; - line = &lines[n]; - return parse_chan_pair(line->init_str, line, n, opts, error_out); + return setup_one_line(lines, n, end, opts, error_out); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -633,7 +637,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) *error_out = "Device number out of range"; return -EINVAL; } - return setup_one_line(lines, n, "none", error_out); + return setup_one_line(lines, n, "none", NULL, error_out); } struct tty_driver *register_lines(struct line_driver *line_driver, @@ -688,15 +692,9 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) if (line->init_str == NULL) continue; - line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if (line->init_str == NULL) - printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); - - if (parse_chan_pair(line->init_str, line, i, opts, &error)) { - printk(KERN_ERR "parse_chan_pair failed for " + if (setup_one_line(lines, i, line->init_str, opts, &error)) + printk(KERN_ERR "setup_one_line failed for " "device %d : %s\n", i, error); - line->valid = 0; - } } } -- cgit v1.2.3 From cfe6b7c79daa0efa27f474f1fe2a88fd7af5cc47 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 19:45:42 -0400 Subject: 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 Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'arch/um/drivers/line.c') 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); -- cgit v1.2.3 From 04292b2cf8f02a33cfc1054c0c51aa8c77731813 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 20:07:05 -0400 Subject: um: get rid of lines_init() move config-independent parts of initialization into register_lines(), call setup_one_line() after it instead of abusing ->init_str. Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 015209a98815..002d4a968ae6 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -481,8 +481,8 @@ void close_lines(struct line *lines, int nlines) close_chan(&lines[i].chan_list, 0); } -static int setup_one_line(struct line *lines, int n, char *init, - const struct chan_opts *opts, char **error_out) +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; @@ -658,6 +658,7 @@ int register_lines(struct line_driver *line_driver, { struct tty_driver *driver = alloc_tty_driver(nlines); int err; + int i; if (!driver) return -ENOMEM; @@ -670,6 +671,13 @@ int register_lines(struct line_driver *line_driver, driver->subtype = line_driver->subtype; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->init_termios = tty_std_termios; + + for (i = 0; i < nlines; i++) { + spin_lock_init(&lines[i].lock); + mutex_init(&lines[i].count_lock); + lines[i].driver = line_driver; + INIT_LIST_HEAD(&lines[i].chan_list); + } tty_set_operations(driver, ops); err = tty_register_driver(driver); @@ -688,25 +696,6 @@ int register_lines(struct line_driver *line_driver, static DEFINE_SPINLOCK(winch_handler_lock); static LIST_HEAD(winch_handlers); -void lines_init(struct line *lines, int nlines, struct chan_opts *opts) -{ - struct line *line; - char *error; - int i; - - for(i = 0; i < nlines; i++) { - line = &lines[i]; - INIT_LIST_HEAD(&line->chan_list); - - if (line->init_str == NULL) - continue; - - if (setup_one_line(lines, i, line->init_str, opts, &error)) - printk(KERN_ERR "setup_one_line failed for " - "device %d : %s\n", i, error); - } -} - struct winch { struct list_head list; int fd; -- cgit v1.2.3 From c8e2876fc8adaf9539f051fcda5d551308e8a0f8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 20:08:48 -0400 Subject: um: finally kill ->init_str leaks now we can do that... Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 002d4a968ae6..9ffade87a8cf 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -509,8 +509,10 @@ int setup_one_line(struct line *lines, int n, char *init, *error_out = "Failed to allocate memory"; return -ENOMEM; } - if (line->valid) + if (line->valid) { tty_unregister_device(driver, n); + kfree(line->init_str); + } line->init_str = new; line->valid = 1; err = parse_chan_pair(new, line, n, opts, error_out); -- cgit v1.2.3 From bed5e39c56f3fe792e336cfa2670001d78f1d44c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Sep 2011 10:49:34 -0400 Subject: um: switch users of ->chan_list to ->chan_{in,out} (easy cases) Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 9ffade87a8cf..c1aa89cefaec 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -21,7 +21,7 @@ static irqreturn_t line_interrupt(int irq, void *data) struct line *line = chan->line; if (line) - chan_interrupt(&line->chan_list, &line->task, line->tty, irq); + chan_interrupt(line, &line->task, line->tty, irq); return IRQ_HANDLED; } @@ -30,7 +30,7 @@ static void line_timer_cb(struct work_struct *work) struct line *line = container_of(work, struct line, task.work); if (!line->throttled) - chan_interrupt(&line->chan_list, &line->task, line->tty, + chan_interrupt(line, &line->task, line->tty, line->driver->read_irq); } @@ -145,7 +145,7 @@ static int flush_buffer(struct line *line) /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ count = line->buffer + LINE_BUFSIZE - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(line->chan_out, line->head, count, line->driver->write_irq); if (n < 0) return n; @@ -162,7 +162,7 @@ static int flush_buffer(struct line *line) } count = line->tail - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(line->chan_out, line->head, count, line->driver->write_irq); if (n < 0) @@ -206,7 +206,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) if (line->head != line->tail) ret = buffer_data(line, buf, len); else { - n = write_chan(&line->chan_list, buf, len, + n = write_chan(line->chan_out, buf, len, line->driver->write_irq); if (n < 0) { ret = n; @@ -318,7 +318,7 @@ void line_throttle(struct tty_struct *tty) { struct line *line = tty->driver_data; - deactivate_chan(&line->chan_list, line->driver->read_irq); + deactivate_chan(line->chan_in, line->driver->read_irq); line->throttled = 1; } @@ -327,7 +327,7 @@ void line_unthrottle(struct tty_struct *tty) struct line *line = tty->driver_data; line->throttled = 0; - chan_interrupt(&line->chan_list, &line->task, tty, + chan_interrupt(line, &line->task, tty, line->driver->read_irq); /* @@ -336,7 +336,7 @@ void line_unthrottle(struct tty_struct *tty) * again and we shouldn't turn the interrupt back on. */ if (!line->throttled) - reactivate_chan(&line->chan_list, line->driver->read_irq); + reactivate_chan(line->chan_in, line->driver->read_irq); } static irqreturn_t line_write_interrupt(int irq, void *data) @@ -428,11 +428,11 @@ int line_open(struct line *lines, struct tty_struct *tty) INIT_DELAYED_WORK(&line->task, line_timer_cb); if (!line->sigio) { - chan_enable_winch(&line->chan_list, tty); + chan_enable_winch(line->chan_out, tty); line->sigio = 1; } - chan_window_size(&line->chan_list, &tty->winsize.ws_row, + chan_window_size(line, &tty->winsize.ws_row, &tty->winsize.ws_col); out_unlock: mutex_unlock(&line->count_lock); @@ -624,7 +624,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, CONFIG_CHUNK(str, size, n, "none", 1); else if (line->tty == NULL) CONFIG_CHUNK(str, size, n, line->init_str, 1); - else n = chan_config_string(&line->chan_list, str, size, error_out); + else n = chan_config_string(line, str, size, error_out); mutex_unlock(&line->count_lock); return n; @@ -761,7 +761,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) if (tty != NULL) { line = tty->driver_data; if (line != NULL) { - chan_window_size(&line->chan_list, &tty->winsize.ws_row, + chan_window_size(line, &tty->winsize.ws_row, &tty->winsize.ws_col); kill_pgrp(tty->pgrp, SIGWINCH, 1); } -- cgit v1.2.3 From 5eaa3411a80fe50b3a0333389e0e259c580869e9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Sep 2011 20:20:52 -0400 Subject: um: line->have_irq is never checked... looks like a half-arsed duplicate of line->enabled Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index c1aa89cefaec..08f63930da8b 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -383,7 +383,6 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, line_write_interrupt, flags, driver->write_irq_name, data); - line->have_irq = 1; return err; } -- cgit v1.2.3 From 0fcd719934cd3521ae4a977f454e75e2be60b7ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 10 Sep 2011 08:17:04 -0400 Subject: um: race fix: initialize delayed_work *before* registering IRQ ... since chan_interrupt() might schedule it if there's too much incoming data. Kill task argument of chan_interrupt(), while we are at it - it's always &line->task. Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 08f63930da8b..9299b8a2d171 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -21,19 +21,10 @@ static irqreturn_t line_interrupt(int irq, void *data) struct line *line = chan->line; if (line) - chan_interrupt(line, &line->task, line->tty, irq); + chan_interrupt(line, line->tty, irq); return IRQ_HANDLED; } -static void line_timer_cb(struct work_struct *work) -{ - struct line *line = container_of(work, struct line, task.work); - - if (!line->throttled) - chan_interrupt(line, &line->task, line->tty, - line->driver->read_irq); -} - /* * Returns the free space inside the ring buffer of this line. * @@ -327,8 +318,7 @@ void line_unthrottle(struct tty_struct *tty) struct line *line = tty->driver_data; line->throttled = 0; - chan_interrupt(line, &line->task, tty, - line->driver->read_irq); + chan_interrupt(line, tty, line->driver->read_irq); /* * Maybe there is enough stuff pending that calling the interrupt @@ -424,8 +414,6 @@ int line_open(struct line *lines, struct tty_struct *tty) if (err) /* line_close() will be called by our caller */ goto out_unlock; - INIT_DELAYED_WORK(&line->task, line_timer_cb); - if (!line->sigio) { chan_enable_winch(line->chan_out, tty); line->sigio = 1; -- cgit v1.2.3 From 10c890c0a303070652f5374ea31a0b29350d14d9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 10 Sep 2011 08:39:18 -0400 Subject: um: switch close_chan() to struct line ... and switch chan_interrupt() to directly calling close_one_chan(), so we can lose delay_free_irq argument of close_chan() as well. Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 9299b8a2d171..4a3c853689a3 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -465,7 +465,7 @@ void close_lines(struct line *lines, int nlines) int i; for(i = 0; i < nlines; i++) - close_chan(&lines[i].chan_list, 0); + close_chan(&lines[i]); } int setup_one_line(struct line *lines, int n, char *init, -- cgit v1.2.3 From 199eebbae45791af0f37184dd495f16a6cf5c34a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 Feb 2012 03:05:32 -0500 Subject: um: deadlock in line_write_interrupt() Signed-off-by: Al Viro Signed-off-by: Richard Weinberger --- arch/um/drivers/line.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/drivers/line.c') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 4a3c853689a3..4ab0d9c0911c 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -344,6 +344,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) spin_lock(&line->lock); err = flush_buffer(line); if (err == 0) { + spin_unlock(&line->lock); return IRQ_NONE; } else if (err < 0) { line->head = line->buffer; -- cgit v1.2.3