Skip to content

Commit bf867a0

Browse files
jmberg-intelgregkh
authored andcommitted
um: line: Use separate IRQs per line
[ Upstream commit d5a9597 ] 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 <[email protected]> Signed-off-by: Johannes Berg <[email protected]> Acked-By: anton ivanov <[email protected]> Signed-off-by: Richard Weinberger <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 11b9a1e commit bf867a0

File tree

6 files changed

+29
-33
lines changed

6 files changed

+29
-33
lines changed

arch/um/drivers/chan_kern.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ static void line_timer_cb(struct work_struct *work)
133133
struct line *line = container_of(work, struct line, task.work);
134134

135135
if (!line->throttled)
136-
chan_interrupt(line, line->driver->read_irq);
136+
chan_interrupt(line, line->read_irq);
137137
}
138138

139139
int enable_chan(struct line *line)
@@ -195,9 +195,9 @@ void free_irqs(void)
195195
chan = list_entry(ele, struct chan, free_list);
196196

197197
if (chan->input && chan->enabled)
198-
um_free_irq(chan->line->driver->read_irq, chan);
198+
um_free_irq(chan->line->read_irq, chan);
199199
if (chan->output && chan->enabled)
200-
um_free_irq(chan->line->driver->write_irq, chan);
200+
um_free_irq(chan->line->write_irq, chan);
201201
chan->enabled = 0;
202202
}
203203
}
@@ -215,9 +215,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
215215
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
216216
} else {
217217
if (chan->input && chan->enabled)
218-
um_free_irq(chan->line->driver->read_irq, chan);
218+
um_free_irq(chan->line->read_irq, chan);
219219
if (chan->output && chan->enabled)
220-
um_free_irq(chan->line->driver->write_irq, chan);
220+
um_free_irq(chan->line->write_irq, chan);
221221
chan->enabled = 0;
222222
}
223223
if (chan->ops->close != NULL)

arch/um/drivers/line.c

+13-9
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ static int flush_buffer(struct line *line)
139139
count = line->buffer + LINE_BUFSIZE - line->head;
140140

141141
n = write_chan(line->chan_out, line->head, count,
142-
line->driver->write_irq);
142+
line->write_irq);
143143
if (n < 0)
144144
return n;
145145
if (n == count) {
@@ -156,7 +156,7 @@ static int flush_buffer(struct line *line)
156156

157157
count = line->tail - line->head;
158158
n = write_chan(line->chan_out, line->head, count,
159-
line->driver->write_irq);
159+
line->write_irq);
160160

161161
if (n < 0)
162162
return n;
@@ -195,7 +195,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
195195
ret = buffer_data(line, buf, len);
196196
else {
197197
n = write_chan(line->chan_out, buf, len,
198-
line->driver->write_irq);
198+
line->write_irq);
199199
if (n < 0) {
200200
ret = n;
201201
goto out_up;
@@ -215,7 +215,7 @@ void line_throttle(struct tty_struct *tty)
215215
{
216216
struct line *line = tty->driver_data;
217217

218-
deactivate_chan(line->chan_in, line->driver->read_irq);
218+
deactivate_chan(line->chan_in, line->read_irq);
219219
line->throttled = 1;
220220
}
221221

@@ -224,7 +224,7 @@ void line_unthrottle(struct tty_struct *tty)
224224
struct line *line = tty->driver_data;
225225

226226
line->throttled = 0;
227-
chan_interrupt(line, line->driver->read_irq);
227+
chan_interrupt(line, line->read_irq);
228228
}
229229

230230
static irqreturn_t line_write_interrupt(int irq, void *data)
@@ -260,19 +260,23 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
260260
int err;
261261

262262
if (input) {
263-
err = um_request_irq(driver->read_irq, fd, IRQ_READ,
264-
line_interrupt, IRQF_SHARED,
263+
err = um_request_irq(UM_IRQ_ALLOC, fd, IRQ_READ,
264+
line_interrupt, 0,
265265
driver->read_irq_name, data);
266266
if (err < 0)
267267
return err;
268+
269+
line->read_irq = err;
268270
}
269271

270272
if (output) {
271-
err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
272-
line_write_interrupt, IRQF_SHARED,
273+
err = um_request_irq(UM_IRQ_ALLOC, fd, IRQ_WRITE,
274+
line_write_interrupt, 0,
273275
driver->write_irq_name, data);
274276
if (err < 0)
275277
return err;
278+
279+
line->write_irq = err;
276280
}
277281

278282
return 0;

arch/um/drivers/line.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ struct line_driver {
2323
const short minor_start;
2424
const short type;
2525
const short subtype;
26-
const int read_irq;
2726
const char *read_irq_name;
28-
const int write_irq;
2927
const char *write_irq_name;
3028
struct mc_device mc;
3129
struct tty_driver *driver;
@@ -35,6 +33,8 @@ struct line {
3533
struct tty_port port;
3634
int valid;
3735

36+
int read_irq, write_irq;
37+
3838
char *init_str;
3939
struct list_head chan_list;
4040
struct chan *chan_in, *chan_out;

arch/um/drivers/ssl.c

-2
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ static struct line_driver driver = {
4747
.minor_start = 64,
4848
.type = TTY_DRIVER_TYPE_SERIAL,
4949
.subtype = 0,
50-
.read_irq = SSL_IRQ,
5150
.read_irq_name = "ssl",
52-
.write_irq = SSL_WRITE_IRQ,
5351
.write_irq_name = "ssl-write",
5452
.mc = {
5553
.list = LIST_HEAD_INIT(driver.mc.list),

arch/um/drivers/stdio_console.c

-2
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,7 @@ static struct line_driver driver = {
5353
.minor_start = 0,
5454
.type = TTY_DRIVER_TYPE_CONSOLE,
5555
.subtype = SYSTEM_TYPE_CONSOLE,
56-
.read_irq = CONSOLE_IRQ,
5756
.read_irq_name = "console",
58-
.write_irq = CONSOLE_WRITE_IRQ,
5957
.write_irq_name = "console-write",
6058
.mc = {
6159
.list = LIST_HEAD_INIT(driver.mc.list),

arch/um/include/asm/irq.h

+9-13
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,15 @@
44

55
#define TIMER_IRQ 0
66
#define UMN_IRQ 1
7-
#define CONSOLE_IRQ 2
8-
#define CONSOLE_WRITE_IRQ 3
9-
#define UBD_IRQ 4
10-
#define UM_ETH_IRQ 5
11-
#define SSL_IRQ 6
12-
#define SSL_WRITE_IRQ 7
13-
#define ACCEPT_IRQ 8
14-
#define MCONSOLE_IRQ 9
15-
#define WINCH_IRQ 10
16-
#define SIGIO_WRITE_IRQ 11
17-
#define TELNETD_IRQ 12
18-
#define XTERM_IRQ 13
19-
#define RANDOM_IRQ 14
7+
#define UBD_IRQ 2
8+
#define UM_ETH_IRQ 3
9+
#define ACCEPT_IRQ 4
10+
#define MCONSOLE_IRQ 5
11+
#define WINCH_IRQ 6
12+
#define SIGIO_WRITE_IRQ 7
13+
#define TELNETD_IRQ 8
14+
#define XTERM_IRQ 9
15+
#define RANDOM_IRQ 10
2016

2117
#ifdef CONFIG_UML_NET_VECTOR
2218

0 commit comments

Comments
 (0)