aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/chan_kern.c273
-rw-r--r--arch/um/drivers/line.c298
-rw-r--r--arch/um/drivers/mconsole_kern.c232
-rw-r--r--arch/um/drivers/mconsole_user.c12
-rw-r--r--arch/um/drivers/net_kern.c8
-rw-r--r--arch/um/drivers/ssl.c47
-rw-r--r--arch/um/drivers/stdio_console.c33
-rw-r--r--arch/um/drivers/ubd_kern.c15
8 files changed, 530 insertions, 388 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 5b58fad45290..cd13b91b9ff6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 58{
59 my_puts("Using a channel type which is configured out of " 59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 60 "UML\n");
61 return(NULL); 61 return NULL;
62} 62}
63 63
64static int not_configged_open(int input, int output, int primary, void *data, 64static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
66{ 66{
67 my_puts("Using a channel type which is configured out of " 67 my_puts("Using a channel type which is configured out of "
68 "UML\n"); 68 "UML\n");
69 return(-ENODEV); 69 return -ENODEV;
70} 70}
71 71
72static void not_configged_close(int fd, void *data) 72static void not_configged_close(int fd, void *data)
@@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
79{ 79{
80 my_puts("Using a channel type which is configured out of " 80 my_puts("Using a channel type which is configured out of "
81 "UML\n"); 81 "UML\n");
82 return(-EIO); 82 return -EIO;
83} 83}
84 84
85static int not_configged_write(int fd, const char *buf, int len, void *data) 85static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 86{
87 my_puts("Using a channel type which is configured out of " 87 my_puts("Using a channel type which is configured out of "
88 "UML\n"); 88 "UML\n");
89 return(-EIO); 89 return -EIO;
90} 90}
91 91
92static int not_configged_console_write(int fd, const char *buf, int len) 92static int not_configged_console_write(int fd, const char *buf, int len)
93{ 93{
94 my_puts("Using a channel type which is configured out of " 94 my_puts("Using a channel type which is configured out of "
95 "UML\n"); 95 "UML\n");
96 return(-EIO); 96 return -EIO;
97} 97}
98 98
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 99static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
101{ 101{
102 my_puts("Using a channel type which is configured out of " 102 my_puts("Using a channel type which is configured out of "
103 "UML\n"); 103 "UML\n");
104 return(-ENODEV); 104 return -ENODEV;
105} 105}
106 106
107static void not_configged_free(void *data) 107static void not_configged_free(void *data)
@@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
135 n = os_read_file(fd, c_out, sizeof(*c_out)); 135 n = os_read_file(fd, c_out, sizeof(*c_out));
136 136
137 if(n == -EAGAIN) 137 if(n == -EAGAIN)
138 return(0); 138 return 0;
139 else if(n == 0) 139 else if(n == 0)
140 return(-EIO); 140 return -EIO;
141 return(n); 141 return n;
142} 142}
143 143
144/* XXX Trivial wrapper around os_write_file */ 144/* XXX Trivial wrapper around os_write_file */
145 145
146int generic_write(int fd, const char *buf, int n, void *unused) 146int generic_write(int fd, const char *buf, int n, void *unused)
147{ 147{
148 return(os_write_file(fd, buf, n)); 148 return os_write_file(fd, buf, n);
149} 149}
150 150
151int generic_window_size(int fd, void *unused, unsigned short *rows_out, 151int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
156 156
157 ret = os_window_size(fd, &rows, &cols); 157 ret = os_window_size(fd, &rows, &cols);
158 if(ret < 0) 158 if(ret < 0)
159 return(ret); 159 return ret;
160 160
161 ret = ((*rows_out != rows) || (*cols_out != cols)); 161 ret = ((*rows_out != rows) || (*cols_out != cols));
162 162
163 *rows_out = rows; 163 *rows_out = rows;
164 *cols_out = cols; 164 *cols_out = cols;
165 165
166 return(ret); 166 return ret;
167} 167}
168 168
169void generic_free(void *data) 169void generic_free(void *data)
@@ -186,25 +186,29 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
186 } 186 }
187 } 187 }
188 188
189 if((tty->flip.flag_buf_ptr == NULL) || 189 if((tty->flip.flag_buf_ptr == NULL) ||
190 (tty->flip.char_buf_ptr == NULL)) 190 (tty->flip.char_buf_ptr == NULL))
191 return; 191 return;
192 tty_insert_flip_char(tty, ch, TTY_NORMAL); 192 tty_insert_flip_char(tty, ch, TTY_NORMAL);
193} 193}
194 194
195static int open_one_chan(struct chan *chan, int input, int output, int primary) 195static int open_one_chan(struct chan *chan)
196{ 196{
197 int fd; 197 int fd;
198 198
199 if(chan->opened) return(0); 199 if(chan->opened)
200 if(chan->ops->open == NULL) fd = 0; 200 return 0;
201 else fd = (*chan->ops->open)(input, output, primary, chan->data, 201
202 &chan->dev); 202 if(chan->ops->open == NULL)
203 if(fd < 0) return(fd); 203 fd = 0;
204 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
205 chan->data, &chan->dev);
206 if(fd < 0)
207 return fd;
204 chan->fd = fd; 208 chan->fd = fd;
205 209
206 chan->opened = 1; 210 chan->opened = 1;
207 return(0); 211 return 0;
208} 212}
209 213
210int open_chan(struct list_head *chans) 214int open_chan(struct list_head *chans)
@@ -215,11 +219,11 @@ int open_chan(struct list_head *chans)
215 219
216 list_for_each(ele, chans){ 220 list_for_each(ele, chans){
217 chan = list_entry(ele, struct chan, list); 221 chan = list_entry(ele, struct chan, list);
218 ret = open_one_chan(chan, chan->input, chan->output, 222 ret = open_one_chan(chan);
219 chan->primary); 223 if(chan->primary)
220 if(chan->primary) err = ret; 224 err = ret;
221 } 225 }
222 return(err); 226 return err;
223} 227}
224 228
225void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 229void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -236,20 +240,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
236 } 240 }
237} 241}
238 242
239void enable_chan(struct list_head *chans, struct tty_struct *tty) 243void enable_chan(struct line *line)
240{ 244{
241 struct list_head *ele; 245 struct list_head *ele;
242 struct chan *chan; 246 struct chan *chan;
243 247
244 list_for_each(ele, chans){ 248 list_for_each(ele, &line->chan_list){
245 chan = list_entry(ele, struct chan, list); 249 chan = list_entry(ele, struct chan, list);
246 if(!chan->opened) continue; 250 if(open_one_chan(chan))
251 continue;
252
253 if(chan->enabled)
254 continue;
255 line_setup_irq(chan->fd, chan->input, chan->output, line,
256 chan);
257 chan->enabled = 1;
258 }
259}
260
261static LIST_HEAD(irqs_to_free);
262
263void free_irqs(void)
264{
265 struct chan *chan;
266
267 while(!list_empty(&irqs_to_free)){
268 chan = list_entry(irqs_to_free.next, struct chan, free_list);
269 list_del(&chan->free_list);
247 270
248 line_setup_irq(chan->fd, chan->input, chan->output, tty); 271 if(chan->input)
272 free_irq(chan->line->driver->read_irq, chan);
273 if(chan->output)
274 free_irq(chan->line->driver->write_irq, chan);
275 chan->enabled = 0;
276 }
277}
278
279static void close_one_chan(struct chan *chan, int delay_free_irq)
280{
281 if(!chan->opened)
282 return;
283
284 if(delay_free_irq){
285 list_add(&chan->free_list, &irqs_to_free);
249 } 286 }
287 else {
288 if(chan->input)
289 free_irq(chan->line->driver->read_irq, chan);
290 if(chan->output)
291 free_irq(chan->line->driver->write_irq, chan);
292 chan->enabled = 0;
293 }
294 if(chan->ops->close != NULL)
295 (*chan->ops->close)(chan->fd, chan->data);
296
297 chan->opened = 0;
298 chan->fd = -1;
250} 299}
251 300
252void close_chan(struct list_head *chans) 301void close_chan(struct list_head *chans, int delay_free_irq)
253{ 302{
254 struct chan *chan; 303 struct chan *chan;
255 304
@@ -259,15 +308,37 @@ void close_chan(struct list_head *chans)
259 * so it must be the last closed. 308 * so it must be the last closed.
260 */ 309 */
261 list_for_each_entry_reverse(chan, chans, list) { 310 list_for_each_entry_reverse(chan, chans, list) {
262 if(!chan->opened) continue; 311 close_one_chan(chan, delay_free_irq);
263 if(chan->ops->close != NULL) 312 }
264 (*chan->ops->close)(chan->fd, chan->data); 313}
265 chan->opened = 0; 314
266 chan->fd = -1; 315void deactivate_chan(struct list_head *chans, int irq)
316{
317 struct list_head *ele;
318
319 struct chan *chan;
320 list_for_each(ele, chans) {
321 chan = list_entry(ele, struct chan, list);
322
323 if(chan->enabled && chan->input)
324 deactivate_fd(chan->fd, irq);
325 }
326}
327
328void reactivate_chan(struct list_head *chans, int irq)
329{
330 struct list_head *ele;
331 struct chan *chan;
332
333 list_for_each(ele, chans) {
334 chan = list_entry(ele, struct chan, list);
335
336 if(chan->enabled && chan->input)
337 reactivate_fd(chan->fd, irq);
267 } 338 }
268} 339}
269 340
270int write_chan(struct list_head *chans, const char *buf, int len, 341int write_chan(struct list_head *chans, const char *buf, int len,
271 int write_irq) 342 int write_irq)
272{ 343{
273 struct list_head *ele; 344 struct list_head *ele;
@@ -285,7 +356,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
285 reactivate_fd(chan->fd, write_irq); 356 reactivate_fd(chan->fd, write_irq);
286 } 357 }
287 } 358 }
288 return(ret); 359 return ret;
289} 360}
290 361
291int console_write_chan(struct list_head *chans, const char *buf, int len) 362int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -301,19 +372,18 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
301 n = chan->ops->console_write(chan->fd, buf, len); 372 n = chan->ops->console_write(chan->fd, buf, len);
302 if(chan->primary) ret = n; 373 if(chan->primary) ret = n;
303 } 374 }
304 return(ret); 375 return ret;
305} 376}
306 377
307int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 378int console_open_chan(struct line *line, struct console *co,
379 struct chan_opts *opts)
308{ 380{
309 if (!list_empty(&line->chan_list)) 381 int err;
310 return 0; 382
383 err = open_chan(&line->chan_list);
384 if(err)
385 return err;
311 386
312 if (0 != parse_chan_pair(line->init_str, &line->chan_list,
313 line->init_pri, co->index, opts))
314 return -1;
315 if (0 != open_chan(&line->chan_list))
316 return -1;
317 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 387 printk("Console initialized on /dev/%s%d\n",co->name,co->index);
318 return 0; 388 return 0;
319} 389}
@@ -327,32 +397,36 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
327 list_for_each(ele, chans){ 397 list_for_each(ele, chans){
328 chan = list_entry(ele, struct chan, list); 398 chan = list_entry(ele, struct chan, list);
329 if(chan->primary){ 399 if(chan->primary){
330 if(chan->ops->window_size == NULL) return(0); 400 if(chan->ops->window_size == NULL)
331 return(chan->ops->window_size(chan->fd, chan->data, 401 return 0;
332 rows_out, cols_out)); 402 return chan->ops->window_size(chan->fd, chan->data,
403 rows_out, cols_out);
333 } 404 }
334 } 405 }
335 return(0); 406 return 0;
336} 407}
337 408
338void free_one_chan(struct chan *chan) 409void free_one_chan(struct chan *chan, int delay_free_irq)
339{ 410{
340 list_del(&chan->list); 411 list_del(&chan->list);
412
413 close_one_chan(chan, delay_free_irq);
414
341 if(chan->ops->free != NULL) 415 if(chan->ops->free != NULL)
342 (*chan->ops->free)(chan->data); 416 (*chan->ops->free)(chan->data);
343 free_irq_by_fd(chan->fd); 417
344 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 418 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
345 kfree(chan); 419 kfree(chan);
346} 420}
347 421
348void free_chan(struct list_head *chans) 422void free_chan(struct list_head *chans, int delay_free_irq)
349{ 423{
350 struct list_head *ele, *next; 424 struct list_head *ele, *next;
351 struct chan *chan; 425 struct chan *chan;
352 426
353 list_for_each_safe(ele, next, chans){ 427 list_for_each_safe(ele, next, chans){
354 chan = list_entry(ele, struct chan, list); 428 chan = list_entry(ele, struct chan, list);
355 free_one_chan(chan); 429 free_one_chan(chan, delay_free_irq);
356 } 430 }
357} 431}
358 432
@@ -363,23 +437,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
363 437
364 if(chan == NULL){ 438 if(chan == NULL){
365 CONFIG_CHUNK(str, size, n, "none", 1); 439 CONFIG_CHUNK(str, size, n, "none", 1);
366 return(n); 440 return n;
367 } 441 }
368 442
369 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 443 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
370 444
371 if(chan->dev == NULL){ 445 if(chan->dev == NULL){
372 CONFIG_CHUNK(str, size, n, "", 1); 446 CONFIG_CHUNK(str, size, n, "", 1);
373 return(n); 447 return n;
374 } 448 }
375 449
376 CONFIG_CHUNK(str, size, n, ":", 0); 450 CONFIG_CHUNK(str, size, n, ":", 0);
377 CONFIG_CHUNK(str, size, n, chan->dev, 0); 451 CONFIG_CHUNK(str, size, n, chan->dev, 0);
378 452
379 return(n); 453 return n;
380} 454}
381 455
382static int chan_pair_config_string(struct chan *in, struct chan *out, 456static int chan_pair_config_string(struct chan *in, struct chan *out,
383 char *str, int size, char **error_out) 457 char *str, int size, char **error_out)
384{ 458{
385 int n; 459 int n;
@@ -390,7 +464,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
390 464
391 if(in == out){ 465 if(in == out){
392 CONFIG_CHUNK(str, size, n, "", 1); 466 CONFIG_CHUNK(str, size, n, "", 1);
393 return(n); 467 return n;
394 } 468 }
395 469
396 CONFIG_CHUNK(str, size, n, ",", 1); 470 CONFIG_CHUNK(str, size, n, ",", 1);
@@ -399,10 +473,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
399 size -= n; 473 size -= n;
400 CONFIG_CHUNK(str, size, n, "", 1); 474 CONFIG_CHUNK(str, size, n, "", 1);
401 475
402 return(n); 476 return n;
403} 477}
404 478
405int chan_config_string(struct list_head *chans, char *str, int size, 479int chan_config_string(struct list_head *chans, char *str, int size,
406 char **error_out) 480 char **error_out)
407{ 481{
408 struct list_head *ele; 482 struct list_head *ele;
@@ -418,7 +492,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
418 out = chan; 492 out = chan;
419 } 493 }
420 494
421 return(chan_pair_config_string(in, out, str, size, error_out)); 495 return chan_pair_config_string(in, out, str, size, error_out);
422} 496}
423 497
424struct chan_type { 498struct chan_type {
@@ -462,7 +536,7 @@ struct chan_type chan_table[] = {
462#endif 536#endif
463}; 537};
464 538
465static struct chan *parse_chan(char *str, int pri, int device, 539static struct chan *parse_chan(struct line *line, char *str, int device,
466 struct chan_opts *opts) 540 struct chan_opts *opts)
467{ 541{
468 struct chan_type *entry; 542 struct chan_type *entry;
@@ -484,36 +558,42 @@ static struct chan *parse_chan(char *str, int pri, int device,
484 if(ops == NULL){ 558 if(ops == NULL){
485 my_printf("parse_chan couldn't parse \"%s\"\n", 559 my_printf("parse_chan couldn't parse \"%s\"\n",
486 str); 560 str);
487 return(NULL); 561 return NULL;
488 } 562 }
489 if(ops->init == NULL) return(NULL); 563 if(ops->init == NULL)
564 return NULL;
490 data = (*ops->init)(str, device, opts); 565 data = (*ops->init)(str, device, opts);
491 if(data == NULL) return(NULL); 566 if(data == NULL)
567 return NULL;
492 568
493 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 569 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
494 if(chan == NULL) return(NULL); 570 if(chan == NULL)
571 return NULL;
495 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 572 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
573 .free_list =
574 LIST_HEAD_INIT(chan->free_list),
575 .line = line,
496 .primary = 1, 576 .primary = 1,
497 .input = 0, 577 .input = 0,
498 .output = 0, 578 .output = 0,
499 .opened = 0, 579 .opened = 0,
580 .enabled = 0,
500 .fd = -1, 581 .fd = -1,
501 .pri = pri,
502 .ops = ops, 582 .ops = ops,
503 .data = data }); 583 .data = data });
504 return(chan); 584 return chan;
505} 585}
506 586
507int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 587int parse_chan_pair(char *str, struct line *line, int device,
508 struct chan_opts *opts) 588 struct chan_opts *opts)
509{ 589{
590 struct list_head *chans = &line->chan_list;
510 struct chan *new, *chan; 591 struct chan *new, *chan;
511 char *in, *out; 592 char *in, *out;
512 593
513 if(!list_empty(chans)){ 594 if(!list_empty(chans)){
514 chan = list_entry(chans->next, struct chan, list); 595 chan = list_entry(chans->next, struct chan, list);
515 if(chan->pri >= pri) return(0); 596 free_chan(chans, 0);
516 free_chan(chans);
517 INIT_LIST_HEAD(chans); 597 INIT_LIST_HEAD(chans);
518 } 598 }
519 599
@@ -522,24 +602,30 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
522 in = str; 602 in = str;
523 *out = '\0'; 603 *out = '\0';
524 out++; 604 out++;
525 new = parse_chan(in, pri, device, opts); 605 new = parse_chan(line, in, device, opts);
526 if(new == NULL) return(-1); 606 if(new == NULL)
607 return -1;
608
527 new->input = 1; 609 new->input = 1;
528 list_add(&new->list, chans); 610 list_add(&new->list, chans);
529 611
530 new = parse_chan(out, pri, device, opts); 612 new = parse_chan(line, out, device, opts);
531 if(new == NULL) return(-1); 613 if(new == NULL)
614 return -1;
615
532 list_add(&new->list, chans); 616 list_add(&new->list, chans);
533 new->output = 1; 617 new->output = 1;
534 } 618 }
535 else { 619 else {
536 new = parse_chan(str, pri, device, opts); 620 new = parse_chan(line, str, device, opts);
537 if(new == NULL) return(-1); 621 if(new == NULL)
622 return -1;
623
538 list_add(&new->list, chans); 624 list_add(&new->list, chans);
539 new->input = 1; 625 new->input = 1;
540 new->output = 1; 626 new->output = 1;
541 } 627 }
542 return(0); 628 return 0;
543} 629}
544 630
545int chan_out_fd(struct list_head *chans) 631int chan_out_fd(struct list_head *chans)
@@ -550,9 +636,9 @@ int chan_out_fd(struct list_head *chans)
550 list_for_each(ele, chans){ 636 list_for_each(ele, chans){
551 chan = list_entry(ele, struct chan, list); 637 chan = list_entry(ele, struct chan, list);
552 if(chan->primary && chan->output) 638 if(chan->primary && chan->output)
553 return(chan->fd); 639 return chan->fd;
554 } 640 }
555 return(-1); 641 return -1;
556} 642}
557 643
558void chan_interrupt(struct list_head *chans, struct work_struct *task, 644void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -567,9 +653,9 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
567 chan = list_entry(ele, struct chan, list); 653 chan = list_entry(ele, struct chan, list);
568 if(!chan->input || (chan->ops->read == NULL)) continue; 654 if(!chan->input || (chan->ops->read == NULL)) continue;
569 do { 655 do {
570 if((tty != NULL) && 656 if((tty != NULL) &&
571 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 657 (tty->flip.count >= TTY_FLIPBUF_SIZE)){
572 schedule_work(task); 658 schedule_delayed_work(task, 1);
573 goto out; 659 goto out;
574 } 660 }
575 err = chan->ops->read(chan->fd, &c, chan->data); 661 err = chan->ops->read(chan->fd, &c, chan->data);
@@ -582,29 +668,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
582 if(chan->primary){ 668 if(chan->primary){
583 if(tty != NULL) 669 if(tty != NULL)
584 tty_hangup(tty); 670 tty_hangup(tty);
585 line_disable(tty, irq); 671 close_chan(chans, 1);
586 close_chan(chans);
587 free_chan(chans);
588 return; 672 return;
589 } 673 }
590 else { 674 else close_one_chan(chan, 1);
591 if(chan->ops->close != NULL)
592 chan->ops->close(chan->fd, chan->data);
593 free_one_chan(chan);
594 }
595 } 675 }
596 } 676 }
597 out: 677 out:
598 if(tty) tty_flip_buffer_push(tty); 678 if(tty) tty_flip_buffer_push(tty);
599} 679}
600
601/*
602 * Overrides for Emacs so that we follow Linus's tabbing style.
603 * Emacs will notice this stuff at the end of the file and automatically
604 * adjust the settings for this buffer only. This must remain at the end
605 * of the file.
606 * ---------------------------------------------------------------------------
607 * Local variables:
608 * c-file-style: "linux"
609 * End:
610 */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index e0fdffa2d542..46ceb25a9959 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,11 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 if(!line->throttled)
40 chan_interrupt(&line->chan_list, &line->task, line->tty,
41 line->driver->read_irq);
40} 42}
41 43
42/* Returns the free space inside the ring buffer of this line. 44/* Returns the free space inside the ring buffer of this line.
@@ -124,7 +126,8 @@ static int buffer_data(struct line *line, const char *buf, int len)
124 if (len < end){ 126 if (len < end){
125 memcpy(line->tail, buf, len); 127 memcpy(line->tail, buf, len);
126 line->tail += len; 128 line->tail += len;
127 } else { 129 }
130 else {
128 /* The circular buffer is wrapping */ 131 /* The circular buffer is wrapping */
129 memcpy(line->tail, buf, end); 132 memcpy(line->tail, buf, end);
130 buf += end; 133 buf += end;
@@ -170,7 +173,7 @@ static int flush_buffer(struct line *line)
170 } 173 }
171 174
172 count = line->tail - line->head; 175 count = line->tail - line->head;
173 n = write_chan(&line->chan_list, line->head, count, 176 n = write_chan(&line->chan_list, line->head, count,
174 line->driver->write_irq); 177 line->driver->write_irq);
175 178
176 if(n < 0) 179 if(n < 0)
@@ -227,7 +230,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
227 if (err <= 0 && (err != -EAGAIN || !ret)) 230 if (err <= 0 && (err != -EAGAIN || !ret))
228 ret = err; 231 ret = err;
229 } else { 232 } else {
230 n = write_chan(&line->chan_list, buf, len, 233 n = write_chan(&line->chan_list, buf, len,
231 line->driver->write_irq); 234 line->driver->write_irq);
232 if (n < 0) { 235 if (n < 0) {
233 ret = n; 236 ret = n;
@@ -338,11 +341,36 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
338 return ret; 341 return ret;
339} 342}
340 343
344void line_throttle(struct tty_struct *tty)
345{
346 struct line *line = tty->driver_data;
347
348 deactivate_chan(&line->chan_list, line->driver->read_irq);
349 line->throttled = 1;
350}
351
352void line_unthrottle(struct tty_struct *tty)
353{
354 struct line *line = tty->driver_data;
355
356 line->throttled = 0;
357 chan_interrupt(&line->chan_list, &line->task, tty,
358 line->driver->read_irq);
359
360 /* Maybe there is enough stuff pending that calling the interrupt
361 * throttles us again. In this case, line->throttled will be 1
362 * again and we shouldn't turn the interrupt back on.
363 */
364 if(!line->throttled)
365 reactivate_chan(&line->chan_list, line->driver->read_irq);
366}
367
341static irqreturn_t line_write_interrupt(int irq, void *data, 368static irqreturn_t line_write_interrupt(int irq, void *data,
342 struct pt_regs *unused) 369 struct pt_regs *unused)
343{ 370{
344 struct tty_struct *tty = data; 371 struct chan *chan = data;
345 struct line *line = tty->driver_data; 372 struct line *line = chan->line;
373 struct tty_struct *tty = line->tty;
346 int err; 374 int err;
347 375
348 /* Interrupts are enabled here because we registered the interrupt with 376 /* Interrupts are enabled here because we registered the interrupt with
@@ -364,7 +392,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
364 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 392 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
365 (tty->ldisc.write_wakeup != NULL)) 393 (tty->ldisc.write_wakeup != NULL))
366 (tty->ldisc.write_wakeup)(tty); 394 (tty->ldisc.write_wakeup)(tty);
367 395
368 /* BLOCKING mode 396 /* BLOCKING mode
369 * In blocking mode, everything sleeps on tty->write_wait. 397 * In blocking mode, everything sleeps on tty->write_wait.
370 * Sleeping in the console driver would break non-blocking 398 * Sleeping in the console driver would break non-blocking
@@ -376,53 +404,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
376 return IRQ_HANDLED; 404 return IRQ_HANDLED;
377} 405}
378 406
379int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 407int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
380{ 408{
381 struct line *line = tty->driver_data;
382 struct line_driver *driver = line->driver; 409 struct line_driver *driver = line->driver;
383 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 410 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
384 411
385 if (input) 412 if (input)
386 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 413 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
387 line_interrupt, flags, 414 line_interrupt, flags,
388 driver->read_irq_name, tty); 415 driver->read_irq_name, data);
389 if (err) 416 if (err)
390 return err; 417 return err;
391 if (output) 418 if (output)
392 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 419 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
393 line_write_interrupt, flags, 420 line_write_interrupt, flags,
394 driver->write_irq_name, tty); 421 driver->write_irq_name, data);
395 line->have_irq = 1; 422 line->have_irq = 1;
396 return err; 423 return err;
397} 424}
398 425
399void line_disable(struct tty_struct *tty, int current_irq) 426int line_open(struct line *lines, struct tty_struct *tty)
400{
401 struct line *line = tty->driver_data;
402
403 if(!line->have_irq)
404 return;
405
406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty);
408 else {
409 free_irq(line->driver->read_irq, tty);
410 }
411
412 if(line->driver->write_irq == current_irq)
413 free_irq_later(line->driver->write_irq, tty);
414 else {
415 free_irq(line->driver->write_irq, tty);
416 }
417
418 line->have_irq = 0;
419}
420
421int line_open(struct line *lines, struct tty_struct *tty,
422 struct chan_opts *opts)
423{ 427{
424 struct line *line; 428 struct line *line;
425 int err = 0; 429 int err = -ENODEV;
426 430
427 line = &lines[tty->index]; 431 line = &lines[tty->index];
428 tty->driver_data = line; 432 tty->driver_data = line;
@@ -430,31 +434,29 @@ int line_open(struct line *lines, struct tty_struct *tty,
430 /* The IRQ which takes this lock is not yet enabled and won't be run 434 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 435 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 436 spin_lock(&line->lock);
433 if (tty->count == 1) { 437
434 if (!line->valid) { 438 tty->driver_data = line;
435 err = -ENODEV; 439 line->tty = tty;
436 goto out; 440 if(!line->valid)
437 } 441 goto out;
438 if (list_empty(&line->chan_list)) { 442
439 err = parse_chan_pair(line->init_str, &line->chan_list, 443 if(tty->count == 1){
440 line->init_pri, tty->index, opts); 444 /* Here the device is opened, if necessary, and interrupt
441 if(err) goto out; 445 * is registered.
442 err = open_chan(&line->chan_list); 446 */
443 if(err) goto out; 447 enable_chan(line);
448 INIT_WORK(&line->task, line_timer_cb, line);
449
450 if(!line->sigio){
451 chan_enable_winch(&line->chan_list, tty);
452 line->sigio = 1;
444 } 453 }
445 /* Here the interrupt is registered.*/
446 enable_chan(&line->chan_list, tty);
447 INIT_WORK(&line->task, line_timer_cb, tty);
448 }
449 454
450 if(!line->sigio){ 455 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
451 chan_enable_winch(&line->chan_list, tty); 456 &tty->winsize.ws_col);
452 line->sigio = 1;
453 } 457 }
454 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
455 &tty->winsize.ws_col);
456 line->count++;
457 458
459 err = 0;
458out: 460out:
459 spin_unlock(&line->lock); 461 spin_unlock(&line->lock);
460 return err; 462 return err;
@@ -474,15 +476,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
474 /* We ignore the error anyway! */ 476 /* We ignore the error anyway! */
475 flush_buffer(line); 477 flush_buffer(line);
476 478
477 line->count--; 479 if(tty->count == 1){
478 if (tty->count == 1) { 480 line->tty = NULL;
479 line_disable(tty, -1);
480 tty->driver_data = NULL; 481 tty->driver_data = NULL;
481 }
482 482
483 if((line->count == 0) && line->sigio){ 483 if(line->sigio){
484 unregister_winch(tty); 484 unregister_winch(tty);
485 line->sigio = 0; 485 line->sigio = 0;
486 }
486 } 487 }
487 488
488 spin_unlock_irq(&line->lock); 489 spin_unlock_irq(&line->lock);
@@ -493,17 +494,15 @@ void close_lines(struct line *lines, int nlines)
493 int i; 494 int i;
494 495
495 for(i = 0; i < nlines; i++) 496 for(i = 0; i < nlines; i++)
496 close_chan(&lines[i].chan_list); 497 close_chan(&lines[i].chan_list, 0);
497} 498}
498 499
499/* Common setup code for both startup command line and mconsole initialization. 500/* Common setup code for both startup command line and mconsole initialization.
500 * @lines contains the the array (of size @num) to modify; 501 * @lines contains the the array (of size @num) to modify;
501 * @init is the setup string; 502 * @init is the setup string;
502 * @all_allowed is a boolean saying if we can setup the whole @lines 503 */
503 * at once. For instance, it will be usually true for startup init. (where we
504 * can use con=xterm) and false for mconsole.*/
505 504
506int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) 505int line_setup(struct line *lines, unsigned int num, char *init)
507{ 506{
508 int i, n; 507 int i, n;
509 char *end; 508 char *end;
@@ -512,10 +511,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
512 /* We said con=/ssl= instead of con#=, so we are configuring all 511 /* We said con=/ssl= instead of con#=, so we are configuring all
513 * consoles at once.*/ 512 * consoles at once.*/
514 n = -1; 513 n = -1;
515 } else { 514 }
515 else {
516 n = simple_strtoul(init, &end, 0); 516 n = simple_strtoul(init, &end, 0);
517 if(*end != '='){ 517 if(*end != '='){
518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
519 init); 519 init);
520 return 0; 520 return 0;
521 } 521 }
@@ -527,8 +527,9 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
528 n, num - 1); 528 n, num - 1);
529 return 0; 529 return 0;
530 } else if (n >= 0){ 530 }
531 if (lines[n].count > 0) { 531 else if (n >= 0){
532 if (lines[n].tty != NULL) {
532 printk("line_setup - device %d is open\n", n); 533 printk("line_setup - device %d is open\n", n);
533 return 0; 534 return 0;
534 } 535 }
@@ -539,13 +540,10 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
539 else { 540 else {
540 lines[n].init_str = init; 541 lines[n].init_str = init;
541 lines[n].valid = 1; 542 lines[n].valid = 1;
542 } 543 }
543 } 544 }
544 } else if(!all_allowed){ 545 }
545 printk("line_setup - can't configure all devices from " 546 else {
546 "mconsole\n");
547 return 0;
548 } else {
549 for(i = 0; i < num; i++){ 547 for(i = 0; i < num; i++){
550 if(lines[i].init_pri <= INIT_ALL){ 548 if(lines[i].init_pri <= INIT_ALL){
551 lines[i].init_pri = INIT_ALL; 549 lines[i].init_pri = INIT_ALL;
@@ -557,18 +555,33 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
557 } 555 }
558 } 556 }
559 } 557 }
560 return 1; 558 return n == -1 ? num : n;
561} 559}
562 560
563int line_config(struct line *lines, unsigned int num, char *str) 561int line_config(struct line *lines, unsigned int num, char *str,
562 struct chan_opts *opts)
564{ 563{
565 char *new = uml_strdup(str); 564 struct line *line;
565 char *new;
566 int n;
566 567
568 if(*str == '='){
569 printk("line_config - can't configure all devices from "
570 "mconsole\n");
571 return 1;
572 }
573
574 new = kstrdup(str, GFP_KERNEL);
567 if(new == NULL){ 575 if(new == NULL){
568 printk("line_config - uml_strdup failed\n"); 576 printk("line_config - kstrdup failed\n");
569 return -ENOMEM; 577 return 1;
570 } 578 }
571 return !line_setup(lines, num, new, 0); 579 n = line_setup(lines, num, new);
580 if(n < 0)
581 return 1;
582
583 line = &lines[n];
584 return parse_chan_pair(line->init_str, line, n, opts);
572} 585}
573 586
574int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 587int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -594,7 +607,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
594 spin_lock(&line->lock); 607 spin_lock(&line->lock);
595 if(!line->valid) 608 if(!line->valid)
596 CONFIG_CHUNK(str, size, n, "none", 1); 609 CONFIG_CHUNK(str, size, n, "none", 1);
597 else if(line->count == 0) 610 else if(line->tty == NULL)
598 CONFIG_CHUNK(str, size, n, line->init_str, 1); 611 CONFIG_CHUNK(str, size, n, line->init_str, 1);
599 else n = chan_config_string(&line->chan_list, str, size, error_out); 612 else n = chan_config_string(&line->chan_list, str, size, error_out);
600 spin_unlock(&line->lock); 613 spin_unlock(&line->lock);
@@ -619,14 +632,18 @@ int line_id(char **str, int *start_out, int *end_out)
619 632
620int line_remove(struct line *lines, unsigned int num, int n) 633int line_remove(struct line *lines, unsigned int num, int n)
621{ 634{
635 int err;
622 char config[sizeof("conxxxx=none\0")]; 636 char config[sizeof("conxxxx=none\0")];
623 637
624 sprintf(config, "%d=none", n); 638 sprintf(config, "%d=none", n);
625 return !line_setup(lines, num, config, 0); 639 err = line_setup(lines, num, config);
640 if(err >= 0)
641 err = 0;
642 return err;
626} 643}
627 644
628struct tty_driver *line_register_devfs(struct lines *set, 645struct tty_driver *line_register_devfs(struct lines *set,
629 struct line_driver *line_driver, 646 struct line_driver *line_driver,
630 struct tty_operations *ops, struct line *lines, 647 struct tty_operations *ops, struct line *lines,
631 int nlines) 648 int nlines)
632{ 649{
@@ -655,7 +672,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
655 } 672 }
656 673
657 for(i = 0; i < nlines; i++){ 674 for(i = 0; i < nlines; i++){
658 if(!lines[i].valid) 675 if(!lines[i].valid)
659 tty_unregister_device(driver, i); 676 tty_unregister_device(driver, i);
660 } 677 }
661 678
@@ -663,24 +680,28 @@ struct tty_driver *line_register_devfs(struct lines *set,
663 return driver; 680 return driver;
664} 681}
665 682
666static spinlock_t winch_handler_lock; 683static DEFINE_SPINLOCK(winch_handler_lock);
667LIST_HEAD(winch_handlers); 684static LIST_HEAD(winch_handlers);
668 685
669void lines_init(struct line *lines, int nlines) 686void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
670{ 687{
671 struct line *line; 688 struct line *line;
672 int i; 689 int i;
673 690
674 spin_lock_init(&winch_handler_lock);
675 for(i = 0; i < nlines; i++){ 691 for(i = 0; i < nlines; i++){
676 line = &lines[i]; 692 line = &lines[i];
677 INIT_LIST_HEAD(&line->chan_list); 693 INIT_LIST_HEAD(&line->chan_list);
678 spin_lock_init(&line->lock); 694
679 if(line->init_str != NULL){ 695 if(line->init_str == NULL)
680 line->init_str = uml_strdup(line->init_str); 696 continue;
681 if(line->init_str == NULL) 697
682 printk("lines_init - uml_strdup returned " 698 line->init_str = kstrdup(line->init_str, GFP_KERNEL);
683 "NULL\n"); 699 if(line->init_str == NULL)
700 printk("lines_init - kstrdup returned NULL\n");
701
702 if(parse_chan_pair(line->init_str, line, i, opts)){
703 printk("parse_chan_pair failed for device %d\n", i);
704 line->valid = 0;
684 } 705 }
685 } 706 }
686} 707}
@@ -717,8 +738,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
717 tty = winch->tty; 738 tty = winch->tty;
718 if (tty != NULL) { 739 if (tty != NULL) {
719 line = tty->driver_data; 740 line = tty->driver_data;
720 chan_window_size(&line->chan_list, 741 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
721 &tty->winsize.ws_row,
722 &tty->winsize.ws_col); 742 &tty->winsize.ws_col);
723 kill_pg(tty->pgrp, SIGWINCH, 1); 743 kill_pg(tty->pgrp, SIGWINCH, 1);
724 } 744 }
@@ -749,60 +769,54 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
749 spin_unlock(&winch_handler_lock); 769 spin_unlock(&winch_handler_lock);
750 770
751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 771 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 772 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
753 "winch", winch) < 0) 773 "winch", winch) < 0)
754 printk("register_winch_irq - failed to register IRQ\n"); 774 printk("register_winch_irq - failed to register IRQ\n");
755} 775}
756 776
777static void free_winch(struct winch *winch)
778{
779 list_del(&winch->list);
780
781 if(winch->pid != -1)
782 os_kill_process(winch->pid, 1);
783 if(winch->fd != -1)
784 os_close_file(winch->fd);
785
786 free_irq(WINCH_IRQ, winch);
787 kfree(winch);
788}
789
757static void unregister_winch(struct tty_struct *tty) 790static void unregister_winch(struct tty_struct *tty)
758{ 791{
759 struct list_head *ele; 792 struct list_head *ele;
760 struct winch *winch, *found = NULL; 793 struct winch *winch;
761 794
762 spin_lock(&winch_handler_lock); 795 spin_lock(&winch_handler_lock);
796
763 list_for_each(ele, &winch_handlers){ 797 list_for_each(ele, &winch_handlers){
764 winch = list_entry(ele, struct winch, list); 798 winch = list_entry(ele, struct winch, list);
765 if(winch->tty == tty){ 799 if(winch->tty == tty){
766 found = winch; 800 free_winch(winch);
767 break; 801 break;
768 } 802 }
769 } 803 }
770 if(found == NULL)
771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
775
776 if(winch->pid != -1)
777 os_kill_process(winch->pid, 1);
778
779 free_irq(WINCH_IRQ, winch);
780 kfree(winch);
781
782 return;
783err:
784 spin_unlock(&winch_handler_lock); 804 spin_unlock(&winch_handler_lock);
785} 805}
786 806
787/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
788 * order... are we sure that nothing else is done on the list? */
789static void winch_cleanup(void) 807static void winch_cleanup(void)
790{ 808{
791 struct list_head *ele; 809 struct list_head *ele, *next;
792 struct winch *winch; 810 struct winch *winch;
793 811
794 list_for_each(ele, &winch_handlers){ 812 spin_lock(&winch_handler_lock);
813
814 list_for_each_safe(ele, next, &winch_handlers){
795 winch = list_entry(ele, struct winch, list); 815 winch = list_entry(ele, struct winch, list);
796 if(winch->fd != -1){ 816 free_winch(winch);
797 /* Why is this different from the above free_irq(),
798 * which deactivates SIGIO? This searches the FD
799 * somewhere else and removes it from the list... */
800 deactivate_fd(winch->fd, WINCH_IRQ);
801 os_close_file(winch->fd);
802 }
803 if(winch->pid != -1)
804 os_kill_process(winch->pid, 1);
805 } 817 }
818
819 spin_unlock(&winch_handler_lock);
806} 820}
807__uml_exitcall(winch_cleanup); 821__uml_exitcall(winch_cleanup);
808 822
@@ -811,10 +825,10 @@ char *add_xterm_umid(char *base)
811 char *umid, *title; 825 char *umid, *title;
812 int len; 826 int len;
813 827
814 umid = get_umid(1); 828 umid = get_umid();
815 if(umid == NULL) 829 if(*umid == '\0')
816 return base; 830 return base;
817 831
818 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 832 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
819 title = kmalloc(len, GFP_KERNEL); 833 title = kmalloc(len, GFP_KERNEL);
820 if(title == NULL){ 834 if(title == NULL){
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 12c95368124a..be610125429f 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,7 @@
20#include "linux/namei.h" 20#include "linux/namei.h"
21#include "linux/proc_fs.h" 21#include "linux/proc_fs.h"
22#include "linux/syscalls.h" 22#include "linux/syscalls.h"
23#include "linux/console.h"
23#include "asm/irq.h" 24#include "asm/irq.h"
24#include "asm/uaccess.h" 25#include "asm/uaccess.h"
25#include "user_util.h" 26#include "user_util.h"
@@ -34,7 +35,7 @@
34#include "irq_kern.h" 35#include "irq_kern.h"
35#include "choose-mode.h" 36#include "choose-mode.h"
36 37
37static int do_unlink_socket(struct notifier_block *notifier, 38static int do_unlink_socket(struct notifier_block *notifier,
38 unsigned long what, void *data) 39 unsigned long what, void *data)
39{ 40{
40 return(mconsole_unlink_socket()); 41 return(mconsole_unlink_socket());
@@ -46,12 +47,12 @@ static struct notifier_block reboot_notifier = {
46 .priority = 0, 47 .priority = 0,
47}; 48};
48 49
49/* Safe without explicit locking for now. Tasklets provide their own 50/* Safe without explicit locking for now. Tasklets provide their own
50 * locking, and the interrupt handler is safe because it can't interrupt 51 * locking, and the interrupt handler is safe because it can't interrupt
51 * itself and it can only happen on CPU 0. 52 * itself and it can only happen on CPU 0.
52 */ 53 */
53 54
54LIST_HEAD(mc_requests); 55static LIST_HEAD(mc_requests);
55 56
56static void mc_work_proc(void *unused) 57static void mc_work_proc(void *unused)
57{ 58{
@@ -60,7 +61,7 @@ static void mc_work_proc(void *unused)
60 61
61 while(!list_empty(&mc_requests)){ 62 while(!list_empty(&mc_requests)){
62 local_save_flags(flags); 63 local_save_flags(flags);
63 req = list_entry(mc_requests.next, struct mconsole_entry, 64 req = list_entry(mc_requests.next, struct mconsole_entry,
64 list); 65 list);
65 list_del(&req->list); 66 list_del(&req->list);
66 local_irq_restore(flags); 67 local_irq_restore(flags);
@@ -69,7 +70,7 @@ static void mc_work_proc(void *unused)
69 } 70 }
70} 71}
71 72
72DECLARE_WORK(mconsole_work, mc_work_proc, NULL); 73static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
73 74
74static irqreturn_t mconsole_interrupt(int irq, void *dev_id, 75static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
75 struct pt_regs *regs) 76 struct pt_regs *regs)
@@ -103,8 +104,8 @@ void mconsole_version(struct mc_request *req)
103{ 104{
104 char version[256]; 105 char version[256];
105 106
106 sprintf(version, "%s %s %s %s %s", system_utsname.sysname, 107 sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
107 system_utsname.nodename, system_utsname.release, 108 system_utsname.nodename, system_utsname.release,
108 system_utsname.version, system_utsname.machine); 109 system_utsname.version, system_utsname.machine);
109 mconsole_reply(req, version, 0, 0); 110 mconsole_reply(req, version, 0, 0);
110} 111}
@@ -348,7 +349,7 @@ static struct mc_device *mconsole_find_dev(char *name)
348 349
349#define CONFIG_BUF_SIZE 64 350#define CONFIG_BUF_SIZE 64
350 351
351static void mconsole_get_config(int (*get_config)(char *, char *, int, 352static void mconsole_get_config(int (*get_config)(char *, char *, int,
352 char **), 353 char **),
353 struct mc_request *req, char *name) 354 struct mc_request *req, char *name)
354{ 355{
@@ -389,7 +390,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
389 out: 390 out:
390 if(buf != default_buf) 391 if(buf != default_buf)
391 kfree(buf); 392 kfree(buf);
392
393} 393}
394 394
395void mconsole_config(struct mc_request *req) 395void mconsole_config(struct mc_request *req)
@@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req)
420 420
421void mconsole_remove(struct mc_request *req) 421void mconsole_remove(struct mc_request *req)
422{ 422{
423 struct mc_device *dev; 423 struct mc_device *dev;
424 char *ptr = req->request.data, *err_msg = ""; 424 char *ptr = req->request.data, *err_msg = "";
425 char error[256]; 425 char error[256];
426 int err, start, end, n; 426 int err, start, end, n;
427 427
428 ptr += strlen("remove"); 428 ptr += strlen("remove");
@@ -433,37 +433,112 @@ void mconsole_remove(struct mc_request *req)
433 return; 433 return;
434 } 434 }
435 435
436 ptr = &ptr[strlen(dev->name)]; 436 ptr = &ptr[strlen(dev->name)];
437 437
438 err = 1; 438 err = 1;
439 n = (*dev->id)(&ptr, &start, &end); 439 n = (*dev->id)(&ptr, &start, &end);
440 if(n < 0){ 440 if(n < 0){
441 err_msg = "Couldn't parse device number"; 441 err_msg = "Couldn't parse device number";
442 goto out; 442 goto out;
443 } 443 }
444 else if((n < start) || (n > end)){ 444 else if((n < start) || (n > end)){
445 sprintf(error, "Invalid device number - must be between " 445 sprintf(error, "Invalid device number - must be between "
446 "%d and %d", start, end); 446 "%d and %d", start, end);
447 err_msg = error; 447 err_msg = error;
448 goto out; 448 goto out;
449 } 449 }
450 450
451 err = (*dev->remove)(n); 451 err = (*dev->remove)(n);
452 switch(err){ 452 switch(err){
453 case -ENODEV: 453 case -ENODEV:
454 err_msg = "Device doesn't exist"; 454 err_msg = "Device doesn't exist";
455 break; 455 break;
456 case -EBUSY: 456 case -EBUSY:
457 err_msg = "Device is currently open"; 457 err_msg = "Device is currently open";
458 break; 458 break;
459 default: 459 default:
460 break; 460 break;
461 } 461 }
462 out: 462out:
463 mconsole_reply(req, err_msg, err, 0); 463 mconsole_reply(req, err_msg, err, 0);
464} 464}
465 465
466static DEFINE_SPINLOCK(console_lock);
467static LIST_HEAD(clients);
468static char console_buf[MCONSOLE_MAX_DATA];
469static int console_index = 0;
470
471static void console_write(struct console *console, const char *string,
472 unsigned len)
473{
474 struct list_head *ele;
475 int n;
476
477 if(list_empty(&clients))
478 return;
479
480 while(1){
481 n = min(len, ARRAY_SIZE(console_buf) - console_index);
482 strncpy(&console_buf[console_index], string, n);
483 console_index += n;
484 string += n;
485 len -= n;
486 if(len == 0)
487 return;
488
489 list_for_each(ele, &clients){
490 struct mconsole_entry *entry;
491
492 entry = list_entry(ele, struct mconsole_entry, list);
493 mconsole_reply_len(&entry->request, console_buf,
494 console_index, 0, 1);
495 }
496
497 console_index = 0;
498 }
499}
500
501static struct console mc_console = { .name = "mc",
502 .write = console_write,
503 .flags = CON_PRINTBUFFER | CON_ENABLED,
504 .index = -1 };
505
506static int mc_add_console(void)
507{
508 register_console(&mc_console);
509 return 0;
510}
511
512late_initcall(mc_add_console);
513
514static void with_console(struct mc_request *req, void (*proc)(void *),
515 void *arg)
516{
517 struct mconsole_entry entry;
518 unsigned long flags;
519
520 INIT_LIST_HEAD(&entry.list);
521 entry.request = *req;
522 list_add(&entry.list, &clients);
523 spin_lock_irqsave(&console_lock, flags);
524
525 (*proc)(arg);
526
527 mconsole_reply_len(req, console_buf, console_index, 0, 0);
528 console_index = 0;
529
530 spin_unlock_irqrestore(&console_lock, flags);
531 list_del(&entry.list);
532}
533
466#ifdef CONFIG_MAGIC_SYSRQ 534#ifdef CONFIG_MAGIC_SYSRQ
535static void sysrq_proc(void *arg)
536{
537 char *op = arg;
538
539 handle_sysrq(*op, &current->thread.regs, NULL);
540}
541
467void mconsole_sysrq(struct mc_request *req) 542void mconsole_sysrq(struct mc_request *req)
468{ 543{
469 char *ptr = req->request.data; 544 char *ptr = req->request.data;
@@ -471,8 +546,13 @@ void mconsole_sysrq(struct mc_request *req)
471 ptr += strlen("sysrq"); 546 ptr += strlen("sysrq");
472 while(isspace(*ptr)) ptr++; 547 while(isspace(*ptr)) ptr++;
473 548
474 mconsole_reply(req, "", 0, 0); 549 /* With 'b', the system will shut down without a chance to reply,
475 handle_sysrq(*ptr, &current->thread.regs, NULL); 550 * so in this case, we reply first.
551 */
552 if(*ptr == 'b')
553 mconsole_reply(req, "", 0, 0);
554
555 with_console(req, sysrq_proc, ptr);
476} 556}
477#else 557#else
478void mconsole_sysrq(struct mc_request *req) 558void mconsole_sysrq(struct mc_request *req)
@@ -481,6 +561,14 @@ void mconsole_sysrq(struct mc_request *req)
481} 561}
482#endif 562#endif
483 563
564static void stack_proc(void *arg)
565{
566 struct task_struct *from = current, *to = arg;
567
568 to->thread.saved_task = from;
569 switch_to(from, to, from);
570}
571
484/* Mconsole stack trace 572/* Mconsole stack trace
485 * Added by Allan Graves, Jeff Dike 573 * Added by Allan Graves, Jeff Dike
486 * Dumps a stacks registers to the linux console. 574 * Dumps a stacks registers to the linux console.
@@ -488,37 +576,34 @@ void mconsole_sysrq(struct mc_request *req)
488 */ 576 */
489void do_stack(struct mc_request *req) 577void do_stack(struct mc_request *req)
490{ 578{
491 char *ptr = req->request.data; 579 char *ptr = req->request.data;
492 int pid_requested= -1; 580 int pid_requested= -1;
493 struct task_struct *from = NULL; 581 struct task_struct *from = NULL;
494 struct task_struct *to = NULL; 582 struct task_struct *to = NULL;
495 583
496 /* Would be nice: 584 /* Would be nice:
497 * 1) Send showregs output to mconsole. 585 * 1) Send showregs output to mconsole.
498 * 2) Add a way to stack dump all pids. 586 * 2) Add a way to stack dump all pids.
499 */ 587 */
500 588
501 ptr += strlen("stack"); 589 ptr += strlen("stack");
502 while(isspace(*ptr)) ptr++; 590 while(isspace(*ptr)) ptr++;
503
504 /* Should really check for multiple pids or reject bad args here */
505 /* What do the arguments in mconsole_reply mean? */
506 if(sscanf(ptr, "%d", &pid_requested) == 0){
507 mconsole_reply(req, "Please specify a pid", 1, 0);
508 return;
509 }
510 591
511 from = current; 592 /* Should really check for multiple pids or reject bad args here */
512 to = find_task_by_pid(pid_requested); 593 /* What do the arguments in mconsole_reply mean? */
594 if(sscanf(ptr, "%d", &pid_requested) == 0){
595 mconsole_reply(req, "Please specify a pid", 1, 0);
596 return;
597 }
513 598
514 if((to == NULL) || (pid_requested == 0)) { 599 from = current;
515 mconsole_reply(req, "Couldn't find that pid", 1, 0);
516 return;
517 }
518 to->thread.saved_task = current;
519 600
520 switch_to(from, to, from); 601 to = find_task_by_pid(pid_requested);
521 mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); 602 if((to == NULL) || (pid_requested == 0)) {
603 mconsole_reply(req, "Couldn't find that pid", 1, 0);
604 return;
605 }
606 with_console(req, stack_proc, to);
522} 607}
523 608
524void mconsole_stack(struct mc_request *req) 609void mconsole_stack(struct mc_request *req)
@@ -534,9 +619,9 @@ void mconsole_stack(struct mc_request *req)
534/* Changed by mconsole_setup, which is __setup, and called before SMP is 619/* Changed by mconsole_setup, which is __setup, and called before SMP is
535 * active. 620 * active.
536 */ 621 */
537static char *notify_socket = NULL; 622static char *notify_socket = NULL;
538 623
539int mconsole_init(void) 624static int mconsole_init(void)
540{ 625{
541 /* long to avoid size mismatch warnings from gcc */ 626 /* long to avoid size mismatch warnings from gcc */
542 long sock; 627 long sock;
@@ -563,16 +648,16 @@ int mconsole_init(void)
563 } 648 }
564 649
565 if(notify_socket != NULL){ 650 if(notify_socket != NULL){
566 notify_socket = uml_strdup(notify_socket); 651 notify_socket = kstrdup(notify_socket, GFP_KERNEL);
567 if(notify_socket != NULL) 652 if(notify_socket != NULL)
568 mconsole_notify(notify_socket, MCONSOLE_SOCKET, 653 mconsole_notify(notify_socket, MCONSOLE_SOCKET,
569 mconsole_socket_name, 654 mconsole_socket_name,
570 strlen(mconsole_socket_name) + 1); 655 strlen(mconsole_socket_name) + 1);
571 else printk(KERN_ERR "mconsole_setup failed to strdup " 656 else printk(KERN_ERR "mconsole_setup failed to strdup "
572 "string\n"); 657 "string\n");
573 } 658 }
574 659
575 printk("mconsole (version %d) initialized on %s\n", 660 printk("mconsole (version %d) initialized on %s\n",
576 MCONSOLE_VERSION, mconsole_socket_name); 661 MCONSOLE_VERSION, mconsole_socket_name);
577 return(0); 662 return(0);
578} 663}
@@ -585,7 +670,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
585 char *buf; 670 char *buf;
586 671
587 buf = kmalloc(count + 1, GFP_KERNEL); 672 buf = kmalloc(count + 1, GFP_KERNEL);
588 if(buf == NULL) 673 if(buf == NULL)
589 return(-ENOMEM); 674 return(-ENOMEM);
590 675
591 if(copy_from_user(buf, buffer, count)){ 676 if(copy_from_user(buf, buffer, count)){
@@ -661,7 +746,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
661 746
662 if(notify_socket == NULL) return(0); 747 if(notify_socket == NULL) return(0);
663 748
664 mconsole_notify(notify_socket, MCONSOLE_PANIC, message, 749 mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
665 strlen(message) + 1); 750 strlen(message) + 1);
666 return(0); 751 return(0);
667} 752}
@@ -686,14 +771,3 @@ char *mconsole_notify_socket(void)
686} 771}
687 772
688EXPORT_SYMBOL(mconsole_notify_socket); 773EXPORT_SYMBOL(mconsole_notify_socket);
689
690/*
691 * Overrides for Emacs so that we follow Linus's tabbing style.
692 * Emacs will notice this stuff at the end of the file and automatically
693 * adjust the settings for this buffer only. This must remain at the end
694 * of the file.
695 * ---------------------------------------------------------------------------
696 * Local variables:
697 * c-file-style: "linux"
698 * End:
699 */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 310c1f823f26..4b109fe7fff8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req)
122 return(1); 122 return(1);
123} 123}
124 124
125int mconsole_reply(struct mc_request *req, char *str, int err, int more) 125int mconsole_reply_len(struct mc_request *req, const char *str, int total,
126 int err, int more)
126{ 127{
127 struct mconsole_reply reply; 128 struct mconsole_reply reply;
128 int total, len, n; 129 int len, n;
129 130
130 total = strlen(str);
131 do { 131 do {
132 reply.err = err; 132 reply.err = err;
133 133
@@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
155 return(0); 155 return(0);
156} 156}
157 157
158int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
159{
160 return mconsole_reply_len(req, str, strlen(str), err, more);
161}
162
163
158int mconsole_unlink_socket(void) 164int mconsole_unlink_socket(void)
159{ 165{
160 unlink(mconsole_socket_name); 166 unlink(mconsole_socket_name);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 84c73a300acb..fb1f9fb9b871 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -34,7 +34,7 @@
34#define DRIVER_NAME "uml-netdev" 34#define DRIVER_NAME "uml-netdev"
35 35
36static DEFINE_SPINLOCK(opened_lock); 36static DEFINE_SPINLOCK(opened_lock);
37LIST_HEAD(opened); 37static LIST_HEAD(opened);
38 38
39static int uml_net_rx(struct net_device *dev) 39static int uml_net_rx(struct net_device *dev)
40{ 40{
@@ -150,6 +150,7 @@ static int uml_net_close(struct net_device *dev)
150 if(lp->close != NULL) 150 if(lp->close != NULL)
151 (*lp->close)(lp->fd, &lp->user); 151 (*lp->close)(lp->fd, &lp->user);
152 lp->fd = -1; 152 lp->fd = -1;
153 list_del(&lp->list);
153 154
154 spin_unlock(&lp->lock); 155 spin_unlock(&lp->lock);
155 return 0; 156 return 0;
@@ -266,7 +267,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
266} 267}
267 268
268static DEFINE_SPINLOCK(devices_lock); 269static DEFINE_SPINLOCK(devices_lock);
269static struct list_head devices = LIST_HEAD_INIT(devices); 270static LIST_HEAD(devices);
270 271
271static struct platform_driver uml_net_driver = { 272static struct platform_driver uml_net_driver = {
272 .driver = { 273 .driver = {
@@ -586,7 +587,7 @@ static int net_config(char *str)
586 err = eth_parse(str, &n, &str); 587 err = eth_parse(str, &n, &str);
587 if(err) return(err); 588 if(err) return(err);
588 589
589 str = uml_strdup(str); 590 str = kstrdup(str, GFP_KERNEL);
590 if(str == NULL){ 591 if(str == NULL){
591 printk(KERN_ERR "net_config failed to strdup string\n"); 592 printk(KERN_ERR "net_config failed to strdup string\n");
592 return(-1); 593 return(-1);
@@ -715,6 +716,7 @@ static void close_devices(void)
715 716
716 list_for_each(ele, &opened){ 717 list_for_each(ele, &opened){
717 lp = list_entry(ele, struct uml_net_private, list); 718 lp = list_entry(ele, struct uml_net_private, list);
719 free_irq(lp->dev->irq, lp->dev);
718 if((lp->close != NULL) && (lp->fd >= 0)) 720 if((lp->close != NULL) && (lp->fd >= 0))
719 (*lp->close)(lp->fd, &lp->user); 721 (*lp->close)(lp->fd, &lp->user);
720 if(lp->remove != NULL) (*lp->remove)(&lp->user); 722 if(lp->remove != NULL) (*lp->remove)(&lp->user);
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 62e04ecfada8..a32ef55cb244 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -69,7 +69,7 @@ static struct line_driver driver = {
69 .name = "ssl", 69 .name = "ssl",
70 .config = ssl_config, 70 .config = ssl_config,
71 .get_config = ssl_get_config, 71 .get_config = ssl_get_config,
72 .id = line_id, 72 .id = line_id,
73 .remove = ssl_remove, 73 .remove = ssl_remove,
74 }, 74 },
75}; 75};
@@ -84,26 +84,23 @@ static struct lines lines = LINES_INIT(NR_PORTS);
84 84
85static int ssl_config(char *str) 85static int ssl_config(char *str)
86{ 86{
87 return(line_config(serial_lines, 87 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
88 sizeof(serial_lines)/sizeof(serial_lines[0]), str));
89} 88}
90 89
91static int ssl_get_config(char *dev, char *str, int size, char **error_out) 90static int ssl_get_config(char *dev, char *str, int size, char **error_out)
92{ 91{
93 return(line_get_config(dev, serial_lines, 92 return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
94 sizeof(serial_lines)/sizeof(serial_lines[0]), 93 size, error_out);
95 str, size, error_out));
96} 94}
97 95
98static int ssl_remove(int n) 96static int ssl_remove(int n)
99{ 97{
100 return line_remove(serial_lines, 98 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
101 sizeof(serial_lines)/sizeof(serial_lines[0]), n);
102} 99}
103 100
104int ssl_open(struct tty_struct *tty, struct file *filp) 101int ssl_open(struct tty_struct *tty, struct file *filp)
105{ 102{
106 return line_open(serial_lines, tty, &opts); 103 return line_open(serial_lines, tty);
107} 104}
108 105
109#if 0 106#if 0
@@ -112,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
112 return; 109 return;
113} 110}
114 111
115static void ssl_throttle(struct tty_struct * tty)
116{
117 printk(KERN_ERR "Someone should implement ssl_throttle\n");
118}
119
120static void ssl_unthrottle(struct tty_struct * tty)
121{
122 printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
123}
124
125static void ssl_stop(struct tty_struct *tty) 112static void ssl_stop(struct tty_struct *tty)
126{ 113{
127 printk(KERN_ERR "Someone should implement ssl_stop\n"); 114 printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -148,9 +135,9 @@ static struct tty_operations ssl_ops = {
148 .flush_chars = line_flush_chars, 135 .flush_chars = line_flush_chars,
149 .set_termios = line_set_termios, 136 .set_termios = line_set_termios,
150 .ioctl = line_ioctl, 137 .ioctl = line_ioctl,
138 .throttle = line_throttle,
139 .unthrottle = line_unthrottle,
151#if 0 140#if 0
152 .throttle = ssl_throttle,
153 .unthrottle = ssl_unthrottle,
154 .stop = ssl_stop, 141 .stop = ssl_stop,
155 .start = ssl_start, 142 .start = ssl_start,
156 .hangup = ssl_hangup, 143 .hangup = ssl_hangup,
@@ -183,7 +170,7 @@ static int ssl_console_setup(struct console *co, char *options)
183{ 170{
184 struct line *line = &serial_lines[co->index]; 171 struct line *line = &serial_lines[co->index];
185 172
186 return console_open_chan(line,co,&opts); 173 return console_open_chan(line, co, &opts);
187} 174}
188 175
189static struct console ssl_cons = { 176static struct console ssl_cons = {
@@ -199,12 +186,13 @@ int ssl_init(void)
199{ 186{
200 char *new_title; 187 char *new_title;
201 188
202 printk(KERN_INFO "Initializing software serial port version %d\n", 189 printk(KERN_INFO "Initializing software serial port version %d\n",
203 ssl_version); 190 ssl_version);
204 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, 191 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
205 serial_lines, ARRAY_SIZE(serial_lines)); 192 serial_lines,
193 ARRAY_SIZE(serial_lines));
206 194
207 lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); 195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
208 196
209 new_title = add_xterm_umid(opts.xterm_title); 197 new_title = add_xterm_umid(opts.xterm_title);
210 if (new_title != NULL) 198 if (new_title != NULL)
@@ -212,7 +200,7 @@ int ssl_init(void)
212 200
213 ssl_init_done = 1; 201 ssl_init_done = 1;
214 register_console(&ssl_cons); 202 register_console(&ssl_cons);
215 return(0); 203 return 0;
216} 204}
217late_initcall(ssl_init); 205late_initcall(ssl_init);
218 206
@@ -220,16 +208,13 @@ static void ssl_exit(void)
220{ 208{
221 if (!ssl_init_done) 209 if (!ssl_init_done)
222 return; 210 return;
223 close_lines(serial_lines, 211 close_lines(serial_lines, ARRAY_SIZE(serial_lines));
224 sizeof(serial_lines)/sizeof(serial_lines[0]));
225} 212}
226__uml_exitcall(ssl_exit); 213__uml_exitcall(ssl_exit);
227 214
228static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
229{ 216{
230 return(line_setup(serial_lines, 217 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
231 sizeof(serial_lines)/sizeof(serial_lines[0]),
232 str, 1));
233} 218}
234 219
235__setup("ssl", ssl_chan_setup); 220__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 005aa6333b6e..61db8b2fc83f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -75,7 +75,7 @@ static struct line_driver driver = {
75 .name = "con", 75 .name = "con",
76 .config = con_config, 76 .config = con_config,
77 .get_config = con_get_config, 77 .get_config = con_get_config,
78 .id = line_id, 78 .id = line_id,
79 .remove = con_remove, 79 .remove = con_remove,
80 }, 80 },
81}; 81};
@@ -86,28 +86,27 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS);
86 * individual elements are protected by individual semaphores. 86 * individual elements are protected by individual semaphores.
87 */ 87 */
88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
89 [ 1 ... MAX_TTYS - 1 ] = 89 [ 1 ... MAX_TTYS - 1 ] =
90 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 90 LINE_INIT(CONFIG_CON_CHAN, &driver) };
91 91
92static int con_config(char *str) 92static int con_config(char *str)
93{ 93{
94 return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); 94 return line_config(vts, ARRAY_SIZE(vts), str, &opts);
95} 95}
96 96
97static int con_get_config(char *dev, char *str, int size, char **error_out) 97static int con_get_config(char *dev, char *str, int size, char **error_out)
98{ 98{
99 return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, 99 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
100 size, error_out));
101} 100}
102 101
103static int con_remove(int n) 102static int con_remove(int n)
104{ 103{
105 return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); 104 return line_remove(vts, ARRAY_SIZE(vts), n);
106} 105}
107 106
108static int con_open(struct tty_struct *tty, struct file *filp) 107static int con_open(struct tty_struct *tty, struct file *filp)
109{ 108{
110 return line_open(vts, tty, &opts); 109 return line_open(vts, tty);
111} 110}
112 111
113static int con_init_done = 0; 112static int con_init_done = 0;
@@ -117,16 +116,18 @@ static struct tty_operations console_ops = {
117 .close = line_close, 116 .close = line_close,
118 .write = line_write, 117 .write = line_write,
119 .put_char = line_put_char, 118 .put_char = line_put_char,
120 .write_room = line_write_room, 119 .write_room = line_write_room,
121 .chars_in_buffer = line_chars_in_buffer, 120 .chars_in_buffer = line_chars_in_buffer,
122 .flush_buffer = line_flush_buffer, 121 .flush_buffer = line_flush_buffer,
123 .flush_chars = line_flush_chars, 122 .flush_chars = line_flush_chars,
124 .set_termios = line_set_termios, 123 .set_termios = line_set_termios,
125 .ioctl = line_ioctl, 124 .ioctl = line_ioctl,
125 .throttle = line_throttle,
126 .unthrottle = line_unthrottle,
126}; 127};
127 128
128static void uml_console_write(struct console *console, const char *string, 129static void uml_console_write(struct console *console, const char *string,
129 unsigned len) 130 unsigned len)
130{ 131{
131 struct line *line = &vts[console->index]; 132 struct line *line = &vts[console->index];
132 unsigned long flags; 133 unsigned long flags;
@@ -146,7 +147,7 @@ static int uml_console_setup(struct console *co, char *options)
146{ 147{
147 struct line *line = &vts[co->index]; 148 struct line *line = &vts[co->index];
148 149
149 return console_open_chan(line,co,&opts); 150 return console_open_chan(line, co, &opts);
150} 151}
151 152
152static struct console stdiocons = { 153static struct console stdiocons = {
@@ -156,7 +157,7 @@ static struct console stdiocons = {
156 .setup = uml_console_setup, 157 .setup = uml_console_setup,
157 .flags = CON_PRINTBUFFER, 158 .flags = CON_PRINTBUFFER,
158 .index = -1, 159 .index = -1,
159 .data = &vts, 160 .data = &vts,
160}; 161};
161 162
162int stdio_init(void) 163int stdio_init(void)
@@ -166,11 +167,11 @@ int stdio_init(void)
166 console_driver = line_register_devfs(&console_lines, &driver, 167 console_driver = line_register_devfs(&console_lines, &driver,
167 &console_ops, vts, 168 &console_ops, vts,
168 ARRAY_SIZE(vts)); 169 ARRAY_SIZE(vts));
169 if (NULL == console_driver) 170 if (console_driver == NULL)
170 return -1; 171 return -1;
171 printk(KERN_INFO "Initialized stdio console driver\n"); 172 printk(KERN_INFO "Initialized stdio console driver\n");
172 173
173 lines_init(vts, sizeof(vts)/sizeof(vts[0])); 174 lines_init(vts, ARRAY_SIZE(vts), &opts);
174 175
175 new_title = add_xterm_umid(opts.xterm_title); 176 new_title = add_xterm_umid(opts.xterm_title);
176 if(new_title != NULL) 177 if(new_title != NULL)
@@ -178,7 +179,7 @@ int stdio_init(void)
178 179
179 con_init_done = 1; 180 con_init_done = 1;
180 register_console(&stdiocons); 181 register_console(&stdiocons);
181 return(0); 182 return 0;
182} 183}
183late_initcall(stdio_init); 184late_initcall(stdio_init);
184 185
@@ -186,13 +187,13 @@ static void console_exit(void)
186{ 187{
187 if (!con_init_done) 188 if (!con_init_done)
188 return; 189 return;
189 close_lines(vts, sizeof(vts)/sizeof(vts[0])); 190 close_lines(vts, ARRAY_SIZE(vts));
190} 191}
191__uml_exitcall(console_exit); 192__uml_exitcall(console_exit);
192 193
193static int console_chan_setup(char *str) 194static int console_chan_setup(char *str)
194{ 195{
195 return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); 196 return line_setup(vts, ARRAY_SIZE(vts), str);
196} 197}
197__setup("con", console_chan_setup); 198__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 199__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93898917cbe5..73f9652b2ee9 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -706,7 +706,7 @@ static int ubd_config(char *str)
706{ 706{
707 int n, err; 707 int n, err;
708 708
709 str = uml_strdup(str); 709 str = kstrdup(str, GFP_KERNEL);
710 if(str == NULL){ 710 if(str == NULL){
711 printk(KERN_ERR "ubd_config failed to strdup string\n"); 711 printk(KERN_ERR "ubd_config failed to strdup string\n");
712 return(1); 712 return(1);
@@ -1387,15 +1387,6 @@ int io_thread(void *arg)
1387 printk("io_thread - write failed, fd = %d, err = %d\n", 1387 printk("io_thread - write failed, fd = %d, err = %d\n",
1388 kernel_fd, -n); 1388 kernel_fd, -n);
1389 } 1389 }
1390}
1391 1390
1392/* 1391 return 0;
1393 * Overrides for Emacs so that we follow Linus's tabbing style. 1392}
1394 * Emacs will notice this stuff at the end of the file and automatically
1395 * adjust the settings for this buffer only. This must remain at the end
1396 * of the file.
1397 * ---------------------------------------------------------------------------
1398 * Local variables:
1399 * c-file-style: "linux"
1400 * End:
1401 */