Skip to content

Commit

Permalink
[S390] console flush on panic / reboot
Browse files Browse the repository at this point in the history
The s390 console drivers use the unblank callback of the console
structure to flush the console buffer. In case of a panic or a
reboot the CPU doing the callback can block on the console i/o.
The other CPUs in the system continue to work. For panic this is
not a good idea.

Replace the unblank callback with proper panic/reboot notifier.
These get called after all but one CPU have been stopped.

Signed-off-by: Holger Smolinski <Holger.Smolinski@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Holger Smolinski authored and Martin Schwidefsky committed Oct 10, 2008
1 parent 15e86b0 commit 2332ce1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 18 deletions.
27 changes: 23 additions & 4 deletions drivers/s390/char/con3215.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/reboot.h>

#include <linux/slab.h>
#include <linux/bootmem.h>
Expand Down Expand Up @@ -775,11 +776,11 @@ static struct tty_driver *con3215_device(struct console *c, int *index)
}

/*
* panic() calls console_unblank before the system enters a
* disabled, endless loop.
* panic() calls con3215_flush through a panic_notifier
* before the system enters a disabled, endless loop.
*/
static void
con3215_unblank(void)
con3215_flush(void)
{
struct raw3215_info *raw;
unsigned long flags;
Expand All @@ -790,14 +791,30 @@ con3215_unblank(void)
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
}

static int con3215_notify(struct notifier_block *self,
unsigned long event, void *data)
{
con3215_flush();
return NOTIFY_OK;
}

static struct notifier_block on_panic_nb = {
.notifier_call = con3215_notify,
.priority = 0,
};

static struct notifier_block on_reboot_nb = {
.notifier_call = con3215_notify,
.priority = 0,
};

/*
* The console structure for the 3215 console
*/
static struct console con3215 = {
.name = "ttyS",
.write = con3215_write,
.device = con3215_device,
.unblank = con3215_unblank,
.flags = CON_PRINTBUFFER,
};

Expand Down Expand Up @@ -859,6 +876,8 @@ con3215_init(void)
raw3215[0] = NULL;
return -ENODEV;
}
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
register_reboot_notifier(&on_reboot_nb);
register_console(&con3215);
return 0;
}
Expand Down
27 changes: 23 additions & 4 deletions drivers/s390/char/con3270.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/reboot.h>

#include <asm/ccwdev.h>
#include <asm/cio.h>
Expand Down Expand Up @@ -528,11 +529,11 @@ con3270_wait_write(struct con3270 *cp)
}

/*
* panic() calls console_unblank before the system enters a
* disabled, endless loop.
* panic() calls con3270_flush through a panic_notifier
* before the system enters a disabled, endless loop.
*/
static void
con3270_unblank(void)
con3270_flush(void)
{
struct con3270 *cp;
unsigned long flags;
Expand All @@ -554,14 +555,30 @@ con3270_unblank(void)
spin_unlock_irqrestore(&cp->view.lock, flags);
}

static int con3270_notify(struct notifier_block *self,
unsigned long event, void *data)
{
con3270_flush();
return NOTIFY_OK;
}

static struct notifier_block on_panic_nb = {
.notifier_call = con3270_notify,
.priority = 0,
};

static struct notifier_block on_reboot_nb = {
.notifier_call = con3270_notify,
.priority = 0,
};

/*
* The console structure for the 3270 console
*/
static struct console con3270 = {
.name = "tty3270",
.write = con3270_write,
.device = con3270_device,
.unblank = con3270_unblank,
.flags = CON_PRINTBUFFER,
};

Expand Down Expand Up @@ -623,6 +640,8 @@ con3270_init(void)
condev->cline->len = 0;
con3270_create_status(condev);
condev->input = alloc_string(&condev->freemem, 80);
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
register_reboot_notifier(&on_reboot_nb);
register_console(&con3270);
return 0;
}
Expand Down
24 changes: 22 additions & 2 deletions drivers/s390/char/sclp_con.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/termios.h>
#include <linux/err.h>
#include <linux/reboot.h>

#include "sclp.h"
#include "sclp_rw.h"
Expand Down Expand Up @@ -172,7 +173,7 @@ sclp_console_device(struct console *c, int *index)
* will be flushed to the SCLP.
*/
static void
sclp_console_unblank(void)
sclp_console_flush(void)
{
unsigned long flags;

Expand All @@ -188,6 +189,24 @@ sclp_console_unblank(void)
spin_unlock_irqrestore(&sclp_con_lock, flags);
}

static int
sclp_console_notify(struct notifier_block *self,
unsigned long event, void *data)
{
sclp_console_flush();
return NOTIFY_OK;
}

static struct notifier_block on_panic_nb = {
.notifier_call = sclp_console_notify,
.priority = 1,
};

static struct notifier_block on_reboot_nb = {
.notifier_call = sclp_console_notify,
.priority = 1,
};

/*
* used to register the SCLP console to the kernel and to
* give printk necessary information
Expand All @@ -197,7 +216,6 @@ static struct console sclp_console =
.name = sclp_console_name,
.write = sclp_console_write,
.device = sclp_console_device,
.unblank = sclp_console_unblank,
.flags = CON_PRINTBUFFER,
.index = 0 /* ttyS0 */
};
Expand Down Expand Up @@ -241,6 +259,8 @@ sclp_console_init(void)
sclp_con_width_htab = 8;

/* enable printk-access to this driver */
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
register_reboot_notifier(&on_reboot_nb);
register_console(&sclp_console);
return 0;
}
Expand Down
26 changes: 18 additions & 8 deletions drivers/s390/char/sclp_vt220.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <linux/bootmem.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/reboot.h>

#include <asm/uaccess.h>
#include "sclp.h"

Expand Down Expand Up @@ -743,24 +745,30 @@ sclp_vt220_con_device(struct console *c, int *index)
return sclp_vt220_driver;
}

/*
* This routine is called from panic when the kernel is going to give up.
* We have to make sure that all buffers will be flushed to the SCLP.
* Note that this function may be called from within an interrupt context.
*/
static void
sclp_vt220_con_unblank(void)
static int
sclp_vt220_notify(struct notifier_block *self,
unsigned long event, void *data)
{
__sclp_vt220_flush_buffer();
return NOTIFY_OK;
}

static struct notifier_block on_panic_nb = {
.notifier_call = sclp_vt220_notify,
.priority = 1,
};

static struct notifier_block on_reboot_nb = {
.notifier_call = sclp_vt220_notify,
.priority = 1,
};

/* Structure needed to register with printk */
static struct console sclp_vt220_console =
{
.name = SCLP_VT220_CONSOLE_NAME,
.write = sclp_vt220_con_write,
.device = sclp_vt220_con_device,
.unblank = sclp_vt220_con_unblank,
.flags = CON_PRINTBUFFER,
.index = SCLP_VT220_CONSOLE_INDEX
};
Expand All @@ -776,6 +784,8 @@ sclp_vt220_con_init(void)
if (rc)
return rc;
/* Attach linux console */
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
register_reboot_notifier(&on_reboot_nb);
register_console(&sclp_vt220_console);
return 0;
}
Expand Down

0 comments on commit 2332ce1

Please sign in to comment.