diff options
author | Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | 2008-07-14 03:59:07 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-07-14 04:02:13 -0400 |
commit | ad211790c040fae3459e9c4c8cbd681ae126d2b8 (patch) | |
tree | 2f9cb8e384ce571d9a34eee45886177025ba0807 /drivers | |
parent | 773922e1dab93a62e60cfb34afadb0f66d5f12e9 (diff) |
[S390] sclp: simplify vt220 cleanup logic
Fix a number of sclp_vt220 cleanup problems:
* fix list_empty check after list_del()
* mark init-only flag as __initdata
* remove implicit dependency between slab_available() and num_pages
* straighten multiple init handling (use init count)
Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/char/sclp_vt220.c | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 3e577f655b18..baea4d548523 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
@@ -82,8 +82,8 @@ static struct sclp_vt220_request *sclp_vt220_current_request; | |||
82 | /* Number of characters in current request buffer */ | 82 | /* Number of characters in current request buffer */ |
83 | static int sclp_vt220_buffered_chars; | 83 | static int sclp_vt220_buffered_chars; |
84 | 84 | ||
85 | /* Flag indicating whether this driver has already been initialized */ | 85 | /* Counter controlling core driver initialization. */ |
86 | static int sclp_vt220_initialized = 0; | 86 | static int __initdata sclp_vt220_init_count; |
87 | 87 | ||
88 | /* Flag indicating that sclp_vt220_current_request should really | 88 | /* Flag indicating that sclp_vt220_current_request should really |
89 | * have been already queued but wasn't because the SCLP was processing | 89 | * have been already queued but wasn't because the SCLP was processing |
@@ -609,10 +609,8 @@ sclp_vt220_flush_buffer(struct tty_struct *tty) | |||
609 | sclp_vt220_emit_current(); | 609 | sclp_vt220_emit_current(); |
610 | } | 610 | } |
611 | 611 | ||
612 | /* | 612 | /* Release allocated pages. */ |
613 | * Initialize all relevant components and register driver with system. | 613 | static void __init __sclp_vt220_free_pages(void) |
614 | */ | ||
615 | static void __init __sclp_vt220_cleanup(void) | ||
616 | { | 614 | { |
617 | struct list_head *page, *p; | 615 | struct list_head *page, *p; |
618 | 616 | ||
@@ -623,21 +621,30 @@ static void __init __sclp_vt220_cleanup(void) | |||
623 | else | 621 | else |
624 | free_bootmem((unsigned long) page, PAGE_SIZE); | 622 | free_bootmem((unsigned long) page, PAGE_SIZE); |
625 | } | 623 | } |
626 | if (!list_empty(&sclp_vt220_register.list)) | ||
627 | sclp_unregister(&sclp_vt220_register); | ||
628 | sclp_vt220_initialized = 0; | ||
629 | } | 624 | } |
630 | 625 | ||
631 | static int __init __sclp_vt220_init(void) | 626 | /* Release memory and unregister from sclp core. Controlled by init counting - |
627 | * only the last invoker will actually perform these actions. */ | ||
628 | static void __init __sclp_vt220_cleanup(void) | ||
629 | { | ||
630 | sclp_vt220_init_count--; | ||
631 | if (sclp_vt220_init_count != 0) | ||
632 | return; | ||
633 | sclp_unregister(&sclp_vt220_register); | ||
634 | __sclp_vt220_free_pages(); | ||
635 | } | ||
636 | |||
637 | /* Allocate buffer pages and register with sclp core. Controlled by init | ||
638 | * counting - only the first invoker will actually perform these actions. */ | ||
639 | static int __init __sclp_vt220_init(int num_pages) | ||
632 | { | 640 | { |
633 | void *page; | 641 | void *page; |
634 | int i; | 642 | int i; |
635 | int num_pages; | ||
636 | int rc; | 643 | int rc; |
637 | 644 | ||
638 | if (sclp_vt220_initialized) | 645 | sclp_vt220_init_count++; |
646 | if (sclp_vt220_init_count != 1) | ||
639 | return 0; | 647 | return 0; |
640 | sclp_vt220_initialized = 1; | ||
641 | spin_lock_init(&sclp_vt220_lock); | 648 | spin_lock_init(&sclp_vt220_lock); |
642 | INIT_LIST_HEAD(&sclp_vt220_empty); | 649 | INIT_LIST_HEAD(&sclp_vt220_empty); |
643 | INIT_LIST_HEAD(&sclp_vt220_outqueue); | 650 | INIT_LIST_HEAD(&sclp_vt220_outqueue); |
@@ -649,24 +656,22 @@ static int __init __sclp_vt220_init(void) | |||
649 | sclp_vt220_flush_later = 0; | 656 | sclp_vt220_flush_later = 0; |
650 | 657 | ||
651 | /* Allocate pages for output buffering */ | 658 | /* Allocate pages for output buffering */ |
652 | num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES; | ||
653 | for (i = 0; i < num_pages; i++) { | 659 | for (i = 0; i < num_pages; i++) { |
654 | if (slab_is_available()) | 660 | if (slab_is_available()) |
655 | page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | 661 | page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
656 | else | 662 | else |
657 | page = alloc_bootmem_low_pages(PAGE_SIZE); | 663 | page = alloc_bootmem_low_pages(PAGE_SIZE); |
658 | if (!page) { | 664 | if (!page) { |
659 | __sclp_vt220_cleanup(); | 665 | rc = -ENOMEM; |
660 | return -ENOMEM; | 666 | goto out; |
661 | } | 667 | } |
662 | list_add_tail((struct list_head *) page, &sclp_vt220_empty); | 668 | list_add_tail((struct list_head *) page, &sclp_vt220_empty); |
663 | } | 669 | } |
664 | rc = sclp_register(&sclp_vt220_register); | 670 | rc = sclp_register(&sclp_vt220_register); |
671 | out: | ||
665 | if (rc) { | 672 | if (rc) { |
666 | printk(KERN_ERR SCLP_VT220_PRINT_HEADER | 673 | __sclp_vt220_free_pages(); |
667 | "could not register vt220 - " | 674 | sclp_vt220_init_count--; |
668 | "sclp_register returned %d\n", rc); | ||
669 | __sclp_vt220_cleanup(); | ||
670 | } | 675 | } |
671 | return rc; | 676 | return rc; |
672 | } | 677 | } |
@@ -689,15 +694,13 @@ static int __init sclp_vt220_tty_init(void) | |||
689 | { | 694 | { |
690 | struct tty_driver *driver; | 695 | struct tty_driver *driver; |
691 | int rc; | 696 | int rc; |
692 | int cleanup; | ||
693 | 697 | ||
694 | /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve | 698 | /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve |
695 | * symmetry between VM and LPAR systems regarding ttyS1. */ | 699 | * symmetry between VM and LPAR systems regarding ttyS1. */ |
696 | driver = alloc_tty_driver(1); | 700 | driver = alloc_tty_driver(1); |
697 | if (!driver) | 701 | if (!driver) |
698 | return -ENOMEM; | 702 | return -ENOMEM; |
699 | cleanup = !sclp_vt220_initialized; | 703 | rc = __sclp_vt220_init(MAX_KMEM_PAGES); |
700 | rc = __sclp_vt220_init(); | ||
701 | if (rc) | 704 | if (rc) |
702 | goto out_driver; | 705 | goto out_driver; |
703 | 706 | ||
@@ -723,8 +726,7 @@ static int __init sclp_vt220_tty_init(void) | |||
723 | return 0; | 726 | return 0; |
724 | 727 | ||
725 | out_init: | 728 | out_init: |
726 | if (cleanup) | 729 | __sclp_vt220_cleanup(); |
727 | __sclp_vt220_cleanup(); | ||
728 | out_driver: | 730 | out_driver: |
729 | put_tty_driver(driver); | 731 | put_tty_driver(driver); |
730 | return rc; | 732 | return rc; |
@@ -773,10 +775,9 @@ sclp_vt220_con_init(void) | |||
773 | { | 775 | { |
774 | int rc; | 776 | int rc; |
775 | 777 | ||
776 | INIT_LIST_HEAD(&sclp_vt220_register.list); | ||
777 | if (!CONSOLE_IS_SCLP) | 778 | if (!CONSOLE_IS_SCLP) |
778 | return 0; | 779 | return 0; |
779 | rc = __sclp_vt220_init(); | 780 | rc = __sclp_vt220_init(MAX_CONSOLE_PAGES); |
780 | if (rc) | 781 | if (rc) |
781 | return rc; | 782 | return rc; |
782 | /* Attach linux console */ | 783 | /* Attach linux console */ |