[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>
This commit is contained in:
Peter Oberparleiter 2008-07-14 09:59:07 +02:00 committed by Heiko Carstens
parent 773922e1da
commit ad211790c0
1 changed files with 28 additions and 27 deletions

View File

@ -82,8 +82,8 @@ static struct sclp_vt220_request *sclp_vt220_current_request;
/* Number of characters in current request buffer */ /* Number of characters in current request buffer */
static int sclp_vt220_buffered_chars; static int sclp_vt220_buffered_chars;
/* Flag indicating whether this driver has already been initialized */ /* Counter controlling core driver initialization. */
static int sclp_vt220_initialized = 0; static int __initdata sclp_vt220_init_count;
/* Flag indicating that sclp_vt220_current_request should really /* Flag indicating that sclp_vt220_current_request should really
* have been already queued but wasn't because the SCLP was processing * have been already queued but wasn't because the SCLP was processing
@ -609,10 +609,8 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
sclp_vt220_emit_current(); sclp_vt220_emit_current();
} }
/* /* Release allocated pages. */
* Initialize all relevant components and register driver with system. static void __init __sclp_vt220_free_pages(void)
*/
static void __init __sclp_vt220_cleanup(void)
{ {
struct list_head *page, *p; struct list_head *page, *p;
@ -623,21 +621,30 @@ static void __init __sclp_vt220_cleanup(void)
else else
free_bootmem((unsigned long) page, PAGE_SIZE); free_bootmem((unsigned long) page, PAGE_SIZE);
} }
if (!list_empty(&sclp_vt220_register.list))
sclp_unregister(&sclp_vt220_register);
sclp_vt220_initialized = 0;
} }
static int __init __sclp_vt220_init(void) /* Release memory and unregister from sclp core. Controlled by init counting -
* only the last invoker will actually perform these actions. */
static void __init __sclp_vt220_cleanup(void)
{
sclp_vt220_init_count--;
if (sclp_vt220_init_count != 0)
return;
sclp_unregister(&sclp_vt220_register);
__sclp_vt220_free_pages();
}
/* Allocate buffer pages and register with sclp core. Controlled by init
* counting - only the first invoker will actually perform these actions. */
static int __init __sclp_vt220_init(int num_pages)
{ {
void *page; void *page;
int i; int i;
int num_pages;
int rc; int rc;
if (sclp_vt220_initialized) sclp_vt220_init_count++;
if (sclp_vt220_init_count != 1)
return 0; return 0;
sclp_vt220_initialized = 1;
spin_lock_init(&sclp_vt220_lock); spin_lock_init(&sclp_vt220_lock);
INIT_LIST_HEAD(&sclp_vt220_empty); INIT_LIST_HEAD(&sclp_vt220_empty);
INIT_LIST_HEAD(&sclp_vt220_outqueue); INIT_LIST_HEAD(&sclp_vt220_outqueue);
@ -649,24 +656,22 @@ static int __init __sclp_vt220_init(void)
sclp_vt220_flush_later = 0; sclp_vt220_flush_later = 0;
/* Allocate pages for output buffering */ /* Allocate pages for output buffering */
num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
for (i = 0; i < num_pages; i++) { for (i = 0; i < num_pages; i++) {
if (slab_is_available()) if (slab_is_available())
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
else else
page = alloc_bootmem_low_pages(PAGE_SIZE); page = alloc_bootmem_low_pages(PAGE_SIZE);
if (!page) { if (!page) {
__sclp_vt220_cleanup(); rc = -ENOMEM;
return -ENOMEM; goto out;
} }
list_add_tail((struct list_head *) page, &sclp_vt220_empty); list_add_tail((struct list_head *) page, &sclp_vt220_empty);
} }
rc = sclp_register(&sclp_vt220_register); rc = sclp_register(&sclp_vt220_register);
out:
if (rc) { if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER __sclp_vt220_free_pages();
"could not register vt220 - " sclp_vt220_init_count--;
"sclp_register returned %d\n", rc);
__sclp_vt220_cleanup();
} }
return rc; return rc;
} }
@ -689,15 +694,13 @@ static int __init sclp_vt220_tty_init(void)
{ {
struct tty_driver *driver; struct tty_driver *driver;
int rc; int rc;
int cleanup;
/* Note: we're not testing for CONSOLE_IS_SCLP here to preserve /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
* symmetry between VM and LPAR systems regarding ttyS1. */ * symmetry between VM and LPAR systems regarding ttyS1. */
driver = alloc_tty_driver(1); driver = alloc_tty_driver(1);
if (!driver) if (!driver)
return -ENOMEM; return -ENOMEM;
cleanup = !sclp_vt220_initialized; rc = __sclp_vt220_init(MAX_KMEM_PAGES);
rc = __sclp_vt220_init();
if (rc) if (rc)
goto out_driver; goto out_driver;
@ -723,8 +726,7 @@ static int __init sclp_vt220_tty_init(void)
return 0; return 0;
out_init: out_init:
if (cleanup) __sclp_vt220_cleanup();
__sclp_vt220_cleanup();
out_driver: out_driver:
put_tty_driver(driver); put_tty_driver(driver);
return rc; return rc;
@ -773,10 +775,9 @@ sclp_vt220_con_init(void)
{ {
int rc; int rc;
INIT_LIST_HEAD(&sclp_vt220_register.list);
if (!CONSOLE_IS_SCLP) if (!CONSOLE_IS_SCLP)
return 0; return 0;
rc = __sclp_vt220_init(); rc = __sclp_vt220_init(MAX_CONSOLE_PAGES);
if (rc) if (rc)
return rc; return rc;
/* Attach linux console */ /* Attach linux console */