Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2332ce1a authored by Holger Smolinski's avatar Holger Smolinski Committed by Martin Schwidefsky
Browse files

[S390] console flush on panic / reboot



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: default avatarHolger Smolinski <Holger.Smolinski@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 15e86b0c
Loading
Loading
Loading
Loading
+23 −4
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/console.h>
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/reboot.h>


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


/*
/*
 * panic() calls console_unblank before the system enters a
 * panic() calls con3215_flush through a panic_notifier
 * disabled, endless loop.
 * before the system enters a disabled, endless loop.
 */
 */
static void
static void
con3215_unblank(void)
con3215_flush(void)
{
{
	struct raw3215_info *raw;
	struct raw3215_info *raw;
	unsigned long flags;
	unsigned long flags;
@@ -790,6 +791,23 @@ con3215_unblank(void)
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
	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
 *  The console structure for the 3215 console
 */
 */
@@ -797,7 +815,6 @@ static struct console con3215 = {
	.name	 = "ttyS",
	.name	 = "ttyS",
	.write	 = con3215_write,
	.write	 = con3215_write,
	.device	 = con3215_device,
	.device	 = con3215_device,
	.unblank = con3215_unblank,
	.flags	 = CON_PRINTBUFFER,
	.flags	 = CON_PRINTBUFFER,
};
};


@@ -859,6 +876,8 @@ con3215_init(void)
		raw3215[0] = NULL;
		raw3215[0] = NULL;
		return -ENODEV;
		return -ENODEV;
	}
	}
	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
	register_reboot_notifier(&on_reboot_nb);
	register_console(&con3215);
	register_console(&con3215);
	return 0;
	return 0;
}
}
+23 −4
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/reboot.h>


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


/*
/*
 * panic() calls console_unblank before the system enters a
 * panic() calls con3270_flush through a panic_notifier
 * disabled, endless loop.
 * before the system enters a disabled, endless loop.
 */
 */
static void
static void
con3270_unblank(void)
con3270_flush(void)
{
{
	struct con3270 *cp;
	struct con3270 *cp;
	unsigned long flags;
	unsigned long flags;
@@ -554,6 +555,23 @@ con3270_unblank(void)
	spin_unlock_irqrestore(&cp->view.lock, flags);
	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
 *  The console structure for the 3270 console
 */
 */
@@ -561,7 +579,6 @@ static struct console con3270 = {
	.name	 = "tty3270",
	.name	 = "tty3270",
	.write	 = con3270_write,
	.write	 = con3270_write,
	.device	 = con3270_device,
	.device	 = con3270_device,
	.unblank = con3270_unblank,
	.flags	 = CON_PRINTBUFFER,
	.flags	 = CON_PRINTBUFFER,
};
};


@@ -623,6 +640,8 @@ con3270_init(void)
	condev->cline->len = 0;
	condev->cline->len = 0;
	con3270_create_status(condev);
	con3270_create_status(condev);
	condev->input = alloc_string(&condev->freemem, 80);
	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);
	register_console(&con3270);
	return 0;
	return 0;
}
}
+22 −2
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/bootmem.h>
#include <linux/termios.h>
#include <linux/termios.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/reboot.h>


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


@@ -188,6 +189,24 @@ sclp_console_unblank(void)
	spin_unlock_irqrestore(&sclp_con_lock, flags);
	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
 * used to register the SCLP console to the kernel and to
 * give printk necessary information
 * give printk necessary information
@@ -197,7 +216,6 @@ static struct console sclp_console =
	.name = sclp_console_name,
	.name = sclp_console_name,
	.write = sclp_console_write,
	.write = sclp_console_write,
	.device = sclp_console_device,
	.device = sclp_console_device,
	.unblank = sclp_console_unblank,
	.flags = CON_PRINTBUFFER,
	.flags = CON_PRINTBUFFER,
	.index = 0 /* ttyS0 */
	.index = 0 /* ttyS0 */
};
};
@@ -241,6 +259,8 @@ sclp_console_init(void)
	sclp_con_width_htab = 8;
	sclp_con_width_htab = 8;


	/* enable printk-access to this driver */
	/* 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);
	register_console(&sclp_console);
	return 0;
	return 0;
}
}
+18 −8
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@
#include <linux/bootmem.h>
#include <linux/bootmem.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/reboot.h>

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


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


/*
static int
 * This routine is called from panic when the kernel is going to give up.
sclp_vt220_notify(struct notifier_block *self,
 * We have to make sure that all buffers will be flushed to the SCLP.
			  unsigned long event, void *data)
 * Note that this function may be called from within an interrupt context.
 */
static void
sclp_vt220_con_unblank(void)
{
{
	__sclp_vt220_flush_buffer();
	__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 */
/* Structure needed to register with printk */
static struct console sclp_vt220_console =
static struct console sclp_vt220_console =
{
{
	.name = SCLP_VT220_CONSOLE_NAME,
	.name = SCLP_VT220_CONSOLE_NAME,
	.write = sclp_vt220_con_write,
	.write = sclp_vt220_con_write,
	.device = sclp_vt220_con_device,
	.device = sclp_vt220_con_device,
	.unblank = sclp_vt220_con_unblank,
	.flags = CON_PRINTBUFFER,
	.flags = CON_PRINTBUFFER,
	.index = SCLP_VT220_CONSOLE_INDEX
	.index = SCLP_VT220_CONSOLE_INDEX
};
};
@@ -776,6 +784,8 @@ sclp_vt220_con_init(void)
	if (rc)
	if (rc)
		return rc;
		return rc;
	/* Attach linux console */
	/* Attach linux console */
	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
	register_reboot_notifier(&on_reboot_nb);
	register_console(&sclp_vt220_console);
	register_console(&sclp_vt220_console);
	return 0;
	return 0;
}
}