[S390] sclp_vt220: Fix vt220 initialization

There are two problems in the vt220 intialization:

o Currently the vt220 console looses early printk events until the
  the vt220 tty is registered.
o console should work if tty_register fails

sclp_vt220_con_init calls __sclp_vt220_init and register_console.
It does not register the driver with the sclp core code via
sclp_register. That results in an sclp_send_mask=0. Therefore,
__sclp_vt220_emit will reject buffers with EIO. Unfortunately
register_console will cause the printk buffer to be sent to the
console and, therefore, every early message gets dropped. The
sclp_send_mask is set later during boot, when sclp_vt220_tty_init
calls sclp_register.

The solution is to move the sclp_register call from sclp_vt220_tty_init
to __sclp_vt220_init. This makes sure that the console is properly
registered with the sclp subsystem before the first log buffer messages
are passed to the vt220 console.

We also adopt the cleanup on error to keep the console alive if
tty_register fails.

Thanks to Peter Oberparleiter and Heiko Carstens for review and ideas
for improvement.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Christian Borntraeger 2008-02-09 18:24:33 +01:00 committed by Martin Schwidefsky
parent bf3f837804
commit 59eb1ca7a8
1 changed files with 18 additions and 13 deletions

View File

@ -3,7 +3,7 @@
* SCLP VT220 terminal driver. * SCLP VT220 terminal driver.
* *
* S390 version * S390 version
* Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright IBM Corp. 2003,2008
* Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com> * Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
*/ */
@ -632,6 +632,9 @@ 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) static int __init __sclp_vt220_init(void)
@ -639,6 +642,7 @@ static int __init __sclp_vt220_init(void)
void *page; void *page;
int i; int i;
int num_pages; int num_pages;
int rc;
if (sclp_vt220_initialized) if (sclp_vt220_initialized)
return 0; return 0;
@ -667,7 +671,14 @@ static int __init __sclp_vt220_init(void)
} }
list_add_tail((struct list_head *) page, &sclp_vt220_empty); list_add_tail((struct list_head *) page, &sclp_vt220_empty);
} }
return 0; rc = sclp_register(&sclp_vt220_register);
if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register vt220 - "
"sclp_register returned %d\n", rc);
__sclp_vt220_cleanup();
}
return rc;
} }
static const struct tty_operations sclp_vt220_ops = { static const struct tty_operations sclp_vt220_ops = {
@ -688,22 +699,17 @@ 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(); rc = __sclp_vt220_init();
if (rc) if (rc)
goto out_driver; goto out_driver;
rc = sclp_register(&sclp_vt220_register);
if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - "
"sclp_register returned %d\n", rc);
goto out_init;
}
driver->owner = THIS_MODULE; driver->owner = THIS_MODULE;
driver->driver_name = SCLP_VT220_DRIVER_NAME; driver->driver_name = SCLP_VT220_DRIVER_NAME;
@ -721,15 +727,14 @@ static int __init sclp_vt220_tty_init(void)
printk(KERN_ERR SCLP_VT220_PRINT_HEADER printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - " "could not register tty - "
"tty_register_driver returned %d\n", rc); "tty_register_driver returned %d\n", rc);
goto out_sclp; goto out_init;
} }
sclp_vt220_driver = driver; sclp_vt220_driver = driver;
return 0; return 0;
out_sclp:
sclp_unregister(&sclp_vt220_register);
out_init: out_init:
__sclp_vt220_cleanup(); if (cleanup)
__sclp_vt220_cleanup();
out_driver: out_driver:
put_tty_driver(driver); put_tty_driver(driver);
return rc; return rc;