2019-08-25 09:49:16 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __LINE_H__
|
|
|
|
#define __LINE_H__
|
|
|
|
|
2012-10-08 02:27:32 +00:00
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/workqueue.h>
|
|
|
|
#include <linux/tty.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/mutex.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include "chan_user.h"
|
|
|
|
#include "mconsole_kern.h"
|
|
|
|
|
2011-09-09 23:45:42 +00:00
|
|
|
/* There's only two modifiable fields in this - .mc.list and .driver */
|
2005-04-16 22:20:36 +00:00
|
|
|
struct line_driver {
|
2007-02-10 09:44:08 +00:00
|
|
|
const char *name;
|
|
|
|
const char *device_name;
|
|
|
|
const short major;
|
|
|
|
const short minor_start;
|
|
|
|
const short type;
|
|
|
|
const short subtype;
|
|
|
|
const char *read_irq_name;
|
|
|
|
const char *write_irq_name;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct mc_device mc;
|
2011-09-09 23:45:42 +00:00
|
|
|
struct tty_driver *driver;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct line {
|
2012-06-04 11:35:26 +00:00
|
|
|
struct tty_port port;
|
2007-02-10 09:43:52 +00:00
|
|
|
int valid;
|
|
|
|
|
um: line: Use separate IRQs per line
Today, all possible serial lines (ssl*=) as well as all
possible consoles (con*=) each share a single interrupt
(with a fixed number) with others of the same type.
Now, if you have two lines, say ssl0 and ssl1, and one
of them is connected to an fd you cannot read (e.g. a
file), but the other gets a read interrupt, then both
of them get the interrupt since it's shared. Then, the
read() call will return EOF, since it's a file being
written and there's nothing to read (at least not at
the current offset, at the end).
Unfortunately, this is treated as a read error, and we
close this line, losing all the possible output.
It might be possible to work around this and make the
IRQ sharing work, however, now that we have dynamically
allocated IRQs that are easy to use, simply use that to
achieve separating between the events; then there's no
interrupt for that line and we never attempt the read
in the first place, thus not closing the line.
This manifested itself in the wifi hostap/hwsim tests
where the parallel script communicates via one serial
console and the kernel messages go to another (a file)
and sending data on the communication console caused
the kernel messages to stop flowing into the file.
Reported-by: Jouni Malinen <j@w1.fi>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-By: anton ivanov <anton.ivanov@cambridgegreys.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2022-05-06 13:46:12 +00:00
|
|
|
int read_irq, write_irq;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
char *init_str;
|
|
|
|
struct list_head chan_list;
|
2011-09-08 11:07:26 +00:00
|
|
|
struct chan *chan_in, *chan_out;
|
2007-02-10 09:43:52 +00:00
|
|
|
|
2005-05-01 15:58:56 +00:00
|
|
|
/*This lock is actually, mostly, local to*/
|
|
|
|
spinlock_t lock;
|
2007-02-10 09:43:52 +00:00
|
|
|
int throttled;
|
2005-05-01 15:58:56 +00:00
|
|
|
/* Yes, this is a real circular buffer.
|
|
|
|
* XXX: And this should become a struct kfifo!
|
|
|
|
*
|
|
|
|
* buffer points to a buffer allocated on demand, of length
|
|
|
|
* LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
|
2005-04-16 22:20:36 +00:00
|
|
|
char *buffer;
|
|
|
|
char *head;
|
|
|
|
char *tail;
|
2005-05-01 15:58:56 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
int sigio;
|
2006-12-07 04:31:36 +00:00
|
|
|
struct delayed_work task;
|
2006-09-27 08:50:33 +00:00
|
|
|
const struct line_driver *driver;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern void line_close(struct tty_struct *tty, struct file * filp);
|
2012-06-04 19:57:24 +00:00
|
|
|
extern int line_open(struct tty_struct *tty, struct file *filp);
|
|
|
|
extern int line_install(struct tty_driver *driver, struct tty_struct *tty,
|
|
|
|
struct line *line);
|
|
|
|
extern void line_cleanup(struct tty_struct *tty);
|
|
|
|
extern void line_hangup(struct tty_struct *tty);
|
2011-09-09 21:25:00 +00:00
|
|
|
extern int line_setup(char **conf, unsigned nlines, char **def,
|
|
|
|
char *init, char *name);
|
2006-01-06 08:18:50 +00:00
|
|
|
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
|
|
|
|
int len);
|
2021-05-05 09:19:19 +00:00
|
|
|
extern unsigned int line_chars_in_buffer(struct tty_struct *tty);
|
2005-05-01 15:58:56 +00:00
|
|
|
extern void line_flush_buffer(struct tty_struct *tty);
|
|
|
|
extern void line_flush_chars(struct tty_struct *tty);
|
2021-05-05 09:19:15 +00:00
|
|
|
extern unsigned int line_write_room(struct tty_struct *tty);
|
2006-01-06 08:18:58 +00:00
|
|
|
extern void line_throttle(struct tty_struct *tty);
|
|
|
|
extern void line_unthrottle(struct tty_struct *tty);
|
2005-05-01 15:58:56 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
extern char *add_xterm_umid(char *base);
|
[PATCH] uml: Simplify console opening/closing and irq registration
This patch simplifies the opening and closing of host console devices and the
registration and deregistration of IRQs. The intent is to make it obvious
that an IRQ can't exist without an open file descriptor.
chan_enable will now open the channel, and when both opening and IRQ
registration are desired, this should be used. Opening only is done for the
initial console, so that interface still needs to exist.
The free_irqs_later interface is now gone. It was intended to avoid freeing
an IRQ while it was being processed. It did this, but it didn't eliminate the
possiblity of free_irq being called from an interrupt, which is bad. In its
place is a list of irqs to be freed, which is processed by the signal handler
just before exiting. close_one_chan now disables irqs.
When a host device disappears, it is just closed, and that disables IRQs.
The device id registered with the IRQ is now the chan structure, not the tty.
This is because the interrupt arrives on a descriptor associated with the
channel. This caused equivalent changes in the arguments to line_timer_cb.
line_disable is gone since it is not used any more.
The count field in the line structure is gone. tty->count is used instead.
The complicated logic in sigio_handler with freeing IRQs when necessary and
making sure its idea of the next irq is correct is now much simpler. The irq
list can't be rearranged underneath it, so it is now a simple list walk.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-06 08:18:57 +00:00
|
|
|
extern int line_setup_irq(int fd, int input, int output, struct line *line,
|
|
|
|
void *data);
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void line_close_chan(struct line *line);
|
2011-09-09 23:45:42 +00:00
|
|
|
extern int register_lines(struct line_driver *line_driver,
|
|
|
|
const struct tty_operations *driver,
|
|
|
|
struct line *lines, int nlines);
|
2011-09-10 00:07:05 +00:00
|
|
|
extern int setup_one_line(struct line *lines, int n, char *init,
|
|
|
|
const struct chan_opts *opts, char **error_out);
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void close_lines(struct line *lines, int nlines);
|
2005-05-01 15:58:56 +00:00
|
|
|
|
2006-01-06 08:18:50 +00:00
|
|
|
extern int line_config(struct line *lines, unsigned int sizeof_lines,
|
2007-02-10 09:43:53 +00:00
|
|
|
char *str, const struct chan_opts *opts,
|
|
|
|
char **error_out);
|
2005-06-25 21:55:25 +00:00
|
|
|
extern int line_id(char **str, int *start_out, int *end_out);
|
2007-02-10 09:43:53 +00:00
|
|
|
extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
|
|
|
|
char **error_out);
|
2006-01-06 08:18:50 +00:00
|
|
|
extern int line_get_config(char *dev, struct line *lines,
|
|
|
|
unsigned int sizeof_lines, char *str,
|
2005-04-16 22:20:36 +00:00
|
|
|
int size, char **error_out);
|
|
|
|
|
|
|
|
#endif
|