diff options
Diffstat (limited to 'drivers/char/hvc_console.c')
-rw-r--r-- | drivers/char/hvc_console.c | 85 |
1 files changed, 22 insertions, 63 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d625cc..02aac104842d 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/kbd_kern.h> | 28 | #include <linux/kbd_kern.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/kref.h> | ||
31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
32 | #include <linux/list.h> | 31 | #include <linux/list.h> |
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
@@ -75,23 +74,6 @@ static int hvc_init(void); | |||
75 | static int sysrq_pressed; | 74 | static int sysrq_pressed; |
76 | #endif | 75 | #endif |
77 | 76 | ||
78 | struct hvc_struct { | ||
79 | spinlock_t lock; | ||
80 | int index; | ||
81 | struct tty_struct *tty; | ||
82 | unsigned int count; | ||
83 | int do_wakeup; | ||
84 | char *outbuf; | ||
85 | int outbuf_size; | ||
86 | int n_outbuf; | ||
87 | uint32_t vtermno; | ||
88 | struct hv_ops *ops; | ||
89 | int irq_requested; | ||
90 | int irq; | ||
91 | struct list_head next; | ||
92 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
93 | }; | ||
94 | |||
95 | /* dynamic list of hvc_struct instances */ | 77 | /* dynamic list of hvc_struct instances */ |
96 | static LIST_HEAD(hvc_structs); | 78 | static LIST_HEAD(hvc_structs); |
97 | 79 | ||
@@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
298 | 280 | ||
299 | return 0; | 281 | return 0; |
300 | } | 282 | } |
283 | EXPORT_SYMBOL_GPL(hvc_instantiate); | ||
301 | 284 | ||
302 | /* Wake the sleeping khvcd */ | 285 | /* Wake the sleeping khvcd */ |
303 | static void hvc_kick(void) | 286 | void hvc_kick(void) |
304 | { | 287 | { |
305 | hvc_kicked = 1; | 288 | hvc_kicked = 1; |
306 | wake_up_process(hvc_task); | 289 | wake_up_process(hvc_task); |
307 | } | 290 | } |
308 | 291 | EXPORT_SYMBOL_GPL(hvc_kick); | |
309 | static int hvc_poll(struct hvc_struct *hp); | ||
310 | |||
311 | /* | ||
312 | * NOTE: This API isn't used if the console adapter doesn't support interrupts. | ||
313 | * In this case the console is poll driven. | ||
314 | */ | ||
315 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
316 | { | ||
317 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
318 | if (hvc_poll(dev_instance)) | ||
319 | hvc_kick(); | ||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | 292 | ||
323 | static void hvc_unthrottle(struct tty_struct *tty) | 293 | static void hvc_unthrottle(struct tty_struct *tty) |
324 | { | 294 | { |
@@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
333 | { | 303 | { |
334 | struct hvc_struct *hp; | 304 | struct hvc_struct *hp; |
335 | unsigned long flags; | 305 | unsigned long flags; |
336 | int irq = 0; | ||
337 | int rc = 0; | 306 | int rc = 0; |
338 | 307 | ||
339 | /* Auto increments kref reference if found. */ | 308 | /* Auto increments kref reference if found. */ |
@@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
352 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ | 321 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ |
353 | 322 | ||
354 | hp->tty = tty; | 323 | hp->tty = tty; |
355 | /* Save for request_irq outside of spin_lock. */ | 324 | |
356 | irq = hp->irq; | 325 | if (hp->ops->notifier_add) |
357 | if (irq) | 326 | rc = hp->ops->notifier_add(hp, hp->data); |
358 | hp->irq_requested = 1; | ||
359 | 327 | ||
360 | spin_unlock_irqrestore(&hp->lock, flags); | 328 | spin_unlock_irqrestore(&hp->lock, flags); |
361 | /* check error, fallback to non-irq */ | 329 | |
362 | if (irq) | ||
363 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); | ||
364 | 330 | ||
365 | /* | 331 | /* |
366 | * If the request_irq() fails and we return an error. The tty layer | 332 | * If the notifier fails we return an error. The tty layer |
367 | * will call hvc_close() after a failed open but we don't want to clean | 333 | * will call hvc_close() after a failed open but we don't want to clean |
368 | * up there so we'll clean up here and clear out the previously set | 334 | * up there so we'll clean up here and clear out the previously set |
369 | * tty fields and return the kref reference. | 335 | * tty fields and return the kref reference. |
@@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
371 | if (rc) { | 337 | if (rc) { |
372 | spin_lock_irqsave(&hp->lock, flags); | 338 | spin_lock_irqsave(&hp->lock, flags); |
373 | hp->tty = NULL; | 339 | hp->tty = NULL; |
374 | hp->irq_requested = 0; | ||
375 | spin_unlock_irqrestore(&hp->lock, flags); | 340 | spin_unlock_irqrestore(&hp->lock, flags); |
376 | tty->driver_data = NULL; | 341 | tty->driver_data = NULL; |
377 | kref_put(&hp->kref, destroy_hvc_struct); | 342 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
386 | static void hvc_close(struct tty_struct *tty, struct file * filp) | 351 | static void hvc_close(struct tty_struct *tty, struct file * filp) |
387 | { | 352 | { |
388 | struct hvc_struct *hp; | 353 | struct hvc_struct *hp; |
389 | int irq = 0; | ||
390 | unsigned long flags; | 354 | unsigned long flags; |
391 | 355 | ||
392 | if (tty_hung_up_p(filp)) | 356 | if (tty_hung_up_p(filp)) |
@@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
404 | spin_lock_irqsave(&hp->lock, flags); | 368 | spin_lock_irqsave(&hp->lock, flags); |
405 | 369 | ||
406 | if (--hp->count == 0) { | 370 | if (--hp->count == 0) { |
407 | if (hp->irq_requested) | 371 | if (hp->ops->notifier_del) |
408 | irq = hp->irq; | 372 | hp->ops->notifier_del(hp, hp->data); |
409 | hp->irq_requested = 0; | ||
410 | 373 | ||
411 | /* We are done with the tty pointer now. */ | 374 | /* We are done with the tty pointer now. */ |
412 | hp->tty = NULL; | 375 | hp->tty = NULL; |
@@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
418 | * waking periodically to check chars_in_buffer(). | 381 | * waking periodically to check chars_in_buffer(). |
419 | */ | 382 | */ |
420 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | 383 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); |
421 | |||
422 | if (irq) | ||
423 | free_irq(irq, hp); | ||
424 | |||
425 | } else { | 384 | } else { |
426 | if (hp->count < 0) | 385 | if (hp->count < 0) |
427 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", | 386 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
@@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty) | |||
436 | { | 395 | { |
437 | struct hvc_struct *hp = tty->driver_data; | 396 | struct hvc_struct *hp = tty->driver_data; |
438 | unsigned long flags; | 397 | unsigned long flags; |
439 | int irq = 0; | ||
440 | int temp_open_count; | 398 | int temp_open_count; |
441 | 399 | ||
442 | if (!hp) | 400 | if (!hp) |
@@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty) | |||
458 | hp->count = 0; | 416 | hp->count = 0; |
459 | hp->n_outbuf = 0; | 417 | hp->n_outbuf = 0; |
460 | hp->tty = NULL; | 418 | hp->tty = NULL; |
461 | if (hp->irq_requested) | 419 | |
462 | /* Saved for use outside of spin_lock. */ | 420 | if (hp->ops->notifier_del) |
463 | irq = hp->irq; | 421 | hp->ops->notifier_del(hp, hp->data); |
464 | hp->irq_requested = 0; | 422 | |
465 | spin_unlock_irqrestore(&hp->lock, flags); | 423 | spin_unlock_irqrestore(&hp->lock, flags); |
466 | if (irq) | 424 | |
467 | free_irq(irq, hp); | ||
468 | while(temp_open_count) { | 425 | while(temp_open_count) { |
469 | --temp_open_count; | 426 | --temp_open_count; |
470 | kref_put(&hp->kref, destroy_hvc_struct); | 427 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT; | |||
575 | #define HVC_POLL_READ 0x00000001 | 532 | #define HVC_POLL_READ 0x00000001 |
576 | #define HVC_POLL_WRITE 0x00000002 | 533 | #define HVC_POLL_WRITE 0x00000002 |
577 | 534 | ||
578 | static int hvc_poll(struct hvc_struct *hp) | 535 | int hvc_poll(struct hvc_struct *hp) |
579 | { | 536 | { |
580 | struct tty_struct *tty; | 537 | struct tty_struct *tty; |
581 | int i, n, poll_mask = 0; | 538 | int i, n, poll_mask = 0; |
@@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp) | |||
602 | if (test_bit(TTY_THROTTLED, &tty->flags)) | 559 | if (test_bit(TTY_THROTTLED, &tty->flags)) |
603 | goto throttled; | 560 | goto throttled; |
604 | 561 | ||
605 | /* If we aren't interrupt driven and aren't throttled, we always | 562 | /* If we aren't notifier driven and aren't throttled, we always |
606 | * request a reschedule | 563 | * request a reschedule |
607 | */ | 564 | */ |
608 | if (hp->irq == 0) | 565 | if (!hp->irq_requested) |
609 | poll_mask |= HVC_POLL_READ; | 566 | poll_mask |= HVC_POLL_READ; |
610 | 567 | ||
611 | /* Read data if any */ | 568 | /* Read data if any */ |
@@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp) | |||
674 | 631 | ||
675 | return poll_mask; | 632 | return poll_mask; |
676 | } | 633 | } |
634 | EXPORT_SYMBOL_GPL(hvc_poll); | ||
677 | 635 | ||
678 | /* | 636 | /* |
679 | * This kthread is either polling or interrupt driven. This is determined by | 637 | * This kthread is either polling or interrupt driven. This is determined by |
@@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = { | |||
733 | .chars_in_buffer = hvc_chars_in_buffer, | 691 | .chars_in_buffer = hvc_chars_in_buffer, |
734 | }; | 692 | }; |
735 | 693 | ||
736 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | 694 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, |
737 | struct hv_ops *ops, int outbuf_size) | 695 | struct hv_ops *ops, int outbuf_size) |
738 | { | 696 | { |
739 | struct hvc_struct *hp; | 697 | struct hvc_struct *hp; |
@@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
754 | memset(hp, 0x00, sizeof(*hp)); | 712 | memset(hp, 0x00, sizeof(*hp)); |
755 | 713 | ||
756 | hp->vtermno = vtermno; | 714 | hp->vtermno = vtermno; |
757 | hp->irq = irq; | 715 | hp->data = data; |
758 | hp->ops = ops; | 716 | hp->ops = ops; |
759 | hp->outbuf_size = outbuf_size; | 717 | hp->outbuf_size = outbuf_size; |
760 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; | 718 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; |
@@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
784 | 742 | ||
785 | return hp; | 743 | return hp; |
786 | } | 744 | } |
745 | EXPORT_SYMBOL_GPL(hvc_alloc); | ||
787 | 746 | ||
788 | int __devexit hvc_remove(struct hvc_struct *hp) | 747 | int __devexit hvc_remove(struct hvc_struct *hp) |
789 | { | 748 | { |