aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2005-05-01 11:58:56 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:58:56 -0400
commitb97b77cca627b2e3e6d0015e2e14b1d1c12de0c8 (patch)
tree3fa7a55e316624a72764e5c7eead52b92a500a88 /arch/um
parent80f9507886076de0cadfdf2b87701e68156829c2 (diff)
[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>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/chan_kern.c16
-rw-r--r--arch/um/drivers/line.c318
-rw-r--r--arch/um/drivers/ssl.c25
-rw-r--r--arch/um/drivers/stdio_console.c19
-rw-r--r--arch/um/include/line.h36
5 files changed, 239 insertions, 175 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 1f77deb3fd23..0150038af795 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -22,7 +22,7 @@
22#ifdef CONFIG_NOCONFIG_CHAN 22#ifdef CONFIG_NOCONFIG_CHAN
23static void *not_configged_init(char *str, int device, struct chan_opts *opts) 23static 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 "UML\n"); 26 "UML\n");
27 return(NULL); 27 return(NULL);
28} 28}
@@ -30,27 +30,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
30static int not_configged_open(int input, int output, int primary, void *data, 30static int not_configged_open(int input, int output, int primary, void *data,
31 char **dev_out) 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 "UML\n"); 34 "UML\n");
35 return(-ENODEV); 35 return(-ENODEV);
36} 36}
37 37
38static void not_configged_close(int fd, void *data) 38static 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 "UML\n"); 41 "UML\n");
42} 42}
43 43
44static int not_configged_read(int fd, char *c_out, void *data) 44static 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 "UML\n"); 47 "UML\n");
48 return(-EIO); 48 return(-EIO);
49} 49}
50 50
51static int not_configged_write(int fd, const char *buf, int len, void *data) 51static 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 "UML\n"); 54 "UML\n");
55 return(-EIO); 55 return(-EIO);
56} 56}
@@ -58,7 +58,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
58static int not_configged_console_write(int fd, const char *buf, int len, 58static int not_configged_console_write(int fd, const char *buf, int len,
59 void *data) 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 "UML\n"); 62 "UML\n");
63 return(-EIO); 63 return(-EIO);
64} 64}
@@ -66,14 +66,14 @@ static int not_configged_console_write(int fd, const char *buf, int len,
66static int not_configged_window_size(int fd, void *data, unsigned short *rows, 66static int not_configged_window_size(int fd, void *data, unsigned short *rows,
67 unsigned short *cols) 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 "UML\n"); 70 "UML\n");
71 return(-ENODEV); 71 return(-ENODEV);
72} 72}
73 73
74static void not_configged_free(void *data) 74static 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 "UML\n"); 77 "UML\n");
78} 78}
79 79
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 6924f273ced9..d0f97127adf6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -39,19 +39,69 @@ static void line_timer_cb(void *arg)
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 line_interrupt(line->driver->read_irq, arg, NULL);
40} 40}
41 41
42static 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 */
46static int write_room(struct line *line)
43{ 47{
44 int n; 48 int n;
45 49
46 if (dev->buffer == NULL) 50 if (line->buffer == NULL)
47 return (LINE_BUFSIZE - 1); 51 return LINE_BUFSIZE - 1;
52
53 /* This is for the case where the buffer is wrapped! */
54 n = line->head - line->tail;
48 55
49 n = dev->head - dev->tail;
50 if (n <= 0) 56 if (n <= 0)
51 n = LINE_BUFSIZE + n; 57 n = LINE_BUFSIZE + n; /* The other case */
52 return (n - 1); 58 return n - 1;
59}
60
61int 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;
53} 79}
54 80
81int 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 */
55static int buffer_data(struct line *line, const char *buf, int len) 105static int buffer_data(struct line *line, const char *buf, int len)
56{ 106{
57 int end, room; 107 int end, room;
@@ -70,48 +120,95 @@ static int buffer_data(struct line *line, const char *buf, int len)
70 len = (len > room) ? room : len; 120 len = (len > room) ? room : len;
71 121
72 end = line->buffer + LINE_BUFSIZE - line->tail; 122 end = line->buffer + LINE_BUFSIZE - line->tail;
73 if(len < end){ 123
124 if (len < end){
74 memcpy(line->tail, buf, len); 125 memcpy(line->tail, buf, len);
75 line->tail += len; 126 line->tail += len;
76 } 127 } else {
77 else { 128 /* The circular buffer is wrapping */
78 memcpy(line->tail, buf, end); 129 memcpy(line->tail, buf, end);
79 buf += end; 130 buf += end;
80 memcpy(line->buffer, buf, len - end); 131 memcpy(line->buffer, buf, len - end);
81 line->tail = line->buffer + len - end; 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!*/
87static int flush_buffer(struct line *line) 147static int flush_buffer(struct line *line)
88{ 148{
89 int n, count; 149 int n, count;
90 150
91 if ((line->buffer == NULL) || (line->head == line->tail)) 151 if ((line->buffer == NULL) || (line->head == line->tail))
92 return(1); 152 return 1;
93 153
94 if (line->tail < line->head) { 154 if (line->tail < line->head) {
155 /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
95 count = line->buffer + LINE_BUFSIZE - line->head; 156 count = line->buffer + LINE_BUFSIZE - line->head;
157
96 n = write_chan(&line->chan_list, line->head, count, 158 n = write_chan(&line->chan_list, line->head, count,
97 line->driver->write_irq); 159 line->driver->write_irq);
98 if (n < 0) 160 if (n < 0)
99 return(n); 161 return n;
100 if (n == count) 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 line->head = line->buffer; 165 line->head = line->buffer;
102 else { 166 } else {
103 line->head += n; 167 line->head += n;
104 return(0); 168 return 0;
105 } 169 }
106 } 170 }
107 171
108 count = line->tail - line->head; 172 count = line->tail - line->head;
109 n = write_chan(&line->chan_list, line->head, count, 173 n = write_chan(&line->chan_list, line->head, count,
110 line->driver->write_irq); 174 line->driver->write_irq);
111 if(n < 0) return(n); 175
176 if(n < 0)
177 return n;
112 178
113 line->head += n; 179 line->head += n;
114 return(line->head == line->tail); 180 return line->head == line->tail;
181}
182
183void 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.*/
204void line_flush_chars(struct tty_struct *tty)
205{
206 line_flush_buffer(tty);
207}
208
209void line_put_char(struct tty_struct *tty, unsigned char ch)
210{
211 line_write(tty, &ch, sizeof(ch));
115} 212}
116 213
117int line_write(struct tty_struct *tty, const unsigned char *buf, int len) 214int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
@@ -120,38 +217,31 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
120 unsigned long flags; 217 unsigned long flags;
121 int n, err, ret = 0; 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); 223 spin_lock_irqsave(&line->lock, flags);
126 if(line->head != line->tail){ 224 if (line->head != line->tail) {
127 local_irq_save(flags);
128 ret = buffer_data(line, buf, len); 225 ret = buffer_data(line, buf, len);
129 err = flush_buffer(line); 226 err = flush_buffer(line);
130 local_irq_restore(flags); 227 if (err <= 0 && (err != -EAGAIN || !ret))
131 if(err <= 0 && (err != -EAGAIN || !ret))
132 ret = err; 228 ret = err;
133 } 229 } else {
134 else {
135 n = write_chan(&line->chan_list, buf, len, 230 n = write_chan(&line->chan_list, buf, len,
136 line->driver->write_irq); 231 line->driver->write_irq);
137 if(n < 0){ 232 if (n < 0) {
138 ret = n; 233 ret = n;
139 goto out_up; 234 goto out_up;
140 } 235 }
141 236
142 len -= n; 237 len -= n;
143 ret += n; 238 ret += n;
144 if(len > 0) 239 if (len > 0)
145 ret += buffer_data(line, buf + n, len); 240 ret += buffer_data(line, buf + n, len);
146 } 241 }
147 out_up: 242out_up:
148 up(&line->sem); 243 spin_unlock_irqrestore(&line->lock, flags);
149 return(ret); 244 return ret;
150}
151
152void line_put_char(struct tty_struct *tty, unsigned char ch)
153{
154 line_write(tty, &ch, sizeof(ch));
155} 245}
156 246
157void line_set_termios(struct tty_struct *tty, struct termios * old) 247void line_set_termios(struct tty_struct *tty, struct termios * old)
@@ -159,11 +249,6 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
159 /* nothing */ 249 /* nothing */
160} 250}
161 251
162int line_chars_in_buffer(struct tty_struct *tty)
163{
164 return 0;
165}
166
167static struct { 252static struct {
168 int cmd; 253 int cmd;
169 char *level; 254 char *level;
@@ -250,7 +335,7 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
250 ret = -ENOIOCTLCMD; 335 ret = -ENOIOCTLCMD;
251 break; 336 break;
252 } 337 }
253 return(ret); 338 return ret;
254} 339}
255 340
256static irqreturn_t line_write_interrupt(int irq, void *data, 341static irqreturn_t line_write_interrupt(int irq, void *data,
@@ -260,18 +345,23 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
260 struct line *line = tty->driver_data; 345 struct line *line = tty->driver_data;
261 int err; 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 err = flush_buffer(line); 352 err = flush_buffer(line);
264 if(err == 0) 353 if (err == 0) {
265 return(IRQ_NONE); 354 return IRQ_NONE;
266 else if(err < 0){ 355 } else if(err < 0) {
267 line->head = line->buffer; 356 line->head = line->buffer;
268 line->tail = line->buffer; 357 line->tail = line->buffer;
269 } 358 }
359 spin_unlock_irq(&line->lock);
270 360
271 if(tty == NULL) 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 (tty->ldisc.write_wakeup != NULL)) 365 (tty->ldisc.write_wakeup != NULL))
276 (tty->ldisc.write_wakeup)(tty); 366 (tty->ldisc.write_wakeup)(tty);
277 367
@@ -281,9 +371,9 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
281 * writes. 371 * writes.
282 */ 372 */
283 373
284 if(waitqueue_active(&tty->write_wait)) 374 if (waitqueue_active(&tty->write_wait))
285 wake_up_interruptible(&tty->write_wait); 375 wake_up_interruptible(&tty->write_wait);
286 return(IRQ_HANDLED); 376 return IRQ_HANDLED;
287} 377}
288 378
289int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 379int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
@@ -292,15 +382,18 @@ int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
292 struct line_driver *driver = line->driver; 382 struct line_driver *driver = line->driver;
293 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 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 line_interrupt, flags, 387 line_interrupt, flags,
297 driver->read_irq_name, tty); 388 driver->read_irq_name, tty);
298 if(err) return(err); 389 if (err)
299 if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 390 return err;
391 if (output)
392 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
300 line_write_interrupt, flags, 393 line_write_interrupt, flags,
301 driver->write_irq_name, tty); 394 driver->write_irq_name, tty);
302 line->have_irq = 1; 395 line->have_irq = 1;
303 return(err); 396 return err;
304} 397}
305 398
306void line_disable(struct tty_struct *tty, int current_irq) 399void line_disable(struct tty_struct *tty, int current_irq)
@@ -336,7 +429,9 @@ int line_open(struct line *lines, struct tty_struct *tty,
336 line = &lines[tty->index]; 429 line = &lines[tty->index];
337 tty->driver_data = line; 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 if (tty->count == 1) { 435 if (tty->count == 1) {
341 if (!line->valid) { 436 if (!line->valid) {
342 err = -ENODEV; 437 err = -ENODEV;
@@ -349,6 +444,7 @@ int line_open(struct line *lines, struct tty_struct *tty,
349 err = open_chan(&line->chan_list); 444 err = open_chan(&line->chan_list);
350 if(err) goto out; 445 if(err) goto out;
351 } 446 }
447 /* Here the interrupt is registered.*/
352 enable_chan(&line->chan_list, tty); 448 enable_chan(&line->chan_list, tty);
353 INIT_WORK(&line->task, line_timer_cb, tty); 449 INIT_WORK(&line->task, line_timer_cb, tty);
354 } 450 }
@@ -362,21 +458,27 @@ int line_open(struct line *lines, struct tty_struct *tty,
362 line->count++; 458 line->count++;
363 459
364out: 460out:
365 up(&line->sem); 461 spin_unlock(&line->lock);
366 return(err); 462 return err;
367} 463}
368 464
369void line_close(struct tty_struct *tty, struct file * filp) 465void line_close(struct tty_struct *tty, struct file * filp)
370{ 466{
371 struct line *line = tty->driver_data; 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 line->count--; 476 line->count--;
375 if (tty->count == 1) { 477 if (tty->count == 1) {
376 line_disable(tty, -1); 478 line_disable(tty, -1);
377 tty->driver_data = NULL; 479 tty->driver_data = NULL;
378 } 480 }
379 up(&line->sem); 481 spin_unlock_irq(&line->lock);
380} 482}
381 483
382void close_lines(struct line *lines, int nlines) 484void close_lines(struct line *lines, int nlines)
@@ -387,31 +489,41 @@ void close_lines(struct line *lines, int nlines)
387 close_chan(&lines[i].chan_list); 489 close_chan(&lines[i].chan_list);
388} 490}
389 491
390int 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
499int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed)
391{ 500{
392 int i, n; 501 int i, n;
393 char *end; 502 char *end;
394 503
395 if(*init == '=') n = -1; 504 if(*init == '=') {
396 else { 505 /* We said con=/ssl= instead of con#=, so we are configuring all
506 * consoles at once.*/
507 n = -1;
508 } else {
397 n = simple_strtoul(init, &end, 0); 509 n = simple_strtoul(init, &end, 0);
398 if(*end != '='){ 510 if(*end != '='){
399 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 511 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
400 init); 512 init);
401 return(0); 513 return 0;
402 } 514 }
403 init = end; 515 init = end;
404 } 516 }
405 init++; 517 init++;
406 if((n >= 0) && (n >= num)){ 518
519 if (n >= (signed int) num) {
407 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 520 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
408 n, num - 1); 521 n, num - 1);
409 return(0); 522 return 0;
410 } 523 } else if (n >= 0){
411 else if (n >= 0){
412 if (lines[n].count > 0) { 524 if (lines[n].count > 0) {
413 printk("line_setup - device %d is open\n", n); 525 printk("line_setup - device %d is open\n", n);
414 return(0); 526 return 0;
415 } 527 }
416 if (lines[n].init_pri <= INIT_ONE){ 528 if (lines[n].init_pri <= INIT_ONE){
417 lines[n].init_pri = INIT_ONE; 529 lines[n].init_pri = INIT_ONE;
@@ -422,13 +534,11 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
422 lines[n].valid = 1; 534 lines[n].valid = 1;
423 } 535 }
424 } 536 }
425 } 537 } else if(!all_allowed){
426 else if(!all_allowed){
427 printk("line_setup - can't configure all devices from " 538 printk("line_setup - can't configure all devices from "
428 "mconsole\n"); 539 "mconsole\n");
429 return(0); 540 return 0;
430 } 541 } else {
431 else {
432 for(i = 0; i < num; i++){ 542 for(i = 0; i < num; i++){
433 if(lines[i].init_pri <= INIT_ALL){ 543 if(lines[i].init_pri <= INIT_ALL){
434 lines[i].init_pri = INIT_ALL; 544 lines[i].init_pri = INIT_ALL;
@@ -440,21 +550,21 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
440 } 550 }
441 } 551 }
442 } 552 }
443 return(1); 553 return 1;
444} 554}
445 555
446int line_config(struct line *lines, int num, char *str) 556int line_config(struct line *lines, unsigned int num, char *str)
447{ 557{
448 char *new = uml_strdup(str); 558 char *new = uml_strdup(str);
449 559
450 if(new == NULL){ 560 if(new == NULL){
451 printk("line_config - uml_strdup failed\n"); 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
457int line_get_config(char *name, struct line *lines, int num, char *str, 567int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
458 int size, char **error_out) 568 int size, char **error_out)
459{ 569{
460 struct line *line; 570 struct line *line;
@@ -464,47 +574,33 @@ int line_get_config(char *name, struct line *lines, int num, char *str,
464 dev = simple_strtoul(name, &end, 0); 574 dev = simple_strtoul(name, &end, 0);
465 if((*end != '\0') || (end == name)){ 575 if((*end != '\0') || (end == name)){
466 *error_out = "line_get_config failed to parse device number"; 576 *error_out = "line_get_config failed to parse device number";
467 return(0); 577 return 0;
468 } 578 }
469 579
470 if((dev < 0) || (dev >= num)){ 580 if((dev < 0) || (dev >= num)){
471 *error_out = "device number of of range"; 581 *error_out = "device number out of range";
472 return(0); 582 return 0;
473 } 583 }
474 584
475 line = &lines[dev]; 585 line = &lines[dev];
476 586
477 down(&line->sem); 587 spin_lock(&line->lock);
478 if(!line->valid) 588 if(!line->valid)
479 CONFIG_CHUNK(str, size, n, "none", 1); 589 CONFIG_CHUNK(str, size, n, "none", 1);
480 else if(line->count == 0) 590 else if(line->count == 0)
481 CONFIG_CHUNK(str, size, n, line->init_str, 1); 591 CONFIG_CHUNK(str, size, n, line->init_str, 1);
482 else n = chan_config_string(&line->chan_list, str, size, error_out); 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
488int line_remove(struct line *lines, int num, char *str) 598int line_remove(struct line *lines, unsigned int num, char *str)
489{ 599{
490 char config[sizeof("conxxxx=none\0")]; 600 char config[sizeof("conxxxx=none\0")];
491 601
492 sprintf(config, "%s=none", str); 602 sprintf(config, "%s=none", str);
493 return(!line_setup(lines, num, config, 0)); 603 return !line_setup(lines, num, config, 0);
494}
495
496int 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} 604}
509 605
510struct tty_driver *line_register_devfs(struct lines *set, 606struct tty_driver *line_register_devfs(struct lines *set,
@@ -553,7 +649,7 @@ void lines_init(struct line *lines, int nlines)
553 for(i = 0; i < nlines; i++){ 649 for(i = 0; i < nlines; i++){
554 line = &lines[i]; 650 line = &lines[i];
555 INIT_LIST_HEAD(&line->chan_list); 651 INIT_LIST_HEAD(&line->chan_list);
556 sema_init(&line->sem, 1); 652 spin_lock_init(&line->lock);
557 if(line->init_str != NULL){ 653 if(line->init_str != NULL){
558 line->init_str = uml_strdup(line->init_str); 654 line->init_str = uml_strdup(line->init_str);
559 if(line->init_str == NULL) 655 if(line->init_str == NULL)
@@ -587,7 +683,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
587 "errno = %d\n", -err); 683 "errno = %d\n", -err);
588 printk("fd %d is losing SIGWINCH support\n", 684 printk("fd %d is losing SIGWINCH support\n",
589 winch->tty_fd); 685 winch->tty_fd);
590 return(IRQ_HANDLED); 686 return IRQ_HANDLED;
591 } 687 }
592 goto out; 688 goto out;
593 } 689 }
@@ -603,7 +699,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
603 out: 699 out:
604 if(winch->fd != -1) 700 if(winch->fd != -1)
605 reactivate_fd(winch->fd, WINCH_IRQ); 701 reactivate_fd(winch->fd, WINCH_IRQ);
606 return(IRQ_HANDLED); 702 return IRQ_HANDLED;
607} 703}
608 704
609DECLARE_MUTEX(winch_handler_sem); 705DECLARE_MUTEX(winch_handler_sem);
@@ -625,7 +721,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
625 .pid = pid, 721 .pid = pid,
626 .tty = tty }); 722 .tty = tty });
627 list_add(&winch->list, &winch_handlers); 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 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 725 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
630 "winch", winch) < 0) 726 "winch", winch) < 0)
631 printk("register_winch_irq - failed to register IRQ\n"); 727 printk("register_winch_irq - failed to register IRQ\n");
@@ -656,26 +752,16 @@ char *add_xterm_umid(char *base)
656 int len; 752 int len;
657 753
658 umid = get_umid(1); 754 umid = get_umid(1);
659 if(umid == NULL) return(base); 755 if(umid == NULL)
756 return base;
660 757
661 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 758 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
662 title = kmalloc(len, GFP_KERNEL); 759 title = kmalloc(len, GFP_KERNEL);
663 if(title == NULL){ 760 if(title == NULL){
664 printk("Failed to allocate buffer for xterm title\n"); 761 printk("Failed to allocate buffer for xterm title\n");
665 return(base); 762 return base;
666 } 763 }
667 764
668 snprintf(title, len, "%s (%s)", base, umid); 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 */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index c5839c3141f8..a2bac429f3d4 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -107,11 +107,6 @@ int ssl_open(struct tty_struct *tty, struct file *filp)
107} 107}
108 108
109#if 0 109#if 0
110static int ssl_chars_in_buffer(struct tty_struct *tty)
111{
112 return(0);
113}
114
115static void ssl_flush_buffer(struct tty_struct *tty) 110static void ssl_flush_buffer(struct tty_struct *tty)
116{ 111{
117 return; 112 return;
@@ -149,11 +144,11 @@ static struct tty_operations ssl_ops = {
149 .put_char = line_put_char, 144 .put_char = line_put_char,
150 .write_room = line_write_room, 145 .write_room = line_write_room,
151 .chars_in_buffer = line_chars_in_buffer, 146 .chars_in_buffer = line_chars_in_buffer,
147 .flush_buffer = line_flush_buffer,
148 .flush_chars = line_flush_chars,
152 .set_termios = line_set_termios, 149 .set_termios = line_set_termios,
153 .ioctl = line_ioctl, 150 .ioctl = line_ioctl,
154#if 0 151#if 0
155 .flush_chars = ssl_flush_chars,
156 .flush_buffer = ssl_flush_buffer,
157 .throttle = ssl_throttle, 152 .throttle = ssl_throttle,
158 .unthrottle = ssl_unthrottle, 153 .unthrottle = ssl_unthrottle,
159 .stop = ssl_stop, 154 .stop = ssl_stop,
@@ -171,10 +166,11 @@ static void ssl_console_write(struct console *c, const char *string,
171 unsigned len) 166 unsigned len)
172{ 167{
173 struct line *line = &serial_lines[c->index]; 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 console_write_chan(&line->chan_list, string, len); 172 console_write_chan(&line->chan_list, string, len);
177 up(&line->sem); 173 spin_unlock_irqrestore(&line->lock, flags);
178} 174}
179 175
180static struct tty_driver *ssl_console_device(struct console *c, int *index) 176static struct tty_driver *ssl_console_device(struct console *c, int *index)
@@ -238,14 +234,3 @@ static int ssl_chan_setup(char *str)
238 234
239__setup("ssl", ssl_chan_setup); 235__setup("ssl", ssl_chan_setup);
240__channel_help(ssl_chan_setup, "ssl"); 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 */
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index e604d7c87695..361d0be342b3 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -116,8 +116,11 @@ static struct tty_operations console_ops = {
116 .open = con_open, 116 .open = con_open,
117 .close = line_close, 117 .close = line_close,
118 .write = line_write, 118 .write = line_write,
119 .put_char = line_put_char,
119 .write_room = line_write_room, 120 .write_room = line_write_room,
120 .chars_in_buffer = line_chars_in_buffer, 121 .chars_in_buffer = line_chars_in_buffer,
122 .flush_buffer = line_flush_buffer,
123 .flush_chars = line_flush_chars,
121 .set_termios = line_set_termios, 124 .set_termios = line_set_termios,
122 .ioctl = line_ioctl, 125 .ioctl = line_ioctl,
123}; 126};
@@ -126,10 +129,11 @@ static void uml_console_write(struct console *console, const char *string,
126 unsigned len) 129 unsigned len)
127{ 130{
128 struct line *line = &vts[console->index]; 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 console_write_chan(&line->chan_list, string, len); 135 console_write_chan(&line->chan_list, string, len);
132 up(&line->sem); 136 spin_unlock_irqrestore(&line->lock, flags);
133} 137}
134 138
135static struct tty_driver *uml_console_device(struct console *c, int *index) 139static struct tty_driver *uml_console_device(struct console *c, int *index)
@@ -192,14 +196,3 @@ static int console_chan_setup(char *str)
192} 196}
193__setup("con", console_chan_setup); 197__setup("con", console_chan_setup);
194__channel_help(console_chan_setup, "con"); 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 */
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 6d81ecc17be5..4c5e92c04ccb 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -10,7 +10,7 @@
10#include "linux/workqueue.h" 10#include "linux/workqueue.h"
11#include "linux/tty.h" 11#include "linux/tty.h"
12#include "linux/interrupt.h" 12#include "linux/interrupt.h"
13#include "asm/semaphore.h" 13#include "linux/spinlock.h"
14#include "chan_user.h" 14#include "chan_user.h"
15#include "mconsole_kern.h" 15#include "mconsole_kern.h"
16 16
@@ -37,10 +37,18 @@ struct line {
37 struct list_head chan_list; 37 struct list_head chan_list;
38 int valid; 38 int valid;
39 int count; 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 char *buffer; 48 char *buffer;
42 char *head; 49 char *head;
43 char *tail; 50 char *tail;
51
44 int sigio; 52 int sigio;
45 struct work_struct task; 53 struct work_struct task;
46 struct line_driver *driver; 54 struct line_driver *driver;
@@ -52,7 +60,6 @@ struct line {
52 init_pri : INIT_STATIC, \ 60 init_pri : INIT_STATIC, \
53 chan_list : { }, \ 61 chan_list : { }, \
54 valid : 1, \ 62 valid : 1, \
55 sem : { }, \
56 buffer : NULL, \ 63 buffer : NULL, \
57 head : NULL, \ 64 head : NULL, \
58 tail : NULL, \ 65 tail : NULL, \
@@ -69,15 +76,18 @@ struct lines {
69extern void line_close(struct tty_struct *tty, struct file * filp); 76extern void line_close(struct tty_struct *tty, struct file * filp);
70extern int line_open(struct line *lines, struct tty_struct *tty, 77extern int line_open(struct line *lines, struct tty_struct *tty,
71 struct chan_opts *opts); 78 struct chan_opts *opts);
72extern int line_setup(struct line *lines, int num, char *init, 79extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init,
73 int all_allowed); 80 int all_allowed);
74extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); 81extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len);
75extern void line_put_char(struct tty_struct *tty, unsigned char ch); 82extern void line_put_char(struct tty_struct *tty, unsigned char ch);
76extern void line_set_termios(struct tty_struct *tty, struct termios * old); 83extern void line_set_termios(struct tty_struct *tty, struct termios * old);
77extern int line_chars_in_buffer(struct tty_struct *tty); 84extern int line_chars_in_buffer(struct tty_struct *tty);
85extern void line_flush_buffer(struct tty_struct *tty);
86extern void line_flush_chars(struct tty_struct *tty);
78extern int line_write_room(struct tty_struct *tty); 87extern int line_write_room(struct tty_struct *tty);
79extern int line_ioctl(struct tty_struct *tty, struct file * file, 88extern int line_ioctl(struct tty_struct *tty, struct file * file,
80 unsigned int cmd, unsigned long arg); 89 unsigned int cmd, unsigned long arg);
90
81extern char *add_xterm_umid(char *base); 91extern char *add_xterm_umid(char *base);
82extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); 92extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty);
83extern void line_close_chan(struct line *line); 93extern void line_close_chan(struct line *line);
@@ -89,20 +99,10 @@ extern struct tty_driver * line_register_devfs(struct lines *set,
89 int nlines); 99 int nlines);
90extern void lines_init(struct line *lines, int nlines); 100extern void lines_init(struct line *lines, int nlines);
91extern void close_lines(struct line *lines, int nlines); 101extern void close_lines(struct line *lines, int nlines);
92extern int line_config(struct line *lines, int num, char *str); 102
93extern int line_remove(struct line *lines, int num, char *str); 103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
94extern int line_get_config(char *dev, struct line *lines, int num, char *str, 104extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
105extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
95 int size, char **error_out); 106 int size, char **error_out);
96 107
97#endif 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 */