diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 21:29:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-27 21:29:53 -0400 |
commit | fa453a625de5b8ee9ada0a5b329df3f88751c615 (patch) | |
tree | 7a9e04d4a44bb929e96bd9bebb7b97cb733d1ecb /arch/um/drivers | |
parent | 30eebb54b13ef198a3f1a143ee9dd68f295c60de (diff) | |
parent | 3463ff4439661d8107ac024329b5fe01d6e5117b (diff) |
Merge branch 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML changes from Richard Weinberger:
"Mostly bug fixes and cleanups"
* 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (35 commits)
um: Update defconfig
um: Switch to large mcmodel on x86_64
MTD: Relax dependencies
um: Wire CONFIG_GENERIC_IO up
um: Serve io_remap_pfn_range()
Introduce CONFIG_GENERIC_IO
um: allow SUBARCH=x86
um: most of the SUBARCH uses can be killed
um: deadlock in line_write_interrupt()
um: don't bother trying to rebuild CHECKFLAGS for USER_OBJS
um: use the right ifdef around exports in user_syms.c
um: a bunch of headers can be killed by using generic-y
um: ptrace-generic.h doesn't need user.h
um: kill HOST_TASK_PID
um: remove pointless include of asm/fixmap.h from asm/pgtable.h
um: asm-offsets.h might as well come from underlying arch...
um: merge processor_{32,64}.h a bit...
um: switch close_chan() to struct line
um: race fix: initialize delayed_work *before* registering IRQ
um: line->have_irq is never checked...
...
Diffstat (limited to 'arch/um/drivers')
-rw-r--r-- | arch/um/drivers/chan.h | 18 | ||||
-rw-r--r-- | arch/um/drivers/chan_kern.c | 198 | ||||
-rw-r--r-- | arch/um/drivers/chan_user.h | 2 | ||||
-rw-r--r-- | arch/um/drivers/line.c | 258 | ||||
-rw-r--r-- | arch/um/drivers/line.h | 29 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/net_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/port_kern.c | 4 | ||||
-rw-r--r-- | arch/um/drivers/random.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/ssl.c | 41 | ||||
-rw-r--r-- | arch/um/drivers/stdio_console.c | 46 | ||||
-rw-r--r-- | arch/um/drivers/ubd.h (renamed from arch/um/drivers/ubd_user.h) | 0 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 46 | ||||
-rw-r--r-- | arch/um/drivers/ubd_user.c | 8 | ||||
-rw-r--r-- | arch/um/drivers/xterm_kern.c | 2 |
15 files changed, 292 insertions, 366 deletions
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h index 8df0fd9024dc..02b5a76e98d9 100644 --- a/arch/um/drivers/chan.h +++ b/arch/um/drivers/chan.h | |||
@@ -27,24 +27,24 @@ struct chan { | |||
27 | void *data; | 27 | void *data; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, | 30 | extern void chan_interrupt(struct line *line, |
31 | struct tty_struct *tty, int irq); | 31 | struct tty_struct *tty, int irq); |
32 | extern int parse_chan_pair(char *str, struct line *line, int device, | 32 | extern int parse_chan_pair(char *str, struct line *line, int device, |
33 | const struct chan_opts *opts, char **error_out); | 33 | const struct chan_opts *opts, char **error_out); |
34 | extern int write_chan(struct list_head *chans, const char *buf, int len, | 34 | extern int write_chan(struct chan *chan, const char *buf, int len, |
35 | int write_irq); | 35 | int write_irq); |
36 | extern int console_write_chan(struct list_head *chans, const char *buf, | 36 | extern int console_write_chan(struct chan *chan, const char *buf, |
37 | int len); | 37 | int len); |
38 | extern int console_open_chan(struct line *line, struct console *co); | 38 | extern int console_open_chan(struct line *line, struct console *co); |
39 | extern void deactivate_chan(struct list_head *chans, int irq); | 39 | extern void deactivate_chan(struct chan *chan, int irq); |
40 | extern void reactivate_chan(struct list_head *chans, int irq); | 40 | extern void reactivate_chan(struct chan *chan, int irq); |
41 | extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); | 41 | extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); |
42 | extern int enable_chan(struct line *line); | 42 | extern int enable_chan(struct line *line); |
43 | extern void close_chan(struct list_head *chans, int delay_free_irq); | 43 | extern void close_chan(struct line *line); |
44 | extern int chan_window_size(struct list_head *chans, | 44 | extern int chan_window_size(struct line *line, |
45 | unsigned short *rows_out, | 45 | unsigned short *rows_out, |
46 | unsigned short *cols_out); | 46 | unsigned short *cols_out); |
47 | extern int chan_config_string(struct list_head *chans, char *str, int size, | 47 | extern int chan_config_string(struct line *line, char *str, int size, |
48 | char **error_out); | 48 | char **error_out); |
49 | 49 | ||
50 | #endif | 50 | #endif |
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 420e2c800799..ca4c7ebfd0aa 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -140,18 +140,18 @@ static int open_chan(struct list_head *chans) | |||
140 | return err; | 140 | return err; |
141 | } | 141 | } |
142 | 142 | ||
143 | void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) | 143 | void chan_enable_winch(struct chan *chan, struct tty_struct *tty) |
144 | { | 144 | { |
145 | struct list_head *ele; | 145 | if (chan && chan->primary && chan->ops->winch) |
146 | struct chan *chan; | 146 | register_winch(chan->fd, tty); |
147 | } | ||
147 | 148 | ||
148 | list_for_each(ele, chans) { | 149 | static void line_timer_cb(struct work_struct *work) |
149 | chan = list_entry(ele, struct chan, list); | 150 | { |
150 | if (chan->primary && chan->output && chan->ops->winch) { | 151 | struct line *line = container_of(work, struct line, task.work); |
151 | register_winch(chan->fd, tty); | 152 | |
152 | return; | 153 | if (!line->throttled) |
153 | } | 154 | chan_interrupt(line, line->tty, line->driver->read_irq); |
154 | } | ||
155 | } | 155 | } |
156 | 156 | ||
157 | int enable_chan(struct line *line) | 157 | int enable_chan(struct line *line) |
@@ -160,6 +160,8 @@ int enable_chan(struct line *line) | |||
160 | struct chan *chan; | 160 | struct chan *chan; |
161 | int err; | 161 | int err; |
162 | 162 | ||
163 | INIT_DELAYED_WORK(&line->task, line_timer_cb); | ||
164 | |||
163 | list_for_each(ele, &line->chan_list) { | 165 | list_for_each(ele, &line->chan_list) { |
164 | chan = list_entry(ele, struct chan, list); | 166 | chan = list_entry(ele, struct chan, list); |
165 | err = open_one_chan(chan); | 167 | err = open_one_chan(chan); |
@@ -183,7 +185,7 @@ int enable_chan(struct line *line) | |||
183 | return 0; | 185 | return 0; |
184 | 186 | ||
185 | out_close: | 187 | out_close: |
186 | close_chan(&line->chan_list, 0); | 188 | close_chan(line); |
187 | return err; | 189 | return err; |
188 | } | 190 | } |
189 | 191 | ||
@@ -244,7 +246,7 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) | |||
244 | chan->fd = -1; | 246 | chan->fd = -1; |
245 | } | 247 | } |
246 | 248 | ||
247 | void close_chan(struct list_head *chans, int delay_free_irq) | 249 | void close_chan(struct line *line) |
248 | { | 250 | { |
249 | struct chan *chan; | 251 | struct chan *chan; |
250 | 252 | ||
@@ -253,77 +255,50 @@ void close_chan(struct list_head *chans, int delay_free_irq) | |||
253 | * state. Then, the first one opened will have the original state, | 255 | * state. Then, the first one opened will have the original state, |
254 | * so it must be the last closed. | 256 | * so it must be the last closed. |
255 | */ | 257 | */ |
256 | list_for_each_entry_reverse(chan, chans, list) { | 258 | list_for_each_entry_reverse(chan, &line->chan_list, list) { |
257 | close_one_chan(chan, delay_free_irq); | 259 | close_one_chan(chan, 0); |
258 | } | 260 | } |
259 | } | 261 | } |
260 | 262 | ||
261 | void deactivate_chan(struct list_head *chans, int irq) | 263 | void deactivate_chan(struct chan *chan, int irq) |
262 | { | 264 | { |
263 | struct list_head *ele; | 265 | if (chan && chan->enabled) |
264 | 266 | deactivate_fd(chan->fd, irq); | |
265 | struct chan *chan; | ||
266 | list_for_each(ele, chans) { | ||
267 | chan = list_entry(ele, struct chan, list); | ||
268 | |||
269 | if (chan->enabled && chan->input) | ||
270 | deactivate_fd(chan->fd, irq); | ||
271 | } | ||
272 | } | 267 | } |
273 | 268 | ||
274 | void reactivate_chan(struct list_head *chans, int irq) | 269 | void reactivate_chan(struct chan *chan, int irq) |
275 | { | 270 | { |
276 | struct list_head *ele; | 271 | if (chan && chan->enabled) |
277 | struct chan *chan; | 272 | reactivate_fd(chan->fd, irq); |
278 | |||
279 | list_for_each(ele, chans) { | ||
280 | chan = list_entry(ele, struct chan, list); | ||
281 | |||
282 | if (chan->enabled && chan->input) | ||
283 | reactivate_fd(chan->fd, irq); | ||
284 | } | ||
285 | } | 273 | } |
286 | 274 | ||
287 | int write_chan(struct list_head *chans, const char *buf, int len, | 275 | int write_chan(struct chan *chan, const char *buf, int len, |
288 | int write_irq) | 276 | int write_irq) |
289 | { | 277 | { |
290 | struct list_head *ele; | ||
291 | struct chan *chan = NULL; | ||
292 | int n, ret = 0; | 278 | int n, ret = 0; |
293 | 279 | ||
294 | if (len == 0) | 280 | if (len == 0 || !chan || !chan->ops->write) |
295 | return 0; | 281 | return 0; |
296 | 282 | ||
297 | list_for_each(ele, chans) { | 283 | n = chan->ops->write(chan->fd, buf, len, chan->data); |
298 | chan = list_entry(ele, struct chan, list); | 284 | if (chan->primary) { |
299 | if (!chan->output || (chan->ops->write == NULL)) | 285 | ret = n; |
300 | continue; | 286 | if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) |
301 | 287 | reactivate_fd(chan->fd, write_irq); | |
302 | n = chan->ops->write(chan->fd, buf, len, chan->data); | ||
303 | if (chan->primary) { | ||
304 | ret = n; | ||
305 | if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) | ||
306 | reactivate_fd(chan->fd, write_irq); | ||
307 | } | ||
308 | } | 288 | } |
309 | return ret; | 289 | return ret; |
310 | } | 290 | } |
311 | 291 | ||
312 | int console_write_chan(struct list_head *chans, const char *buf, int len) | 292 | int console_write_chan(struct chan *chan, const char *buf, int len) |
313 | { | 293 | { |
314 | struct list_head *ele; | ||
315 | struct chan *chan; | ||
316 | int n, ret = 0; | 294 | int n, ret = 0; |
317 | 295 | ||
318 | list_for_each(ele, chans) { | 296 | if (!chan || !chan->ops->console_write) |
319 | chan = list_entry(ele, struct chan, list); | 297 | return 0; |
320 | if (!chan->output || (chan->ops->console_write == NULL)) | ||
321 | continue; | ||
322 | 298 | ||
323 | n = chan->ops->console_write(chan->fd, buf, len); | 299 | n = chan->ops->console_write(chan->fd, buf, len); |
324 | if (chan->primary) | 300 | if (chan->primary) |
325 | ret = n; | 301 | ret = n; |
326 | } | ||
327 | return ret; | 302 | return ret; |
328 | } | 303 | } |
329 | 304 | ||
@@ -340,20 +315,24 @@ int console_open_chan(struct line *line, struct console *co) | |||
340 | return 0; | 315 | return 0; |
341 | } | 316 | } |
342 | 317 | ||
343 | int chan_window_size(struct list_head *chans, unsigned short *rows_out, | 318 | int chan_window_size(struct line *line, unsigned short *rows_out, |
344 | unsigned short *cols_out) | 319 | unsigned short *cols_out) |
345 | { | 320 | { |
346 | struct list_head *ele; | ||
347 | struct chan *chan; | 321 | struct chan *chan; |
348 | 322 | ||
349 | list_for_each(ele, chans) { | 323 | chan = line->chan_in; |
350 | chan = list_entry(ele, struct chan, list); | 324 | if (chan && chan->primary) { |
351 | if (chan->primary) { | 325 | if (chan->ops->window_size == NULL) |
352 | if (chan->ops->window_size == NULL) | 326 | return 0; |
353 | return 0; | 327 | return chan->ops->window_size(chan->fd, chan->data, |
354 | return chan->ops->window_size(chan->fd, chan->data, | 328 | rows_out, cols_out); |
355 | rows_out, cols_out); | 329 | } |
356 | } | 330 | chan = line->chan_out; |
331 | if (chan && chan->primary) { | ||
332 | if (chan->ops->window_size == NULL) | ||
333 | return 0; | ||
334 | return chan->ops->window_size(chan->fd, chan->data, | ||
335 | rows_out, cols_out); | ||
357 | } | 336 | } |
358 | return 0; | 337 | return 0; |
359 | } | 338 | } |
@@ -429,21 +408,15 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, | |||
429 | return n; | 408 | return n; |
430 | } | 409 | } |
431 | 410 | ||
432 | int chan_config_string(struct list_head *chans, char *str, int size, | 411 | int chan_config_string(struct line *line, char *str, int size, |
433 | char **error_out) | 412 | char **error_out) |
434 | { | 413 | { |
435 | struct list_head *ele; | 414 | struct chan *in = line->chan_in, *out = line->chan_out; |
436 | struct chan *chan, *in = NULL, *out = NULL; | ||
437 | 415 | ||
438 | list_for_each(ele, chans) { | 416 | if (in && !in->primary) |
439 | chan = list_entry(ele, struct chan, list); | 417 | in = NULL; |
440 | if (!chan->primary) | 418 | if (out && !out->primary) |
441 | continue; | 419 | out = NULL; |
442 | if (chan->input) | ||
443 | in = chan; | ||
444 | if (chan->output) | ||
445 | out = chan; | ||
446 | } | ||
447 | 420 | ||
448 | return chan_pair_config_string(in, out, str, size, error_out); | 421 | return chan_pair_config_string(in, out, str, size, error_out); |
449 | } | 422 | } |
@@ -547,10 +520,14 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
547 | char *in, *out; | 520 | char *in, *out; |
548 | 521 | ||
549 | if (!list_empty(chans)) { | 522 | if (!list_empty(chans)) { |
523 | line->chan_in = line->chan_out = NULL; | ||
550 | free_chan(chans); | 524 | free_chan(chans); |
551 | INIT_LIST_HEAD(chans); | 525 | INIT_LIST_HEAD(chans); |
552 | } | 526 | } |
553 | 527 | ||
528 | if (!str) | ||
529 | return 0; | ||
530 | |||
554 | out = strchr(str, ','); | 531 | out = strchr(str, ','); |
555 | if (out != NULL) { | 532 | if (out != NULL) { |
556 | in = str; | 533 | in = str; |
@@ -562,6 +539,7 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
562 | 539 | ||
563 | new->input = 1; | 540 | new->input = 1; |
564 | list_add(&new->list, chans); | 541 | list_add(&new->list, chans); |
542 | line->chan_in = new; | ||
565 | 543 | ||
566 | new = parse_chan(line, out, device, opts, error_out); | 544 | new = parse_chan(line, out, device, opts, error_out); |
567 | if (new == NULL) | 545 | if (new == NULL) |
@@ -569,6 +547,7 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
569 | 547 | ||
570 | list_add(&new->list, chans); | 548 | list_add(&new->list, chans); |
571 | new->output = 1; | 549 | new->output = 1; |
550 | line->chan_out = new; | ||
572 | } | 551 | } |
573 | else { | 552 | else { |
574 | new = parse_chan(line, str, device, opts, error_out); | 553 | new = parse_chan(line, str, device, opts, error_out); |
@@ -578,43 +557,42 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
578 | list_add(&new->list, chans); | 557 | list_add(&new->list, chans); |
579 | new->input = 1; | 558 | new->input = 1; |
580 | new->output = 1; | 559 | new->output = 1; |
560 | line->chan_in = line->chan_out = new; | ||
581 | } | 561 | } |
582 | return 0; | 562 | return 0; |
583 | } | 563 | } |
584 | 564 | ||
585 | void chan_interrupt(struct list_head *chans, struct delayed_work *task, | 565 | void chan_interrupt(struct line *line, struct tty_struct *tty, int irq) |
586 | struct tty_struct *tty, int irq) | ||
587 | { | 566 | { |
588 | struct list_head *ele, *next; | 567 | struct chan *chan = line->chan_in; |
589 | struct chan *chan; | ||
590 | int err; | 568 | int err; |
591 | char c; | 569 | char c; |
592 | 570 | ||
593 | list_for_each_safe(ele, next, chans) { | 571 | if (!chan || !chan->ops->read) |
594 | chan = list_entry(ele, struct chan, list); | 572 | goto out; |
595 | if (!chan->input || (chan->ops->read == NULL)) | 573 | |
596 | continue; | 574 | do { |
597 | do { | 575 | if (tty && !tty_buffer_request_room(tty, 1)) { |
598 | if (tty && !tty_buffer_request_room(tty, 1)) { | 576 | schedule_delayed_work(&line->task, 1); |
599 | schedule_delayed_work(task, 1); | 577 | goto out; |
600 | goto out; | ||
601 | } | ||
602 | err = chan->ops->read(chan->fd, &c, chan->data); | ||
603 | if (err > 0) | ||
604 | tty_receive_char(tty, c); | ||
605 | } while (err > 0); | ||
606 | |||
607 | if (err == 0) | ||
608 | reactivate_fd(chan->fd, irq); | ||
609 | if (err == -EIO) { | ||
610 | if (chan->primary) { | ||
611 | if (tty != NULL) | ||
612 | tty_hangup(tty); | ||
613 | close_chan(chans, 1); | ||
614 | return; | ||
615 | } | ||
616 | else close_one_chan(chan, 1); | ||
617 | } | 578 | } |
579 | err = chan->ops->read(chan->fd, &c, chan->data); | ||
580 | if (err > 0) | ||
581 | tty_receive_char(tty, c); | ||
582 | } while (err > 0); | ||
583 | |||
584 | if (err == 0) | ||
585 | reactivate_fd(chan->fd, irq); | ||
586 | if (err == -EIO) { | ||
587 | if (chan->primary) { | ||
588 | if (tty != NULL) | ||
589 | tty_hangup(tty); | ||
590 | if (line->chan_out != chan) | ||
591 | close_one_chan(line->chan_out, 1); | ||
592 | } | ||
593 | close_one_chan(chan, 1); | ||
594 | if (chan->primary) | ||
595 | return; | ||
618 | } | 596 | } |
619 | out: | 597 | out: |
620 | if (tty) | 598 | if (tty) |
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h index 9b9ced85b703..6257b7a6e1af 100644 --- a/arch/um/drivers/chan_user.h +++ b/arch/um/drivers/chan_user.h | |||
@@ -14,8 +14,6 @@ struct chan_opts { | |||
14 | const int raw; | 14 | const int raw; |
15 | }; | 15 | }; |
16 | 16 | ||
17 | enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; | ||
18 | |||
19 | struct chan_ops { | 17 | struct chan_ops { |
20 | char *type; | 18 | char *type; |
21 | void *(*init)(char *, int, const struct chan_opts *); | 19 | void *(*init)(char *, int, const struct chan_opts *); |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index c1cf2206b84b..4ab0d9c0911c 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) | |||
21 | struct line *line = chan->line; | 21 | struct line *line = chan->line; |
22 | 22 | ||
23 | if (line) | 23 | if (line) |
24 | chan_interrupt(&line->chan_list, &line->task, line->tty, irq); | 24 | chan_interrupt(line, line->tty, irq); |
25 | return IRQ_HANDLED; | 25 | return IRQ_HANDLED; |
26 | } | 26 | } |
27 | 27 | ||
28 | static void line_timer_cb(struct work_struct *work) | ||
29 | { | ||
30 | struct line *line = container_of(work, struct line, task.work); | ||
31 | |||
32 | if (!line->throttled) | ||
33 | chan_interrupt(&line->chan_list, &line->task, line->tty, | ||
34 | line->driver->read_irq); | ||
35 | } | ||
36 | |||
37 | /* | 28 | /* |
38 | * Returns the free space inside the ring buffer of this line. | 29 | * Returns the free space inside the ring buffer of this line. |
39 | * | 30 | * |
@@ -145,7 +136,7 @@ static int flush_buffer(struct line *line) | |||
145 | /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ | 136 | /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ |
146 | count = line->buffer + LINE_BUFSIZE - line->head; | 137 | count = line->buffer + LINE_BUFSIZE - line->head; |
147 | 138 | ||
148 | n = write_chan(&line->chan_list, line->head, count, | 139 | n = write_chan(line->chan_out, line->head, count, |
149 | line->driver->write_irq); | 140 | line->driver->write_irq); |
150 | if (n < 0) | 141 | if (n < 0) |
151 | return n; | 142 | return n; |
@@ -162,7 +153,7 @@ static int flush_buffer(struct line *line) | |||
162 | } | 153 | } |
163 | 154 | ||
164 | count = line->tail - line->head; | 155 | count = line->tail - line->head; |
165 | n = write_chan(&line->chan_list, line->head, count, | 156 | n = write_chan(line->chan_out, line->head, count, |
166 | line->driver->write_irq); | 157 | line->driver->write_irq); |
167 | 158 | ||
168 | if (n < 0) | 159 | if (n < 0) |
@@ -206,7 +197,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) | |||
206 | if (line->head != line->tail) | 197 | if (line->head != line->tail) |
207 | ret = buffer_data(line, buf, len); | 198 | ret = buffer_data(line, buf, len); |
208 | else { | 199 | else { |
209 | n = write_chan(&line->chan_list, buf, len, | 200 | n = write_chan(line->chan_out, buf, len, |
210 | line->driver->write_irq); | 201 | line->driver->write_irq); |
211 | if (n < 0) { | 202 | if (n < 0) { |
212 | ret = n; | 203 | ret = n; |
@@ -318,7 +309,7 @@ void line_throttle(struct tty_struct *tty) | |||
318 | { | 309 | { |
319 | struct line *line = tty->driver_data; | 310 | struct line *line = tty->driver_data; |
320 | 311 | ||
321 | deactivate_chan(&line->chan_list, line->driver->read_irq); | 312 | deactivate_chan(line->chan_in, line->driver->read_irq); |
322 | line->throttled = 1; | 313 | line->throttled = 1; |
323 | } | 314 | } |
324 | 315 | ||
@@ -327,8 +318,7 @@ void line_unthrottle(struct tty_struct *tty) | |||
327 | struct line *line = tty->driver_data; | 318 | struct line *line = tty->driver_data; |
328 | 319 | ||
329 | line->throttled = 0; | 320 | line->throttled = 0; |
330 | chan_interrupt(&line->chan_list, &line->task, tty, | 321 | chan_interrupt(line, tty, line->driver->read_irq); |
331 | line->driver->read_irq); | ||
332 | 322 | ||
333 | /* | 323 | /* |
334 | * Maybe there is enough stuff pending that calling the interrupt | 324 | * Maybe there is enough stuff pending that calling the interrupt |
@@ -336,7 +326,7 @@ void line_unthrottle(struct tty_struct *tty) | |||
336 | * again and we shouldn't turn the interrupt back on. | 326 | * again and we shouldn't turn the interrupt back on. |
337 | */ | 327 | */ |
338 | if (!line->throttled) | 328 | if (!line->throttled) |
339 | reactivate_chan(&line->chan_list, line->driver->read_irq); | 329 | reactivate_chan(line->chan_in, line->driver->read_irq); |
340 | } | 330 | } |
341 | 331 | ||
342 | static irqreturn_t line_write_interrupt(int irq, void *data) | 332 | static irqreturn_t line_write_interrupt(int irq, void *data) |
@@ -347,13 +337,14 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
347 | int err; | 337 | int err; |
348 | 338 | ||
349 | /* | 339 | /* |
350 | * Interrupts are disabled here because we registered the interrupt with | 340 | * Interrupts are disabled here because genirq keep irqs disabled when |
351 | * IRQF_DISABLED (see line_setup_irq). | 341 | * calling the action handler. |
352 | */ | 342 | */ |
353 | 343 | ||
354 | spin_lock(&line->lock); | 344 | spin_lock(&line->lock); |
355 | err = flush_buffer(line); | 345 | err = flush_buffer(line); |
356 | if (err == 0) { | 346 | if (err == 0) { |
347 | spin_unlock(&line->lock); | ||
357 | return IRQ_NONE; | 348 | return IRQ_NONE; |
358 | } else if (err < 0) { | 349 | } else if (err < 0) { |
359 | line->head = line->buffer; | 350 | line->head = line->buffer; |
@@ -371,7 +362,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
371 | int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | 362 | int line_setup_irq(int fd, int input, int output, struct line *line, void *data) |
372 | { | 363 | { |
373 | const struct line_driver *driver = line->driver; | 364 | const struct line_driver *driver = line->driver; |
374 | int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; | 365 | int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; |
375 | 366 | ||
376 | if (input) | 367 | if (input) |
377 | err = um_request_irq(driver->read_irq, fd, IRQ_READ, | 368 | err = um_request_irq(driver->read_irq, fd, IRQ_READ, |
@@ -383,7 +374,6 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | |||
383 | err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, | 374 | err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, |
384 | line_write_interrupt, flags, | 375 | line_write_interrupt, flags, |
385 | driver->write_irq_name, data); | 376 | driver->write_irq_name, data); |
386 | line->have_irq = 1; | ||
387 | return err; | 377 | return err; |
388 | } | 378 | } |
389 | 379 | ||
@@ -409,7 +399,7 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
409 | struct line *line = &lines[tty->index]; | 399 | struct line *line = &lines[tty->index]; |
410 | int err = -ENODEV; | 400 | int err = -ENODEV; |
411 | 401 | ||
412 | spin_lock(&line->count_lock); | 402 | mutex_lock(&line->count_lock); |
413 | if (!line->valid) | 403 | if (!line->valid) |
414 | goto out_unlock; | 404 | goto out_unlock; |
415 | 405 | ||
@@ -421,25 +411,19 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
421 | tty->driver_data = line; | 411 | tty->driver_data = line; |
422 | line->tty = tty; | 412 | line->tty = tty; |
423 | 413 | ||
424 | spin_unlock(&line->count_lock); | ||
425 | err = enable_chan(line); | 414 | err = enable_chan(line); |
426 | if (err) /* line_close() will be called by our caller */ | 415 | if (err) /* line_close() will be called by our caller */ |
427 | return err; | 416 | goto out_unlock; |
428 | |||
429 | INIT_DELAYED_WORK(&line->task, line_timer_cb); | ||
430 | 417 | ||
431 | if (!line->sigio) { | 418 | if (!line->sigio) { |
432 | chan_enable_winch(&line->chan_list, tty); | 419 | chan_enable_winch(line->chan_out, tty); |
433 | line->sigio = 1; | 420 | line->sigio = 1; |
434 | } | 421 | } |
435 | 422 | ||
436 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, | 423 | chan_window_size(line, &tty->winsize.ws_row, |
437 | &tty->winsize.ws_col); | 424 | &tty->winsize.ws_col); |
438 | |||
439 | return 0; | ||
440 | |||
441 | out_unlock: | 425 | out_unlock: |
442 | spin_unlock(&line->count_lock); | 426 | mutex_unlock(&line->count_lock); |
443 | return err; | 427 | return err; |
444 | } | 428 | } |
445 | 429 | ||
@@ -459,7 +443,7 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
459 | /* We ignore the error anyway! */ | 443 | /* We ignore the error anyway! */ |
460 | flush_buffer(line); | 444 | flush_buffer(line); |
461 | 445 | ||
462 | spin_lock(&line->count_lock); | 446 | mutex_lock(&line->count_lock); |
463 | BUG_ON(!line->valid); | 447 | BUG_ON(!line->valid); |
464 | 448 | ||
465 | if (--line->count) | 449 | if (--line->count) |
@@ -468,17 +452,13 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
468 | line->tty = NULL; | 452 | line->tty = NULL; |
469 | tty->driver_data = NULL; | 453 | tty->driver_data = NULL; |
470 | 454 | ||
471 | spin_unlock(&line->count_lock); | ||
472 | |||
473 | if (line->sigio) { | 455 | if (line->sigio) { |
474 | unregister_winch(tty); | 456 | unregister_winch(tty); |
475 | line->sigio = 0; | 457 | line->sigio = 0; |
476 | } | 458 | } |
477 | 459 | ||
478 | return; | ||
479 | |||
480 | out_unlock: | 460 | out_unlock: |
481 | spin_unlock(&line->count_lock); | 461 | mutex_unlock(&line->count_lock); |
482 | } | 462 | } |
483 | 463 | ||
484 | void close_lines(struct line *lines, int nlines) | 464 | void close_lines(struct line *lines, int nlines) |
@@ -486,34 +466,60 @@ void close_lines(struct line *lines, int nlines) | |||
486 | int i; | 466 | int i; |
487 | 467 | ||
488 | for(i = 0; i < nlines; i++) | 468 | for(i = 0; i < nlines; i++) |
489 | close_chan(&lines[i].chan_list, 0); | 469 | close_chan(&lines[i]); |
490 | } | 470 | } |
491 | 471 | ||
492 | static int setup_one_line(struct line *lines, int n, char *init, int init_prio, | 472 | int setup_one_line(struct line *lines, int n, char *init, |
493 | char **error_out) | 473 | const struct chan_opts *opts, char **error_out) |
494 | { | 474 | { |
495 | struct line *line = &lines[n]; | 475 | struct line *line = &lines[n]; |
476 | struct tty_driver *driver = line->driver->driver; | ||
496 | int err = -EINVAL; | 477 | int err = -EINVAL; |
497 | 478 | ||
498 | spin_lock(&line->count_lock); | 479 | mutex_lock(&line->count_lock); |
499 | 480 | ||
500 | if (line->count) { | 481 | if (line->count) { |
501 | *error_out = "Device is already open"; | 482 | *error_out = "Device is already open"; |
502 | goto out; | 483 | goto out; |
503 | } | 484 | } |
504 | 485 | ||
505 | if (line->init_pri <= init_prio) { | 486 | if (!strcmp(init, "none")) { |
506 | line->init_pri = init_prio; | 487 | if (line->valid) { |
507 | if (!strcmp(init, "none")) | 488 | line->valid = 0; |
489 | kfree(line->init_str); | ||
490 | tty_unregister_device(driver, n); | ||
491 | parse_chan_pair(NULL, line, n, opts, error_out); | ||
492 | err = 0; | ||
493 | } | ||
494 | } else { | ||
495 | char *new = kstrdup(init, GFP_KERNEL); | ||
496 | if (!new) { | ||
497 | *error_out = "Failed to allocate memory"; | ||
498 | return -ENOMEM; | ||
499 | } | ||
500 | if (line->valid) { | ||
501 | tty_unregister_device(driver, n); | ||
502 | kfree(line->init_str); | ||
503 | } | ||
504 | line->init_str = new; | ||
505 | line->valid = 1; | ||
506 | err = parse_chan_pair(new, line, n, opts, error_out); | ||
507 | if (!err) { | ||
508 | struct device *d = tty_register_device(driver, n, NULL); | ||
509 | if (IS_ERR(d)) { | ||
510 | *error_out = "Failed to register device"; | ||
511 | err = PTR_ERR(d); | ||
512 | parse_chan_pair(NULL, line, n, opts, error_out); | ||
513 | } | ||
514 | } | ||
515 | if (err) { | ||
516 | line->init_str = NULL; | ||
508 | line->valid = 0; | 517 | line->valid = 0; |
509 | else { | 518 | kfree(new); |
510 | line->init_str = init; | ||
511 | line->valid = 1; | ||
512 | } | 519 | } |
513 | } | 520 | } |
514 | err = 0; | ||
515 | out: | 521 | out: |
516 | spin_unlock(&line->count_lock); | 522 | mutex_unlock(&line->count_lock); |
517 | return err; | 523 | return err; |
518 | } | 524 | } |
519 | 525 | ||
@@ -524,54 +530,43 @@ out: | |||
524 | * @error_out is an error string in the case of failure; | 530 | * @error_out is an error string in the case of failure; |
525 | */ | 531 | */ |
526 | 532 | ||
527 | int line_setup(struct line *lines, unsigned int num, char *init, | 533 | int line_setup(char **conf, unsigned int num, char **def, |
528 | char **error_out) | 534 | char *init, char *name) |
529 | { | 535 | { |
530 | int i, n, err; | 536 | char *error; |
531 | char *end; | ||
532 | 537 | ||
533 | if (*init == '=') { | 538 | if (*init == '=') { |
534 | /* | 539 | /* |
535 | * We said con=/ssl= instead of con#=, so we are configuring all | 540 | * We said con=/ssl= instead of con#=, so we are configuring all |
536 | * consoles at once. | 541 | * consoles at once. |
537 | */ | 542 | */ |
538 | n = -1; | 543 | *def = init + 1; |
539 | } | 544 | } else { |
540 | else { | 545 | char *end; |
541 | n = simple_strtoul(init, &end, 0); | 546 | unsigned n = simple_strtoul(init, &end, 0); |
547 | |||
542 | if (*end != '=') { | 548 | if (*end != '=') { |
543 | *error_out = "Couldn't parse device number"; | 549 | error = "Couldn't parse device number"; |
544 | return -EINVAL; | 550 | goto out; |
545 | } | 551 | } |
546 | init = end; | 552 | if (n >= num) { |
547 | } | 553 | error = "Device number out of range"; |
548 | init++; | 554 | goto out; |
549 | |||
550 | if (n >= (signed int) num) { | ||
551 | *error_out = "Device number out of range"; | ||
552 | return -EINVAL; | ||
553 | } | ||
554 | else if (n >= 0) { | ||
555 | err = setup_one_line(lines, n, init, INIT_ONE, error_out); | ||
556 | if (err) | ||
557 | return err; | ||
558 | } | ||
559 | else { | ||
560 | for(i = 0; i < num; i++) { | ||
561 | err = setup_one_line(lines, i, init, INIT_ALL, | ||
562 | error_out); | ||
563 | if (err) | ||
564 | return err; | ||
565 | } | 555 | } |
556 | conf[n] = end + 1; | ||
566 | } | 557 | } |
567 | return n == -1 ? num : n; | 558 | return 0; |
559 | |||
560 | out: | ||
561 | printk(KERN_ERR "Failed to set up %s with " | ||
562 | "configuration string \"%s\" : %s\n", name, init, error); | ||
563 | return -EINVAL; | ||
568 | } | 564 | } |
569 | 565 | ||
570 | int line_config(struct line *lines, unsigned int num, char *str, | 566 | int line_config(struct line *lines, unsigned int num, char *str, |
571 | const struct chan_opts *opts, char **error_out) | 567 | const struct chan_opts *opts, char **error_out) |
572 | { | 568 | { |
573 | struct line *line; | 569 | char *end; |
574 | char *new; | ||
575 | int n; | 570 | int n; |
576 | 571 | ||
577 | if (*str == '=') { | 572 | if (*str == '=') { |
@@ -579,17 +574,17 @@ int line_config(struct line *lines, unsigned int num, char *str, | |||
579 | return -EINVAL; | 574 | return -EINVAL; |
580 | } | 575 | } |
581 | 576 | ||
582 | new = kstrdup(str, GFP_KERNEL); | 577 | n = simple_strtoul(str, &end, 0); |
583 | if (new == NULL) { | 578 | if (*end++ != '=') { |
584 | *error_out = "Failed to allocate memory"; | 579 | *error_out = "Couldn't parse device number"; |
585 | return -ENOMEM; | 580 | return -EINVAL; |
581 | } | ||
582 | if (n >= num) { | ||
583 | *error_out = "Device number out of range"; | ||
584 | return -EINVAL; | ||
586 | } | 585 | } |
587 | n = line_setup(lines, num, new, error_out); | ||
588 | if (n < 0) | ||
589 | return n; | ||
590 | 586 | ||
591 | line = &lines[n]; | 587 | return setup_one_line(lines, n, end, opts, error_out); |
592 | return parse_chan_pair(line->init_str, line, n, opts, error_out); | ||
593 | } | 588 | } |
594 | 589 | ||
595 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | 590 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, |
@@ -612,13 +607,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
612 | 607 | ||
613 | line = &lines[dev]; | 608 | line = &lines[dev]; |
614 | 609 | ||
615 | spin_lock(&line->count_lock); | 610 | mutex_lock(&line->count_lock); |
616 | if (!line->valid) | 611 | if (!line->valid) |
617 | CONFIG_CHUNK(str, size, n, "none", 1); | 612 | CONFIG_CHUNK(str, size, n, "none", 1); |
618 | else if (line->tty == NULL) | 613 | else if (line->tty == NULL) |
619 | CONFIG_CHUNK(str, size, n, line->init_str, 1); | 614 | CONFIG_CHUNK(str, size, n, line->init_str, 1); |
620 | else n = chan_config_string(&line->chan_list, str, size, error_out); | 615 | else n = chan_config_string(line, str, size, error_out); |
621 | spin_unlock(&line->count_lock); | 616 | mutex_unlock(&line->count_lock); |
622 | 617 | ||
623 | return n; | 618 | return n; |
624 | } | 619 | } |
@@ -640,25 +635,23 @@ int line_id(char **str, int *start_out, int *end_out) | |||
640 | 635 | ||
641 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) | 636 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) |
642 | { | 637 | { |
643 | int err; | 638 | if (n >= num) { |
644 | char config[sizeof("conxxxx=none\0")]; | 639 | *error_out = "Device number out of range"; |
645 | 640 | return -EINVAL; | |
646 | sprintf(config, "%d=none", n); | 641 | } |
647 | err = line_setup(lines, num, config, error_out); | 642 | return setup_one_line(lines, n, "none", NULL, error_out); |
648 | if (err >= 0) | ||
649 | err = 0; | ||
650 | return err; | ||
651 | } | 643 | } |
652 | 644 | ||
653 | struct tty_driver *register_lines(struct line_driver *line_driver, | 645 | int register_lines(struct line_driver *line_driver, |
654 | const struct tty_operations *ops, | 646 | const struct tty_operations *ops, |
655 | struct line *lines, int nlines) | 647 | struct line *lines, int nlines) |
656 | { | 648 | { |
657 | int i; | ||
658 | struct tty_driver *driver = alloc_tty_driver(nlines); | 649 | struct tty_driver *driver = alloc_tty_driver(nlines); |
650 | int err; | ||
651 | int i; | ||
659 | 652 | ||
660 | if (!driver) | 653 | if (!driver) |
661 | return NULL; | 654 | return -ENOMEM; |
662 | 655 | ||
663 | driver->driver_name = line_driver->name; | 656 | driver->driver_name = line_driver->name; |
664 | driver->name = line_driver->device_name; | 657 | driver->name = line_driver->device_name; |
@@ -666,54 +659,33 @@ struct tty_driver *register_lines(struct line_driver *line_driver, | |||
666 | driver->minor_start = line_driver->minor_start; | 659 | driver->minor_start = line_driver->minor_start; |
667 | driver->type = line_driver->type; | 660 | driver->type = line_driver->type; |
668 | driver->subtype = line_driver->subtype; | 661 | driver->subtype = line_driver->subtype; |
669 | driver->flags = TTY_DRIVER_REAL_RAW; | 662 | driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
670 | driver->init_termios = tty_std_termios; | 663 | driver->init_termios = tty_std_termios; |
664 | |||
665 | for (i = 0; i < nlines; i++) { | ||
666 | spin_lock_init(&lines[i].lock); | ||
667 | mutex_init(&lines[i].count_lock); | ||
668 | lines[i].driver = line_driver; | ||
669 | INIT_LIST_HEAD(&lines[i].chan_list); | ||
670 | } | ||
671 | tty_set_operations(driver, ops); | 671 | tty_set_operations(driver, ops); |
672 | 672 | ||
673 | if (tty_register_driver(driver)) { | 673 | err = tty_register_driver(driver); |
674 | if (err) { | ||
674 | printk(KERN_ERR "register_lines : can't register %s driver\n", | 675 | printk(KERN_ERR "register_lines : can't register %s driver\n", |
675 | line_driver->name); | 676 | line_driver->name); |
676 | put_tty_driver(driver); | 677 | put_tty_driver(driver); |
677 | return NULL; | 678 | return err; |
678 | } | ||
679 | |||
680 | for(i = 0; i < nlines; i++) { | ||
681 | if (!lines[i].valid) | ||
682 | tty_unregister_device(driver, i); | ||
683 | } | 679 | } |
684 | 680 | ||
681 | line_driver->driver = driver; | ||
685 | mconsole_register_dev(&line_driver->mc); | 682 | mconsole_register_dev(&line_driver->mc); |
686 | return driver; | 683 | return 0; |
687 | } | 684 | } |
688 | 685 | ||
689 | static DEFINE_SPINLOCK(winch_handler_lock); | 686 | static DEFINE_SPINLOCK(winch_handler_lock); |
690 | static LIST_HEAD(winch_handlers); | 687 | static LIST_HEAD(winch_handlers); |
691 | 688 | ||
692 | void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | ||
693 | { | ||
694 | struct line *line; | ||
695 | char *error; | ||
696 | int i; | ||
697 | |||
698 | for(i = 0; i < nlines; i++) { | ||
699 | line = &lines[i]; | ||
700 | INIT_LIST_HEAD(&line->chan_list); | ||
701 | |||
702 | if (line->init_str == NULL) | ||
703 | continue; | ||
704 | |||
705 | line->init_str = kstrdup(line->init_str, GFP_KERNEL); | ||
706 | if (line->init_str == NULL) | ||
707 | printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); | ||
708 | |||
709 | if (parse_chan_pair(line->init_str, line, i, opts, &error)) { | ||
710 | printk(KERN_ERR "parse_chan_pair failed for " | ||
711 | "device %d : %s\n", i, error); | ||
712 | line->valid = 0; | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | |||
717 | struct winch { | 689 | struct winch { |
718 | struct list_head list; | 690 | struct list_head list; |
719 | int fd; | 691 | int fd; |
@@ -777,7 +749,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
777 | if (tty != NULL) { | 749 | if (tty != NULL) { |
778 | line = tty->driver_data; | 750 | line = tty->driver_data; |
779 | if (line != NULL) { | 751 | if (line != NULL) { |
780 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, | 752 | chan_window_size(line, &tty->winsize.ws_row, |
781 | &tty->winsize.ws_col); | 753 | &tty->winsize.ws_col); |
782 | kill_pgrp(tty->pgrp, SIGWINCH, 1); | 754 | kill_pgrp(tty->pgrp, SIGWINCH, 1); |
783 | } | 755 | } |
@@ -807,7 +779,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
807 | .stack = stack }); | 779 | .stack = stack }); |
808 | 780 | ||
809 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | 781 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, |
810 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 782 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
811 | "winch", winch) < 0) { | 783 | "winch", winch) < 0) { |
812 | printk(KERN_ERR "register_winch_irq - failed to register " | 784 | printk(KERN_ERR "register_winch_irq - failed to register " |
813 | "IRQ\n"); | 785 | "IRQ\n"); |
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h index 63df3ca02ac2..0a1834719dba 100644 --- a/arch/um/drivers/line.h +++ b/arch/um/drivers/line.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #include "chan_user.h" | 15 | #include "chan_user.h" |
16 | #include "mconsole_kern.h" | 16 | #include "mconsole_kern.h" |
17 | 17 | ||
18 | /* There's only one modifiable field in this - .mc.list */ | 18 | /* There's only two modifiable fields in this - .mc.list and .driver */ |
19 | struct line_driver { | 19 | struct line_driver { |
20 | const char *name; | 20 | const char *name; |
21 | const char *device_name; | 21 | const char *device_name; |
@@ -28,17 +28,18 @@ struct line_driver { | |||
28 | const int write_irq; | 28 | const int write_irq; |
29 | const char *write_irq_name; | 29 | const char *write_irq_name; |
30 | struct mc_device mc; | 30 | struct mc_device mc; |
31 | struct tty_driver *driver; | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | struct line { | 34 | struct line { |
34 | struct tty_struct *tty; | 35 | struct tty_struct *tty; |
35 | spinlock_t count_lock; | 36 | struct mutex count_lock; |
36 | unsigned long count; | 37 | unsigned long count; |
37 | int valid; | 38 | int valid; |
38 | 39 | ||
39 | char *init_str; | 40 | char *init_str; |
40 | int init_pri; | ||
41 | struct list_head chan_list; | 41 | struct list_head chan_list; |
42 | struct chan *chan_in, *chan_out; | ||
42 | 43 | ||
43 | /*This lock is actually, mostly, local to*/ | 44 | /*This lock is actually, mostly, local to*/ |
44 | spinlock_t lock; | 45 | spinlock_t lock; |
@@ -55,21 +56,12 @@ struct line { | |||
55 | int sigio; | 56 | int sigio; |
56 | struct delayed_work task; | 57 | struct delayed_work task; |
57 | const struct line_driver *driver; | 58 | const struct line_driver *driver; |
58 | int have_irq; | ||
59 | }; | 59 | }; |
60 | 60 | ||
61 | #define LINE_INIT(str, d) \ | ||
62 | { .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \ | ||
63 | .init_str = str, \ | ||
64 | .init_pri = INIT_STATIC, \ | ||
65 | .valid = 1, \ | ||
66 | .lock = __SPIN_LOCK_UNLOCKED((str).lock), \ | ||
67 | .driver = d } | ||
68 | |||
69 | extern void line_close(struct tty_struct *tty, struct file * filp); | 61 | extern void line_close(struct tty_struct *tty, struct file * filp); |
70 | extern int line_open(struct line *lines, struct tty_struct *tty); | 62 | extern int line_open(struct line *lines, struct tty_struct *tty); |
71 | extern int line_setup(struct line *lines, unsigned int sizeof_lines, | 63 | extern int line_setup(char **conf, unsigned nlines, char **def, |
72 | char *init, char **error_out); | 64 | char *init, char *name); |
73 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, | 65 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, |
74 | int len); | 66 | int len); |
75 | extern int line_put_char(struct tty_struct *tty, unsigned char ch); | 67 | extern int line_put_char(struct tty_struct *tty, unsigned char ch); |
@@ -87,10 +79,11 @@ extern char *add_xterm_umid(char *base); | |||
87 | extern int line_setup_irq(int fd, int input, int output, struct line *line, | 79 | extern int line_setup_irq(int fd, int input, int output, struct line *line, |
88 | void *data); | 80 | void *data); |
89 | extern void line_close_chan(struct line *line); | 81 | extern void line_close_chan(struct line *line); |
90 | extern struct tty_driver *register_lines(struct line_driver *line_driver, | 82 | extern int register_lines(struct line_driver *line_driver, |
91 | const struct tty_operations *driver, | 83 | const struct tty_operations *driver, |
92 | struct line *lines, int nlines); | 84 | struct line *lines, int nlines); |
93 | extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); | 85 | extern int setup_one_line(struct line *lines, int n, char *init, |
86 | const struct chan_opts *opts, char **error_out); | ||
94 | extern void close_lines(struct line *lines, int nlines); | 87 | extern void close_lines(struct line *lines, int nlines); |
95 | 88 | ||
96 | extern int line_config(struct line *lines, unsigned int sizeof_lines, | 89 | extern int line_config(struct line *lines, unsigned int sizeof_lines, |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index c70e047eed72..e672bd6d43e3 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -773,7 +773,7 @@ static int __init mconsole_init(void) | |||
773 | register_reboot_notifier(&reboot_notifier); | 773 | register_reboot_notifier(&reboot_notifier); |
774 | 774 | ||
775 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, | 775 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, |
776 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 776 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
777 | "mconsole", (void *)sock); | 777 | "mconsole", (void *)sock); |
778 | if (err) { | 778 | if (err) { |
779 | printk(KERN_ERR "Failed to get IRQ for management console\n"); | 779 | printk(KERN_ERR "Failed to get IRQ for management console\n"); |
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index d2996183e584..95f4416e6d9f 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -161,7 +161,7 @@ static int uml_net_open(struct net_device *dev) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, | 163 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, |
164 | IRQF_DISABLED | IRQF_SHARED, dev->name, dev); | 164 | IRQF_SHARED, dev->name, dev); |
165 | if (err != 0) { | 165 | if (err != 0) { |
166 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); | 166 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); |
167 | err = -ENETUNREACH; | 167 | err = -ENETUNREACH; |
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index a11573be0961..e31680e662a4 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c | |||
@@ -100,7 +100,7 @@ static int port_accept(struct port_list *port) | |||
100 | .port = port }); | 100 | .port = port }); |
101 | 101 | ||
102 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, | 102 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, |
103 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 103 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
104 | "telnetd", conn)) { | 104 | "telnetd", conn)) { |
105 | printk(KERN_ERR "port_accept : failed to get IRQ for " | 105 | printk(KERN_ERR "port_accept : failed to get IRQ for " |
106 | "telnetd\n"); | 106 | "telnetd\n"); |
@@ -184,7 +184,7 @@ void *port_data(int port_num) | |||
184 | } | 184 | } |
185 | 185 | ||
186 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | 186 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, |
187 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 187 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
188 | "port", port)) { | 188 | "port", port)) { |
189 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); | 189 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); |
190 | goto out_close; | 190 | goto out_close; |
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 981085a93f30..b25296e6218a 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c | |||
@@ -131,7 +131,7 @@ static int __init rng_init (void) | |||
131 | random_fd = err; | 131 | random_fd = err; |
132 | 132 | ||
133 | err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, | 133 | err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, |
134 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", | 134 | IRQF_SAMPLE_RANDOM, "random", |
135 | NULL); | 135 | NULL); |
136 | if (err) | 136 | if (err) |
137 | goto err_out_cleanup_hw; | 137 | goto err_out_cleanup_hw; |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 9d8c20af6f80..e09801a1327b 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
@@ -20,12 +20,6 @@ | |||
20 | 20 | ||
21 | static const int ssl_version = 1; | 21 | static const int ssl_version = 1; |
22 | 22 | ||
23 | /* Referenced only by tty_driver below - presumably it's locked correctly | ||
24 | * by the tty driver. | ||
25 | */ | ||
26 | |||
27 | static struct tty_driver *ssl_driver; | ||
28 | |||
29 | #define NR_PORTS 64 | 23 | #define NR_PORTS 64 |
30 | 24 | ||
31 | static void ssl_announce(char *dev_name, int dev) | 25 | static void ssl_announce(char *dev_name, int dev) |
@@ -71,8 +65,9 @@ static struct line_driver driver = { | |||
71 | /* The array is initialized by line_init, at initcall time. The | 65 | /* The array is initialized by line_init, at initcall time. The |
72 | * elements are locked individually as needed. | 66 | * elements are locked individually as needed. |
73 | */ | 67 | */ |
74 | static struct line serial_lines[NR_PORTS] = | 68 | static char *conf[NR_PORTS]; |
75 | { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; | 69 | static char *def_conf = CONFIG_SSL_CHAN; |
70 | static struct line serial_lines[NR_PORTS]; | ||
76 | 71 | ||
77 | static int ssl_config(char *str, char **error_out) | 72 | static int ssl_config(char *str, char **error_out) |
78 | { | 73 | { |
@@ -156,14 +151,14 @@ static void ssl_console_write(struct console *c, const char *string, | |||
156 | unsigned long flags; | 151 | unsigned long flags; |
157 | 152 | ||
158 | spin_lock_irqsave(&line->lock, flags); | 153 | spin_lock_irqsave(&line->lock, flags); |
159 | console_write_chan(&line->chan_list, string, len); | 154 | console_write_chan(line->chan_out, string, len); |
160 | spin_unlock_irqrestore(&line->lock, flags); | 155 | spin_unlock_irqrestore(&line->lock, flags); |
161 | } | 156 | } |
162 | 157 | ||
163 | static struct tty_driver *ssl_console_device(struct console *c, int *index) | 158 | static struct tty_driver *ssl_console_device(struct console *c, int *index) |
164 | { | 159 | { |
165 | *index = c->index; | 160 | *index = c->index; |
166 | return ssl_driver; | 161 | return driver.driver; |
167 | } | 162 | } |
168 | 163 | ||
169 | static int ssl_console_setup(struct console *co, char *options) | 164 | static int ssl_console_setup(struct console *co, char *options) |
@@ -186,17 +181,30 @@ static struct console ssl_cons = { | |||
186 | static int ssl_init(void) | 181 | static int ssl_init(void) |
187 | { | 182 | { |
188 | char *new_title; | 183 | char *new_title; |
184 | int err; | ||
185 | int i; | ||
189 | 186 | ||
190 | printk(KERN_INFO "Initializing software serial port version %d\n", | 187 | printk(KERN_INFO "Initializing software serial port version %d\n", |
191 | ssl_version); | 188 | ssl_version); |
192 | ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, | 189 | |
190 | err = register_lines(&driver, &ssl_ops, serial_lines, | ||
193 | ARRAY_SIZE(serial_lines)); | 191 | ARRAY_SIZE(serial_lines)); |
192 | if (err) | ||
193 | return err; | ||
194 | 194 | ||
195 | new_title = add_xterm_umid(opts.xterm_title); | 195 | new_title = add_xterm_umid(opts.xterm_title); |
196 | if (new_title != NULL) | 196 | if (new_title != NULL) |
197 | opts.xterm_title = new_title; | 197 | opts.xterm_title = new_title; |
198 | 198 | ||
199 | lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); | 199 | for (i = 0; i < NR_PORTS; i++) { |
200 | char *error; | ||
201 | char *s = conf[i]; | ||
202 | if (!s) | ||
203 | s = def_conf; | ||
204 | if (setup_one_line(serial_lines, i, s, &opts, &error)) | ||
205 | printk(KERN_ERR "setup_one_line failed for " | ||
206 | "device %d : %s\n", i, error); | ||
207 | } | ||
200 | 208 | ||
201 | ssl_init_done = 1; | 209 | ssl_init_done = 1; |
202 | register_console(&ssl_cons); | 210 | register_console(&ssl_cons); |
@@ -214,14 +222,7 @@ __uml_exitcall(ssl_exit); | |||
214 | 222 | ||
215 | static int ssl_chan_setup(char *str) | 223 | static int ssl_chan_setup(char *str) |
216 | { | 224 | { |
217 | char *error; | 225 | line_setup(conf, NR_PORTS, &def_conf, str, "serial line"); |
218 | int ret; | ||
219 | |||
220 | ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error); | ||
221 | if(ret < 0) | ||
222 | printk(KERN_ERR "Failed to set up serial line with " | ||
223 | "configuration string \"%s\" : %s\n", str, error); | ||
224 | |||
225 | return 1; | 226 | return 1; |
226 | } | 227 | } |
227 | 228 | ||
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 088776f01908..7663541c372e 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
@@ -27,12 +27,6 @@ | |||
27 | 27 | ||
28 | #define MAX_TTYS (16) | 28 | #define MAX_TTYS (16) |
29 | 29 | ||
30 | /* Referenced only by tty_driver below - presumably it's locked correctly | ||
31 | * by the tty driver. | ||
32 | */ | ||
33 | |||
34 | static struct tty_driver *console_driver; | ||
35 | |||
36 | static void stdio_announce(char *dev_name, int dev) | 30 | static void stdio_announce(char *dev_name, int dev) |
37 | { | 31 | { |
38 | printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, | 32 | printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, |
@@ -76,9 +70,9 @@ static struct line_driver driver = { | |||
76 | /* The array is initialized by line_init, at initcall time. The | 70 | /* The array is initialized by line_init, at initcall time. The |
77 | * elements are locked individually as needed. | 71 | * elements are locked individually as needed. |
78 | */ | 72 | */ |
79 | static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), | 73 | static char *vt_conf[MAX_TTYS]; |
80 | [ 1 ... MAX_TTYS - 1 ] = | 74 | static char *def_conf; |
81 | LINE_INIT(CONFIG_CON_CHAN, &driver) }; | 75 | static struct line vts[MAX_TTYS]; |
82 | 76 | ||
83 | static int con_config(char *str, char **error_out) | 77 | static int con_config(char *str, char **error_out) |
84 | { | 78 | { |
@@ -130,14 +124,14 @@ static void uml_console_write(struct console *console, const char *string, | |||
130 | unsigned long flags; | 124 | unsigned long flags; |
131 | 125 | ||
132 | spin_lock_irqsave(&line->lock, flags); | 126 | spin_lock_irqsave(&line->lock, flags); |
133 | console_write_chan(&line->chan_list, string, len); | 127 | console_write_chan(line->chan_out, string, len); |
134 | spin_unlock_irqrestore(&line->lock, flags); | 128 | spin_unlock_irqrestore(&line->lock, flags); |
135 | } | 129 | } |
136 | 130 | ||
137 | static struct tty_driver *uml_console_device(struct console *c, int *index) | 131 | static struct tty_driver *uml_console_device(struct console *c, int *index) |
138 | { | 132 | { |
139 | *index = c->index; | 133 | *index = c->index; |
140 | return console_driver; | 134 | return driver.driver; |
141 | } | 135 | } |
142 | 136 | ||
143 | static int uml_console_setup(struct console *co, char *options) | 137 | static int uml_console_setup(struct console *co, char *options) |
@@ -160,18 +154,31 @@ static struct console stdiocons = { | |||
160 | static int stdio_init(void) | 154 | static int stdio_init(void) |
161 | { | 155 | { |
162 | char *new_title; | 156 | char *new_title; |
157 | int err; | ||
158 | int i; | ||
163 | 159 | ||
164 | console_driver = register_lines(&driver, &console_ops, vts, | 160 | err = register_lines(&driver, &console_ops, vts, |
165 | ARRAY_SIZE(vts)); | 161 | ARRAY_SIZE(vts)); |
166 | if (console_driver == NULL) | 162 | if (err) |
167 | return -1; | 163 | return err; |
164 | |||
168 | printk(KERN_INFO "Initialized stdio console driver\n"); | 165 | printk(KERN_INFO "Initialized stdio console driver\n"); |
169 | 166 | ||
170 | new_title = add_xterm_umid(opts.xterm_title); | 167 | new_title = add_xterm_umid(opts.xterm_title); |
171 | if(new_title != NULL) | 168 | if(new_title != NULL) |
172 | opts.xterm_title = new_title; | 169 | opts.xterm_title = new_title; |
173 | 170 | ||
174 | lines_init(vts, ARRAY_SIZE(vts), &opts); | 171 | for (i = 0; i < MAX_TTYS; i++) { |
172 | char *error; | ||
173 | char *s = vt_conf[i]; | ||
174 | if (!s) | ||
175 | s = def_conf; | ||
176 | if (!s) | ||
177 | s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN; | ||
178 | if (setup_one_line(vts, i, s, &opts, &error)) | ||
179 | printk(KERN_ERR "setup_one_line failed for " | ||
180 | "device %d : %s\n", i, error); | ||
181 | } | ||
175 | 182 | ||
176 | con_init_done = 1; | 183 | con_init_done = 1; |
177 | register_console(&stdiocons); | 184 | register_console(&stdiocons); |
@@ -189,14 +196,7 @@ __uml_exitcall(console_exit); | |||
189 | 196 | ||
190 | static int console_chan_setup(char *str) | 197 | static int console_chan_setup(char *str) |
191 | { | 198 | { |
192 | char *error; | 199 | line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console"); |
193 | int ret; | ||
194 | |||
195 | ret = line_setup(vts, ARRAY_SIZE(vts), str, &error); | ||
196 | if(ret < 0) | ||
197 | printk(KERN_ERR "Failed to set up console with " | ||
198 | "configuration string \"%s\" : %s\n", str, error); | ||
199 | |||
200 | return 1; | 200 | return 1; |
201 | } | 201 | } |
202 | __setup("con", console_chan_setup); | 202 | __setup("con", console_chan_setup); |
diff --git a/arch/um/drivers/ubd_user.h b/arch/um/drivers/ubd.h index 3845051f1b10..3845051f1b10 100644 --- a/arch/um/drivers/ubd_user.h +++ b/arch/um/drivers/ubd.h | |||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 944453a3ec99..20505cafa299 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -19,40 +19,26 @@ | |||
19 | 19 | ||
20 | #define UBD_SHIFT 4 | 20 | #define UBD_SHIFT 4 |
21 | 21 | ||
22 | #include "linux/kernel.h" | 22 | #include <linux/module.h> |
23 | #include "linux/module.h" | 23 | #include <linux/init.h> |
24 | #include "linux/blkdev.h" | 24 | #include <linux/blkdev.h> |
25 | #include "linux/ata.h" | 25 | #include <linux/ata.h> |
26 | #include "linux/hdreg.h" | 26 | #include <linux/hdreg.h> |
27 | #include "linux/init.h" | 27 | #include <linux/cdrom.h> |
28 | #include "linux/cdrom.h" | 28 | #include <linux/proc_fs.h> |
29 | #include "linux/proc_fs.h" | 29 | #include <linux/seq_file.h> |
30 | #include "linux/seq_file.h" | 30 | #include <linux/ctype.h> |
31 | #include "linux/ctype.h" | 31 | #include <linux/slab.h> |
32 | #include "linux/capability.h" | 32 | #include <linux/vmalloc.h> |
33 | #include "linux/mm.h" | 33 | #include <linux/platform_device.h> |
34 | #include "linux/slab.h" | 34 | #include <linux/scatterlist.h> |
35 | #include "linux/vmalloc.h" | 35 | #include <asm/tlbflush.h> |
36 | #include "linux/mutex.h" | ||
37 | #include "linux/blkpg.h" | ||
38 | #include "linux/genhd.h" | ||
39 | #include "linux/spinlock.h" | ||
40 | #include "linux/platform_device.h" | ||
41 | #include "linux/scatterlist.h" | ||
42 | #include "asm/segment.h" | ||
43 | #include "asm/uaccess.h" | ||
44 | #include "asm/irq.h" | ||
45 | #include "asm/types.h" | ||
46 | #include "asm/tlbflush.h" | ||
47 | #include "mem_user.h" | ||
48 | #include "kern_util.h" | 36 | #include "kern_util.h" |
49 | #include "mconsole_kern.h" | 37 | #include "mconsole_kern.h" |
50 | #include "init.h" | 38 | #include "init.h" |
51 | #include "irq_user.h" | ||
52 | #include "irq_kern.h" | 39 | #include "irq_kern.h" |
53 | #include "ubd_user.h" | 40 | #include "ubd.h" |
54 | #include "os.h" | 41 | #include "os.h" |
55 | #include "mem.h" | ||
56 | #include "cow.h" | 42 | #include "cow.h" |
57 | 43 | ||
58 | enum ubd_req { UBD_READ, UBD_WRITE }; | 44 | enum ubd_req { UBD_READ, UBD_WRITE }; |
@@ -1115,7 +1101,7 @@ static int __init ubd_driver_init(void){ | |||
1115 | return 0; | 1101 | return 0; |
1116 | } | 1102 | } |
1117 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 1103 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
1118 | IRQF_DISABLED, "ubd", ubd_devs); | 1104 | 0, "ubd", ubd_devs); |
1119 | if(err != 0) | 1105 | if(err != 0) |
1120 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | 1106 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); |
1121 | return 0; | 1107 | return 0; |
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index 007b94d97726..ffe02c431dea 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c | |||
@@ -15,14 +15,12 @@ | |||
15 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
16 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
17 | #include <sys/param.h> | 17 | #include <sys/param.h> |
18 | #include "asm/types.h" | ||
19 | #include "ubd_user.h" | ||
20 | #include "os.h" | ||
21 | #include "cow.h" | ||
22 | |||
23 | #include <endian.h> | 18 | #include <endian.h> |
24 | #include <byteswap.h> | 19 | #include <byteswap.h> |
25 | 20 | ||
21 | #include "ubd.h" | ||
22 | #include "os.h" | ||
23 | |||
26 | void ignore_sigwinch_sig(void) | 24 | void ignore_sigwinch_sig(void) |
27 | { | 25 | { |
28 | signal(SIGWINCH, SIG_IGN); | 26 | signal(SIGWINCH, SIG_IGN); |
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index b646bccef37a..8bd130f0bda3 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c | |||
@@ -50,7 +50,7 @@ int xterm_fd(int socket, int *pid_out) | |||
50 | init_completion(&data->ready); | 50 | init_completion(&data->ready); |
51 | 51 | ||
52 | err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, | 52 | err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, |
53 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 53 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
54 | "xterm", data); | 54 | "xterm", data); |
55 | if (err) { | 55 | if (err) { |
56 | printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " | 56 | printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " |