aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 21:29:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 21:29:53 -0400
commitfa453a625de5b8ee9ada0a5b329df3f88751c615 (patch)
tree7a9e04d4a44bb929e96bd9bebb7b97cb733d1ecb /arch/um/drivers
parent30eebb54b13ef198a3f1a143ee9dd68f295c60de (diff)
parent3463ff4439661d8107ac024329b5fe01d6e5117b (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.h18
-rw-r--r--arch/um/drivers/chan_kern.c198
-rw-r--r--arch/um/drivers/chan_user.h2
-rw-r--r--arch/um/drivers/line.c258
-rw-r--r--arch/um/drivers/line.h29
-rw-r--r--arch/um/drivers/mconsole_kern.c2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/port_kern.c4
-rw-r--r--arch/um/drivers/random.c2
-rw-r--r--arch/um/drivers/ssl.c41
-rw-r--r--arch/um/drivers/stdio_console.c46
-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.c46
-rw-r--r--arch/um/drivers/ubd_user.c8
-rw-r--r--arch/um/drivers/xterm_kern.c2
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
30extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, 30extern void chan_interrupt(struct line *line,
31 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
32extern int parse_chan_pair(char *str, struct line *line, int device, 32extern 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);
34extern int write_chan(struct list_head *chans, const char *buf, int len, 34extern int write_chan(struct chan *chan, const char *buf, int len,
35 int write_irq); 35 int write_irq);
36extern int console_write_chan(struct list_head *chans, const char *buf, 36extern int console_write_chan(struct chan *chan, const char *buf,
37 int len); 37 int len);
38extern int console_open_chan(struct line *line, struct console *co); 38extern int console_open_chan(struct line *line, struct console *co);
39extern void deactivate_chan(struct list_head *chans, int irq); 39extern void deactivate_chan(struct chan *chan, int irq);
40extern void reactivate_chan(struct list_head *chans, int irq); 40extern void reactivate_chan(struct chan *chan, int irq);
41extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 41extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
42extern int enable_chan(struct line *line); 42extern int enable_chan(struct line *line);
43extern void close_chan(struct list_head *chans, int delay_free_irq); 43extern void close_chan(struct line *line);
44extern int chan_window_size(struct list_head *chans, 44extern 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);
47extern int chan_config_string(struct list_head *chans, char *str, int size, 47extern 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
143void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 143void 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) { 149static 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
157int enable_chan(struct line *line) 157int 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
247void close_chan(struct list_head *chans, int delay_free_irq) 249void 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
261void deactivate_chan(struct list_head *chans, int irq) 263void 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
274void reactivate_chan(struct list_head *chans, int irq) 269void 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
287int write_chan(struct list_head *chans, const char *buf, int len, 275int 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
312int console_write_chan(struct list_head *chans, const char *buf, int len) 292int 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
343int chan_window_size(struct list_head *chans, unsigned short *rows_out, 318int 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
432int chan_config_string(struct list_head *chans, char *str, int size, 411int 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
585void chan_interrupt(struct list_head *chans, struct delayed_work *task, 565void 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
17enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
18
19struct chan_ops { 17struct 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
28static 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
342static irqreturn_t line_write_interrupt(int irq, void *data) 332static 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)
371int line_setup_irq(int fd, int input, int output, struct line *line, void *data) 362int 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
441out_unlock: 425out_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
480out_unlock: 460out_unlock:
481 spin_unlock(&line->count_lock); 461 mutex_unlock(&line->count_lock);
482} 462}
483 463
484void close_lines(struct line *lines, int nlines) 464void 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
492static int setup_one_line(struct line *lines, int n, char *init, int init_prio, 472int 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;
515out: 521out:
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
527int line_setup(struct line *lines, unsigned int num, char *init, 533int 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
560out:
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
570int line_config(struct line *lines, unsigned int num, char *str, 566int 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
595int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 590int 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
641int line_remove(struct line *lines, unsigned int num, int n, char **error_out) 636int 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
653struct tty_driver *register_lines(struct line_driver *line_driver, 645int 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
689static DEFINE_SPINLOCK(winch_handler_lock); 686static DEFINE_SPINLOCK(winch_handler_lock);
690static LIST_HEAD(winch_handlers); 687static LIST_HEAD(winch_handlers);
691 688
692void 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
717struct winch { 689struct 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 */
19struct line_driver { 19struct 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
33struct line { 34struct 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
69extern void line_close(struct tty_struct *tty, struct file * filp); 61extern void line_close(struct tty_struct *tty, struct file * filp);
70extern int line_open(struct line *lines, struct tty_struct *tty); 62extern int line_open(struct line *lines, struct tty_struct *tty);
71extern int line_setup(struct line *lines, unsigned int sizeof_lines, 63extern int line_setup(char **conf, unsigned nlines, char **def,
72 char *init, char **error_out); 64 char *init, char *name);
73extern int line_write(struct tty_struct *tty, const unsigned char *buf, 65extern int line_write(struct tty_struct *tty, const unsigned char *buf,
74 int len); 66 int len);
75extern int line_put_char(struct tty_struct *tty, unsigned char ch); 67extern int line_put_char(struct tty_struct *tty, unsigned char ch);
@@ -87,10 +79,11 @@ extern char *add_xterm_umid(char *base);
87extern int line_setup_irq(int fd, int input, int output, struct line *line, 79extern int line_setup_irq(int fd, int input, int output, struct line *line,
88 void *data); 80 void *data);
89extern void line_close_chan(struct line *line); 81extern void line_close_chan(struct line *line);
90extern struct tty_driver *register_lines(struct line_driver *line_driver, 82extern 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);
93extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); 85extern int setup_one_line(struct line *lines, int n, char *init,
86 const struct chan_opts *opts, char **error_out);
94extern void close_lines(struct line *lines, int nlines); 87extern void close_lines(struct line *lines, int nlines);
95 88
96extern int line_config(struct line *lines, unsigned int sizeof_lines, 89extern 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
21static const int ssl_version = 1; 21static 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
27static struct tty_driver *ssl_driver;
28
29#define NR_PORTS 64 23#define NR_PORTS 64
30 24
31static void ssl_announce(char *dev_name, int dev) 25static 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 */
74static struct line serial_lines[NR_PORTS] = 68static char *conf[NR_PORTS];
75 { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; 69static char *def_conf = CONFIG_SSL_CHAN;
70static struct line serial_lines[NR_PORTS];
76 71
77static int ssl_config(char *str, char **error_out) 72static 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
163static struct tty_driver *ssl_console_device(struct console *c, int *index) 158static 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
169static int ssl_console_setup(struct console *co, char *options) 164static int ssl_console_setup(struct console *co, char *options)
@@ -186,17 +181,30 @@ static struct console ssl_cons = {
186static int ssl_init(void) 181static 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
215static int ssl_chan_setup(char *str) 223static 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
34static struct tty_driver *console_driver;
35
36static void stdio_announce(char *dev_name, int dev) 30static 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 */
79static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 73static char *vt_conf[MAX_TTYS];
80 [ 1 ... MAX_TTYS - 1 ] = 74static char *def_conf;
81 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 75static struct line vts[MAX_TTYS];
82 76
83static int con_config(char *str, char **error_out) 77static 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
137static struct tty_driver *uml_console_device(struct console *c, int *index) 131static 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
143static int uml_console_setup(struct console *co, char *options) 137static int uml_console_setup(struct console *co, char *options)
@@ -160,18 +154,31 @@ static struct console stdiocons = {
160static int stdio_init(void) 154static 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
190static int console_chan_setup(char *str) 197static 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
58enum ubd_req { UBD_READ, UBD_WRITE }; 44enum 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
26void ignore_sigwinch_sig(void) 24void 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, "