Commit b97b77cca627b2e3e6d0015e2e14b1d1c12de0c8

Authored by Paolo 'Blaisorblade' Giarrusso
Committed by Linus Torvalds
1 parent 80f9507886

[PATCH] uml: redo console locking

Fix some console locking problems (including scheduling in atomic) and various
reorderings and cleanup in that code.  Not yet ready for 2.6.12 probably.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 5 changed files with 239 additions and 175 deletions Side-by-side Diff

arch/um/drivers/chan_kern.c
... ... @@ -22,7 +22,7 @@
22 22 #ifdef CONFIG_NOCONFIG_CHAN
23 23 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
24 24 {
25   - printk(KERN_ERR "Using a channel type which is configured out of "
  25 + printf(KERN_ERR "Using a channel type which is configured out of "
26 26 "UML\n");
27 27 return(NULL);
28 28 }
29 29  
30 30  
31 31  
... ... @@ -30,27 +30,27 @@
30 30 static int not_configged_open(int input, int output, int primary, void *data,
31 31 char **dev_out)
32 32 {
33   - printk(KERN_ERR "Using a channel type which is configured out of "
  33 + printf(KERN_ERR "Using a channel type which is configured out of "
34 34 "UML\n");
35 35 return(-ENODEV);
36 36 }
37 37  
38 38 static void not_configged_close(int fd, void *data)
39 39 {
40   - printk(KERN_ERR "Using a channel type which is configured out of "
  40 + printf(KERN_ERR "Using a channel type which is configured out of "
41 41 "UML\n");
42 42 }
43 43  
44 44 static int not_configged_read(int fd, char *c_out, void *data)
45 45 {
46   - printk(KERN_ERR "Using a channel type which is configured out of "
  46 + printf(KERN_ERR "Using a channel type which is configured out of "
47 47 "UML\n");
48 48 return(-EIO);
49 49 }
50 50  
51 51 static int not_configged_write(int fd, const char *buf, int len, void *data)
52 52 {
53   - printk(KERN_ERR "Using a channel type which is configured out of "
  53 + printf(KERN_ERR "Using a channel type which is configured out of "
54 54 "UML\n");
55 55 return(-EIO);
56 56 }
... ... @@ -58,7 +58,7 @@
58 58 static int not_configged_console_write(int fd, const char *buf, int len,
59 59 void *data)
60 60 {
61   - printk(KERN_ERR "Using a channel type which is configured out of "
  61 + printf(KERN_ERR "Using a channel type which is configured out of "
62 62 "UML\n");
63 63 return(-EIO);
64 64 }
65 65  
... ... @@ -66,14 +66,14 @@
66 66 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
67 67 unsigned short *cols)
68 68 {
69   - printk(KERN_ERR "Using a channel type which is configured out of "
  69 + printf(KERN_ERR "Using a channel type which is configured out of "
70 70 "UML\n");
71 71 return(-ENODEV);
72 72 }
73 73  
74 74 static void not_configged_free(void *data)
75 75 {
76   - printk(KERN_ERR "Using a channel type which is configured out of "
  76 + printf(KERN_ERR "Using a channel type which is configured out of "
77 77 "UML\n");
78 78 }
79 79  
arch/um/drivers/line.c
... ... @@ -39,19 +39,69 @@
39 39 line_interrupt(line->driver->read_irq, arg, NULL);
40 40 }
41 41  
42   -static int write_room(struct line *dev)
  42 +/* Returns the free space inside the ring buffer of this line.
  43 + *
  44 + * Should be called while holding line->lock (this does not modify datas).
  45 + */
  46 +static int write_room(struct line *line)
43 47 {
44 48 int n;
45 49  
46   - if (dev->buffer == NULL)
47   - return (LINE_BUFSIZE - 1);
  50 + if (line->buffer == NULL)
  51 + return LINE_BUFSIZE - 1;
48 52  
49   - n = dev->head - dev->tail;
  53 + /* This is for the case where the buffer is wrapped! */
  54 + n = line->head - line->tail;
  55 +
50 56 if (n <= 0)
51   - n = LINE_BUFSIZE + n;
52   - return (n - 1);
  57 + n = LINE_BUFSIZE + n; /* The other case */
  58 + return n - 1;
53 59 }
54 60  
  61 +int line_write_room(struct tty_struct *tty)
  62 +{
  63 + struct line *line = tty->driver_data;
  64 + unsigned long flags;
  65 + int room;
  66 +
  67 + if (tty->stopped)
  68 + return 0;
  69 +
  70 + spin_lock_irqsave(&line->lock, flags);
  71 + room = write_room(line);
  72 + spin_unlock_irqrestore(&line->lock, flags);
  73 +
  74 + /*XXX: Warning to remove */
  75 + if (0 == room)
  76 + printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
  77 + __FUNCTION__,tty->name);
  78 + return room;
  79 +}
  80 +
  81 +int line_chars_in_buffer(struct tty_struct *tty)
  82 +{
  83 + struct line *line = tty->driver_data;
  84 + unsigned long flags;
  85 + int ret;
  86 +
  87 + spin_lock_irqsave(&line->lock, flags);
  88 +
  89 + /*write_room subtracts 1 for the needed NULL, so we readd it.*/
  90 + ret = LINE_BUFSIZE - (write_room(line) + 1);
  91 + spin_unlock_irqrestore(&line->lock, flags);
  92 +
  93 + return ret;
  94 +}
  95 +
  96 +/*
  97 + * This copies the content of buf into the circular buffer associated with
  98 + * this line.
  99 + * The return value is the number of characters actually copied, i.e. the ones
  100 + * for which there was space: this function is not supposed to ever flush out
  101 + * the circular buffer.
  102 + *
  103 + * Must be called while holding line->lock!
  104 + */
55 105 static int buffer_data(struct line *line, const char *buf, int len)
56 106 {
57 107 int end, room;
58 108  
59 109  
60 110  
61 111  
62 112  
63 113  
64 114  
65 115  
66 116  
67 117  
68 118  
69 119  
70 120  
71 121  
72 122  
73 123  
74 124  
75 125  
76 126  
77 127  
78 128  
79 129  
... ... @@ -70,100 +120,135 @@
70 120 len = (len > room) ? room : len;
71 121  
72 122 end = line->buffer + LINE_BUFSIZE - line->tail;
73   - if(len < end){
  123 +
  124 + if (len < end){
74 125 memcpy(line->tail, buf, len);
75 126 line->tail += len;
76   - }
77   - else {
  127 + } else {
  128 + /* The circular buffer is wrapping */
78 129 memcpy(line->tail, buf, end);
79 130 buf += end;
80 131 memcpy(line->buffer, buf, len - end);
81 132 line->tail = line->buffer + len - end;
82 133 }
83 134  
84   - return(len);
  135 + return len;
85 136 }
86 137  
  138 +/*
  139 + * Flushes the ring buffer to the output channels. That is, write_chan is
  140 + * called, passing it line->head as buffer, and an appropriate count.
  141 + *
  142 + * On exit, returns 1 when the buffer is empty,
  143 + * 0 when the buffer is not empty on exit,
  144 + * and -errno when an error occurred.
  145 + *
  146 + * Must be called while holding line->lock!*/
87 147 static int flush_buffer(struct line *line)
88 148 {
89 149 int n, count;
90 150  
91 151 if ((line->buffer == NULL) || (line->head == line->tail))
92   - return(1);
  152 + return 1;
93 153  
94 154 if (line->tail < line->head) {
  155 + /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
95 156 count = line->buffer + LINE_BUFSIZE - line->head;
  157 +
96 158 n = write_chan(&line->chan_list, line->head, count,
97 159 line->driver->write_irq);
98 160 if (n < 0)
99   - return(n);
100   - if (n == count)
  161 + return n;
  162 + if (n == count) {
  163 + /* We have flushed from ->head to buffer end, now we
  164 + * must flush only from the beginning to ->tail.*/
101 165 line->head = line->buffer;
102   - else {
  166 + } else {
103 167 line->head += n;
104   - return(0);
  168 + return 0;
105 169 }
106 170 }
107 171  
108 172 count = line->tail - line->head;
109 173 n = write_chan(&line->chan_list, line->head, count,
110 174 line->driver->write_irq);
111   - if(n < 0) return(n);
112 175  
  176 + if(n < 0)
  177 + return n;
  178 +
113 179 line->head += n;
114   - return(line->head == line->tail);
  180 + return line->head == line->tail;
115 181 }
116 182  
  183 +void line_flush_buffer(struct tty_struct *tty)
  184 +{
  185 + struct line *line = tty->driver_data;
  186 + unsigned long flags;
  187 + int err;
  188 +
  189 + /*XXX: copied from line_write, verify if it is correct!*/
  190 + if(tty->stopped)
  191 + return;
  192 + //return 0;
  193 +
  194 + spin_lock_irqsave(&line->lock, flags);
  195 + err = flush_buffer(line);
  196 + /*if (err == 1)
  197 + err = 0;*/
  198 + spin_unlock_irqrestore(&line->lock, flags);
  199 + //return err;
  200 +}
  201 +
  202 +/* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer
  203 + * and ->write. Hope it's not that bad.*/
  204 +void line_flush_chars(struct tty_struct *tty)
  205 +{
  206 + line_flush_buffer(tty);
  207 +}
  208 +
  209 +void line_put_char(struct tty_struct *tty, unsigned char ch)
  210 +{
  211 + line_write(tty, &ch, sizeof(ch));
  212 +}
  213 +
117 214 int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
118 215 {
119 216 struct line *line = tty->driver_data;
120 217 unsigned long flags;
121 218 int n, err, ret = 0;
122 219  
123   - if(tty->stopped) return 0;
  220 + if(tty->stopped)
  221 + return 0;
124 222  
125   - down(&line->sem);
126   - if(line->head != line->tail){
127   - local_irq_save(flags);
  223 + spin_lock_irqsave(&line->lock, flags);
  224 + if (line->head != line->tail) {
128 225 ret = buffer_data(line, buf, len);
129 226 err = flush_buffer(line);
130   - local_irq_restore(flags);
131   - if(err <= 0 && (err != -EAGAIN || !ret))
  227 + if (err <= 0 && (err != -EAGAIN || !ret))
132 228 ret = err;
133   - }
134   - else {
  229 + } else {
135 230 n = write_chan(&line->chan_list, buf, len,
136 231 line->driver->write_irq);
137   - if(n < 0){
  232 + if (n < 0) {
138 233 ret = n;
139 234 goto out_up;
140 235 }
141 236  
142 237 len -= n;
143 238 ret += n;
144   - if(len > 0)
  239 + if (len > 0)
145 240 ret += buffer_data(line, buf + n, len);
146 241 }
147   - out_up:
148   - up(&line->sem);
149   - return(ret);
  242 +out_up:
  243 + spin_unlock_irqrestore(&line->lock, flags);
  244 + return ret;
150 245 }
151 246  
152   -void line_put_char(struct tty_struct *tty, unsigned char ch)
153   -{
154   - line_write(tty, &ch, sizeof(ch));
155   -}
156   -
157 247 void line_set_termios(struct tty_struct *tty, struct termios * old)
158 248 {
159 249 /* nothing */
160 250 }
161 251  
162   -int line_chars_in_buffer(struct tty_struct *tty)
163   -{
164   - return 0;
165   -}
166   -
167 252 static struct {
168 253 int cmd;
169 254 char *level;
... ... @@ -250,7 +335,7 @@
250 335 ret = -ENOIOCTLCMD;
251 336 break;
252 337 }
253   - return(ret);
  338 + return ret;
254 339 }
255 340  
256 341 static irqreturn_t line_write_interrupt(int irq, void *data,
257 342  
258 343  
259 344  
260 345  
... ... @@ -260,18 +345,23 @@
260 345 struct line *line = tty->driver_data;
261 346 int err;
262 347  
  348 + /* Interrupts are enabled here because we registered the interrupt with
  349 + * SA_INTERRUPT (see line_setup_irq).*/
  350 +
  351 + spin_lock_irq(&line->lock);
263 352 err = flush_buffer(line);
264   - if(err == 0)
265   - return(IRQ_NONE);
266   - else if(err < 0){
  353 + if (err == 0) {
  354 + return IRQ_NONE;
  355 + } else if(err < 0) {
267 356 line->head = line->buffer;
268 357 line->tail = line->buffer;
269 358 }
  359 + spin_unlock_irq(&line->lock);
270 360  
271 361 if(tty == NULL)
272   - return(IRQ_NONE);
  362 + return IRQ_NONE;
273 363  
274   - if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
  364 + if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
275 365 (tty->ldisc.write_wakeup != NULL))
276 366 (tty->ldisc.write_wakeup)(tty);
277 367  
278 368  
... ... @@ -281,9 +371,9 @@
281 371 * writes.
282 372 */
283 373  
284   - if(waitqueue_active(&tty->write_wait))
  374 + if (waitqueue_active(&tty->write_wait))
285 375 wake_up_interruptible(&tty->write_wait);
286   - return(IRQ_HANDLED);
  376 + return IRQ_HANDLED;
287 377 }
288 378  
289 379 int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
290 380  
291 381  
... ... @@ -292,15 +382,18 @@
292 382 struct line_driver *driver = line->driver;
293 383 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
294 384  
295   - if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ,
  385 + if (input)
  386 + err = um_request_irq(driver->read_irq, fd, IRQ_READ,
296 387 line_interrupt, flags,
297 388 driver->read_irq_name, tty);
298   - if(err) return(err);
299   - if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
  389 + if (err)
  390 + return err;
  391 + if (output)
  392 + err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
300 393 line_write_interrupt, flags,
301 394 driver->write_irq_name, tty);
302 395 line->have_irq = 1;
303   - return(err);
  396 + return err;
304 397 }
305 398  
306 399 void line_disable(struct tty_struct *tty, int current_irq)
... ... @@ -336,7 +429,9 @@
336 429 line = &lines[tty->index];
337 430 tty->driver_data = line;
338 431  
339   - down(&line->sem);
  432 + /* The IRQ which takes this lock is not yet enabled and won't be run
  433 + * before the end, so we don't need to use spin_lock_irq.*/
  434 + spin_lock(&line->lock);
340 435 if (tty->count == 1) {
341 436 if (!line->valid) {
342 437 err = -ENODEV;
... ... @@ -349,6 +444,7 @@
349 444 err = open_chan(&line->chan_list);
350 445 if(err) goto out;
351 446 }
  447 + /* Here the interrupt is registered.*/
352 448 enable_chan(&line->chan_list, tty);
353 449 INIT_WORK(&line->task, line_timer_cb, tty);
354 450 }
355 451  
356 452  
... ... @@ -362,21 +458,27 @@
362 458 line->count++;
363 459  
364 460 out:
365   - up(&line->sem);
366   - return(err);
  461 + spin_unlock(&line->lock);
  462 + return err;
367 463 }
368 464  
369 465 void line_close(struct tty_struct *tty, struct file * filp)
370 466 {
371 467 struct line *line = tty->driver_data;
372 468  
373   - down(&line->sem);
  469 + /* XXX: I assume this should be called in process context, not with interrupt
  470 + * disabled!*/
  471 + spin_lock_irq(&line->lock);
  472 +
  473 + /* We ignore the error anyway! */
  474 + flush_buffer(line);
  475 +
374 476 line->count--;
375 477 if (tty->count == 1) {
376 478 line_disable(tty, -1);
377 479 tty->driver_data = NULL;
378 480 }
379   - up(&line->sem);
  481 + spin_unlock_irq(&line->lock);
380 482 }
381 483  
382 484 void close_lines(struct line *lines, int nlines)
383 485  
384 486  
385 487  
386 488  
387 489  
... ... @@ -387,31 +489,41 @@
387 489 close_chan(&lines[i].chan_list);
388 490 }
389 491  
390   -int line_setup(struct line *lines, int num, char *init, int all_allowed)
  492 +/* Common setup code for both startup command line and mconsole initialization.
  493 + * @lines contains the the array (of size @num) to modify;
  494 + * @init is the setup string;
  495 + * @all_allowed is a boolean saying if we can setup the whole @lines
  496 + * at once. For instance, it will be usually true for startup init. (where we
  497 + * can use con=xterm) and false for mconsole.*/
  498 +
  499 +int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed)
391 500 {
392 501 int i, n;
393 502 char *end;
394 503  
395   - if(*init == '=') n = -1;
396   - else {
  504 + if(*init == '=') {
  505 + /* We said con=/ssl= instead of con#=, so we are configuring all
  506 + * consoles at once.*/
  507 + n = -1;
  508 + } else {
397 509 n = simple_strtoul(init, &end, 0);
398 510 if(*end != '='){
399 511 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
400 512 init);
401   - return(0);
  513 + return 0;
402 514 }
403 515 init = end;
404 516 }
405 517 init++;
406   - if((n >= 0) && (n >= num)){
  518 +
  519 + if (n >= (signed int) num) {
407 520 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
408 521 n, num - 1);
409   - return(0);
410   - }
411   - else if (n >= 0){
  522 + return 0;
  523 + } else if (n >= 0){
412 524 if (lines[n].count > 0) {
413 525 printk("line_setup - device %d is open\n", n);
414   - return(0);
  526 + return 0;
415 527 }
416 528 if (lines[n].init_pri <= INIT_ONE){
417 529 lines[n].init_pri = INIT_ONE;
418 530  
... ... @@ -422,13 +534,11 @@
422 534 lines[n].valid = 1;
423 535 }
424 536 }
425   - }
426   - else if(!all_allowed){
  537 + } else if(!all_allowed){
427 538 printk("line_setup - can't configure all devices from "
428 539 "mconsole\n");
429   - return(0);
430   - }
431   - else {
  540 + return 0;
  541 + } else {
432 542 for(i = 0; i < num; i++){
433 543 if(lines[i].init_pri <= INIT_ALL){
434 544 lines[i].init_pri = INIT_ALL;
435 545  
436 546  
437 547  
438 548  
... ... @@ -440,21 +550,21 @@
440 550 }
441 551 }
442 552 }
443   - return(1);
  553 + return 1;
444 554 }
445 555  
446   -int line_config(struct line *lines, int num, char *str)
  556 +int line_config(struct line *lines, unsigned int num, char *str)
447 557 {
448 558 char *new = uml_strdup(str);
449 559  
450 560 if(new == NULL){
451 561 printk("line_config - uml_strdup failed\n");
452   - return(-ENOMEM);
  562 + return -ENOMEM;
453 563 }
454   - return(!line_setup(lines, num, new, 0));
  564 + return !line_setup(lines, num, new, 0);
455 565 }
456 566  
457   -int line_get_config(char *name, struct line *lines, int num, char *str,
  567 +int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
458 568 int size, char **error_out)
459 569 {
460 570 struct line *line;
461 571  
462 572  
463 573  
464 574  
465 575  
466 576  
467 577  
... ... @@ -464,49 +574,35 @@
464 574 dev = simple_strtoul(name, &end, 0);
465 575 if((*end != '\0') || (end == name)){
466 576 *error_out = "line_get_config failed to parse device number";
467   - return(0);
  577 + return 0;
468 578 }
469 579  
470 580 if((dev < 0) || (dev >= num)){
471   - *error_out = "device number of of range";
472   - return(0);
  581 + *error_out = "device number out of range";
  582 + return 0;
473 583 }
474 584  
475 585 line = &lines[dev];
476 586  
477   - down(&line->sem);
  587 + spin_lock(&line->lock);
478 588 if(!line->valid)
479 589 CONFIG_CHUNK(str, size, n, "none", 1);
480 590 else if(line->count == 0)
481 591 CONFIG_CHUNK(str, size, n, line->init_str, 1);
482 592 else n = chan_config_string(&line->chan_list, str, size, error_out);
483   - up(&line->sem);
  593 + spin_unlock(&line->lock);
484 594  
485   - return(n);
  595 + return n;
486 596 }
487 597  
488   -int line_remove(struct line *lines, int num, char *str)
  598 +int line_remove(struct line *lines, unsigned int num, char *str)
489 599 {
490 600 char config[sizeof("conxxxx=none\0")];
491 601  
492 602 sprintf(config, "%s=none", str);
493   - return(!line_setup(lines, num, config, 0));
  603 + return !line_setup(lines, num, config, 0);
494 604 }
495 605  
496   -int line_write_room(struct tty_struct *tty)
497   -{
498   - struct line *dev = tty->driver_data;
499   - int room;
500   -
501   - if (tty->stopped)
502   - return 0;
503   - room = write_room(dev);
504   - if (0 == room)
505   - printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
506   - __FUNCTION__,tty->name);
507   - return room;
508   -}
509   -
510 606 struct tty_driver *line_register_devfs(struct lines *set,
511 607 struct line_driver *line_driver,
512 608 struct tty_operations *ops, struct line *lines,
... ... @@ -553,7 +649,7 @@
553 649 for(i = 0; i < nlines; i++){
554 650 line = &lines[i];
555 651 INIT_LIST_HEAD(&line->chan_list);
556   - sema_init(&line->sem, 1);
  652 + spin_lock_init(&line->lock);
557 653 if(line->init_str != NULL){
558 654 line->init_str = uml_strdup(line->init_str);
559 655 if(line->init_str == NULL)
... ... @@ -587,7 +683,7 @@
587 683 "errno = %d\n", -err);
588 684 printk("fd %d is losing SIGWINCH support\n",
589 685 winch->tty_fd);
590   - return(IRQ_HANDLED);
  686 + return IRQ_HANDLED;
591 687 }
592 688 goto out;
593 689 }
... ... @@ -603,7 +699,7 @@
603 699 out:
604 700 if(winch->fd != -1)
605 701 reactivate_fd(winch->fd, WINCH_IRQ);
606   - return(IRQ_HANDLED);
  702 + return IRQ_HANDLED;
607 703 }
608 704  
609 705 DECLARE_MUTEX(winch_handler_sem);
... ... @@ -625,7 +721,7 @@
625 721 .pid = pid,
626 722 .tty = tty });
627 723 list_add(&winch->list, &winch_handlers);
628   - if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
  724 + if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
629 725 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
630 726 "winch", winch) < 0)
631 727 printk("register_winch_irq - failed to register IRQ\n");
632 728  
633 729  
634 730  
... ... @@ -656,27 +752,17 @@
656 752 int len;
657 753  
658 754 umid = get_umid(1);
659   - if(umid == NULL) return(base);
  755 + if(umid == NULL)
  756 + return base;
660 757  
661 758 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
662 759 title = kmalloc(len, GFP_KERNEL);
663 760 if(title == NULL){
664 761 printk("Failed to allocate buffer for xterm title\n");
665   - return(base);
  762 + return base;
666 763 }
667 764  
668 765 snprintf(title, len, "%s (%s)", base, umid);
669   - return(title);
  766 + return title;
670 767 }
671   -
672   -/*
673   - * Overrides for Emacs so that we follow Linus's tabbing style.
674   - * Emacs will notice this stuff at the end of the file and automatically
675   - * adjust the settings for this buffer only. This must remain at the end
676   - * of the file.
677   - * ---------------------------------------------------------------------------
678   - * Local variables:
679   - * c-file-style: "linux"
680   - * End:
681   - */
arch/um/drivers/ssl.c
... ... @@ -107,11 +107,6 @@
107 107 }
108 108  
109 109 #if 0
110   -static int ssl_chars_in_buffer(struct tty_struct *tty)
111   -{
112   - return(0);
113   -}
114   -
115 110 static void ssl_flush_buffer(struct tty_struct *tty)
116 111 {
117 112 return;
118 113  
... ... @@ -149,11 +144,11 @@
149 144 .put_char = line_put_char,
150 145 .write_room = line_write_room,
151 146 .chars_in_buffer = line_chars_in_buffer,
  147 + .flush_buffer = line_flush_buffer,
  148 + .flush_chars = line_flush_chars,
152 149 .set_termios = line_set_termios,
153 150 .ioctl = line_ioctl,
154 151 #if 0
155   - .flush_chars = ssl_flush_chars,
156   - .flush_buffer = ssl_flush_buffer,
157 152 .throttle = ssl_throttle,
158 153 .unthrottle = ssl_unthrottle,
159 154 .stop = ssl_stop,
160 155  
161 156  
... ... @@ -171,10 +166,11 @@
171 166 unsigned len)
172 167 {
173 168 struct line *line = &serial_lines[c->index];
  169 + unsigned long flags;
174 170  
175   - down(&line->sem);
  171 + spin_lock_irqsave(&line->lock, flags);
176 172 console_write_chan(&line->chan_list, string, len);
177   - up(&line->sem);
  173 + spin_unlock_irqrestore(&line->lock, flags);
178 174 }
179 175  
180 176 static struct tty_driver *ssl_console_device(struct console *c, int *index)
... ... @@ -238,15 +234,4 @@
238 234  
239 235 __setup("ssl", ssl_chan_setup);
240 236 __channel_help(ssl_chan_setup, "ssl");
241   -
242   -/*
243   - * Overrides for Emacs so that we follow Linus's tabbing style.
244   - * Emacs will notice this stuff at the end of the file and automatically
245   - * adjust the settings for this buffer only. This must remain at the end
246   - * of the file.
247   - * ---------------------------------------------------------------------------
248   - * Local variables:
249   - * c-file-style: "linux"
250   - * End:
251   - */
arch/um/drivers/stdio_console.c
... ... @@ -116,8 +116,11 @@
116 116 .open = con_open,
117 117 .close = line_close,
118 118 .write = line_write,
  119 + .put_char = line_put_char,
119 120 .write_room = line_write_room,
120 121 .chars_in_buffer = line_chars_in_buffer,
  122 + .flush_buffer = line_flush_buffer,
  123 + .flush_chars = line_flush_chars,
121 124 .set_termios = line_set_termios,
122 125 .ioctl = line_ioctl,
123 126 };
124 127  
125 128  
... ... @@ -126,10 +129,11 @@
126 129 unsigned len)
127 130 {
128 131 struct line *line = &vts[console->index];
  132 + unsigned long flags;
129 133  
130   - down(&line->sem);
  134 + spin_lock_irqsave(&line->lock, flags);
131 135 console_write_chan(&line->chan_list, string, len);
132   - up(&line->sem);
  136 + spin_unlock_irqrestore(&line->lock, flags);
133 137 }
134 138  
135 139 static struct tty_driver *uml_console_device(struct console *c, int *index)
... ... @@ -192,15 +196,4 @@
192 196 }
193 197 __setup("con", console_chan_setup);
194 198 __channel_help(console_chan_setup, "con");
195   -
196   -/*
197   - * Overrides for Emacs so that we follow Linus's tabbing style.
198   - * Emacs will notice this stuff at the end of the file and automatically
199   - * adjust the settings for this buffer only. This must remain at the end
200   - * of the file.
201   - * ---------------------------------------------------------------------------
202   - * Local variables:
203   - * c-file-style: "linux"
204   - * End:
205   - */
arch/um/include/line.h
... ... @@ -10,7 +10,7 @@
10 10 #include "linux/workqueue.h"
11 11 #include "linux/tty.h"
12 12 #include "linux/interrupt.h"
13   -#include "asm/semaphore.h"
  13 +#include "linux/spinlock.h"
14 14 #include "chan_user.h"
15 15 #include "mconsole_kern.h"
16 16  
17 17  
... ... @@ -37,10 +37,18 @@
37 37 struct list_head chan_list;
38 38 int valid;
39 39 int count;
40   - struct semaphore sem;
  40 + /*This lock is actually, mostly, local to*/
  41 + spinlock_t lock;
  42 +
  43 + /* Yes, this is a real circular buffer.
  44 + * XXX: And this should become a struct kfifo!
  45 + *
  46 + * buffer points to a buffer allocated on demand, of length
  47 + * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
41 48 char *buffer;
42 49 char *head;
43 50 char *tail;
  51 +
44 52 int sigio;
45 53 struct work_struct task;
46 54 struct line_driver *driver;
... ... @@ -52,7 +60,6 @@
52 60 init_pri : INIT_STATIC, \
53 61 chan_list : { }, \
54 62 valid : 1, \
55   - sem : { }, \
56 63 buffer : NULL, \
57 64 head : NULL, \
58 65 tail : NULL, \
59 66  
60 67  
... ... @@ -69,15 +76,18 @@
69 76 extern void line_close(struct tty_struct *tty, struct file * filp);
70 77 extern int line_open(struct line *lines, struct tty_struct *tty,
71 78 struct chan_opts *opts);
72   -extern int line_setup(struct line *lines, int num, char *init,
  79 +extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init,
73 80 int all_allowed);
74 81 extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len);
75 82 extern void line_put_char(struct tty_struct *tty, unsigned char ch);
76 83 extern void line_set_termios(struct tty_struct *tty, struct termios * old);
77 84 extern int line_chars_in_buffer(struct tty_struct *tty);
  85 +extern void line_flush_buffer(struct tty_struct *tty);
  86 +extern void line_flush_chars(struct tty_struct *tty);
78 87 extern int line_write_room(struct tty_struct *tty);
79 88 extern int line_ioctl(struct tty_struct *tty, struct file * file,
80 89 unsigned int cmd, unsigned long arg);
  90 +
81 91 extern char *add_xterm_umid(char *base);
82 92 extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty);
83 93 extern void line_close_chan(struct line *line);
84 94  
... ... @@ -89,21 +99,11 @@
89 99 int nlines);
90 100 extern void lines_init(struct line *lines, int nlines);
91 101 extern void close_lines(struct line *lines, int nlines);
92   -extern int line_config(struct line *lines, int num, char *str);
93   -extern int line_remove(struct line *lines, int num, char *str);
94   -extern int line_get_config(char *dev, struct line *lines, int num, char *str,
  102 +
  103 +extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
  104 +extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
  105 +extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
95 106 int size, char **error_out);
96 107  
97 108 #endif
98   -
99   -/*
100   - * Overrides for Emacs so that we follow Linus's tabbing style.
101   - * Emacs will notice this stuff at the end of the file and automatically
102   - * adjust the settings for this buffer only. This must remain at the end
103   - * of the file.
104   - * ---------------------------------------------------------------------------
105   - * Local variables:
106   - * c-file-style: "linux"
107   - * End:
108   - */