diff options
author | Holger Smolinski <Holger.Smolinski@de.ibm.com> | 2008-10-10 15:33:27 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-10-10 15:34:01 -0400 |
commit | 2332ce1a97963b7769e0c2d40492a10a124efba5 (patch) | |
tree | 38728f02d84d91c9ce6e4bb06e871cc19cbe57cd /drivers/s390/char | |
parent | 15e86b0c752d50e910b2cca6e83ce74c4440d06c (diff) |
[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: Holger Smolinski <Holger.Smolinski@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/char')
-rw-r--r-- | drivers/s390/char/con3215.c | 27 | ||||
-rw-r--r-- | drivers/s390/char/con3270.c | 27 | ||||
-rw-r--r-- | drivers/s390/char/sclp_con.c | 24 | ||||
-rw-r--r-- | drivers/s390/char/sclp_vt220.c | 26 |
4 files changed, 86 insertions, 18 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index d3ec9b55ab35..982cf62ab66d 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/reboot.h> | ||
24 | 25 | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/bootmem.h> | 27 | #include <linux/bootmem.h> |
@@ -775,11 +776,11 @@ static struct tty_driver *con3215_device(struct console *c, int *index) | |||
775 | } | 776 | } |
776 | 777 | ||
777 | /* | 778 | /* |
778 | * panic() calls console_unblank before the system enters a | 779 | * panic() calls con3215_flush through a panic_notifier |
779 | * disabled, endless loop. | 780 | * before the system enters a disabled, endless loop. |
780 | */ | 781 | */ |
781 | static void | 782 | static void |
782 | con3215_unblank(void) | 783 | con3215_flush(void) |
783 | { | 784 | { |
784 | struct raw3215_info *raw; | 785 | struct raw3215_info *raw; |
785 | unsigned long flags; | 786 | unsigned long flags; |
@@ -790,6 +791,23 @@ con3215_unblank(void) | |||
790 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); | 791 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
791 | } | 792 | } |
792 | 793 | ||
794 | static int con3215_notify(struct notifier_block *self, | ||
795 | unsigned long event, void *data) | ||
796 | { | ||
797 | con3215_flush(); | ||
798 | return NOTIFY_OK; | ||
799 | } | ||
800 | |||
801 | static struct notifier_block on_panic_nb = { | ||
802 | .notifier_call = con3215_notify, | ||
803 | .priority = 0, | ||
804 | }; | ||
805 | |||
806 | static struct notifier_block on_reboot_nb = { | ||
807 | .notifier_call = con3215_notify, | ||
808 | .priority = 0, | ||
809 | }; | ||
810 | |||
793 | /* | 811 | /* |
794 | * The console structure for the 3215 console | 812 | * The console structure for the 3215 console |
795 | */ | 813 | */ |
@@ -797,7 +815,6 @@ static struct console con3215 = { | |||
797 | .name = "ttyS", | 815 | .name = "ttyS", |
798 | .write = con3215_write, | 816 | .write = con3215_write, |
799 | .device = con3215_device, | 817 | .device = con3215_device, |
800 | .unblank = con3215_unblank, | ||
801 | .flags = CON_PRINTBUFFER, | 818 | .flags = CON_PRINTBUFFER, |
802 | }; | 819 | }; |
803 | 820 | ||
@@ -859,6 +876,8 @@ con3215_init(void) | |||
859 | raw3215[0] = NULL; | 876 | raw3215[0] = NULL; |
860 | return -ENODEV; | 877 | return -ENODEV; |
861 | } | 878 | } |
879 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); | ||
880 | register_reboot_notifier(&on_reboot_nb); | ||
862 | register_console(&con3215); | 881 | register_console(&con3215); |
863 | return 0; | 882 | return 0; |
864 | } | 883 | } |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 3c07974886ed..d028d2ee83dd 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/reboot.h> | ||
18 | 19 | ||
19 | #include <asm/ccwdev.h> | 20 | #include <asm/ccwdev.h> |
20 | #include <asm/cio.h> | 21 | #include <asm/cio.h> |
@@ -528,11 +529,11 @@ con3270_wait_write(struct con3270 *cp) | |||
528 | } | 529 | } |
529 | 530 | ||
530 | /* | 531 | /* |
531 | * panic() calls console_unblank before the system enters a | 532 | * panic() calls con3270_flush through a panic_notifier |
532 | * disabled, endless loop. | 533 | * before the system enters a disabled, endless loop. |
533 | */ | 534 | */ |
534 | static void | 535 | static void |
535 | con3270_unblank(void) | 536 | con3270_flush(void) |
536 | { | 537 | { |
537 | struct con3270 *cp; | 538 | struct con3270 *cp; |
538 | unsigned long flags; | 539 | unsigned long flags; |
@@ -554,6 +555,23 @@ con3270_unblank(void) | |||
554 | spin_unlock_irqrestore(&cp->view.lock, flags); | 555 | spin_unlock_irqrestore(&cp->view.lock, flags); |
555 | } | 556 | } |
556 | 557 | ||
558 | static int con3270_notify(struct notifier_block *self, | ||
559 | unsigned long event, void *data) | ||
560 | { | ||
561 | con3270_flush(); | ||
562 | return NOTIFY_OK; | ||
563 | } | ||
564 | |||
565 | static struct notifier_block on_panic_nb = { | ||
566 | .notifier_call = con3270_notify, | ||
567 | .priority = 0, | ||
568 | }; | ||
569 | |||
570 | static struct notifier_block on_reboot_nb = { | ||
571 | .notifier_call = con3270_notify, | ||
572 | .priority = 0, | ||
573 | }; | ||
574 | |||
557 | /* | 575 | /* |
558 | * The console structure for the 3270 console | 576 | * The console structure for the 3270 console |
559 | */ | 577 | */ |
@@ -561,7 +579,6 @@ static struct console con3270 = { | |||
561 | .name = "tty3270", | 579 | .name = "tty3270", |
562 | .write = con3270_write, | 580 | .write = con3270_write, |
563 | .device = con3270_device, | 581 | .device = con3270_device, |
564 | .unblank = con3270_unblank, | ||
565 | .flags = CON_PRINTBUFFER, | 582 | .flags = CON_PRINTBUFFER, |
566 | }; | 583 | }; |
567 | 584 | ||
@@ -623,6 +640,8 @@ con3270_init(void) | |||
623 | condev->cline->len = 0; | 640 | condev->cline->len = 0; |
624 | con3270_create_status(condev); | 641 | con3270_create_status(condev); |
625 | condev->input = alloc_string(&condev->freemem, 80); | 642 | condev->input = alloc_string(&condev->freemem, 80); |
643 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); | ||
644 | register_reboot_notifier(&on_reboot_nb); | ||
626 | register_console(&con3270); | 645 | register_console(&con3270); |
627 | return 0; | 646 | return 0; |
628 | } | 647 | } |
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index 7e619c534bf4..9a25c4bd1421 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
17 | #include <linux/termios.h> | 17 | #include <linux/termios.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/reboot.h> | ||
19 | 20 | ||
20 | #include "sclp.h" | 21 | #include "sclp.h" |
21 | #include "sclp_rw.h" | 22 | #include "sclp_rw.h" |
@@ -172,7 +173,7 @@ sclp_console_device(struct console *c, int *index) | |||
172 | * will be flushed to the SCLP. | 173 | * will be flushed to the SCLP. |
173 | */ | 174 | */ |
174 | static void | 175 | static void |
175 | sclp_console_unblank(void) | 176 | sclp_console_flush(void) |
176 | { | 177 | { |
177 | unsigned long flags; | 178 | unsigned long flags; |
178 | 179 | ||
@@ -188,6 +189,24 @@ sclp_console_unblank(void) | |||
188 | spin_unlock_irqrestore(&sclp_con_lock, flags); | 189 | spin_unlock_irqrestore(&sclp_con_lock, flags); |
189 | } | 190 | } |
190 | 191 | ||
192 | static int | ||
193 | sclp_console_notify(struct notifier_block *self, | ||
194 | unsigned long event, void *data) | ||
195 | { | ||
196 | sclp_console_flush(); | ||
197 | return NOTIFY_OK; | ||
198 | } | ||
199 | |||
200 | static struct notifier_block on_panic_nb = { | ||
201 | .notifier_call = sclp_console_notify, | ||
202 | .priority = 1, | ||
203 | }; | ||
204 | |||
205 | static struct notifier_block on_reboot_nb = { | ||
206 | .notifier_call = sclp_console_notify, | ||
207 | .priority = 1, | ||
208 | }; | ||
209 | |||
191 | /* | 210 | /* |
192 | * used to register the SCLP console to the kernel and to | 211 | * used to register the SCLP console to the kernel and to |
193 | * give printk necessary information | 212 | * give printk necessary information |
@@ -197,7 +216,6 @@ static struct console sclp_console = | |||
197 | .name = sclp_console_name, | 216 | .name = sclp_console_name, |
198 | .write = sclp_console_write, | 217 | .write = sclp_console_write, |
199 | .device = sclp_console_device, | 218 | .device = sclp_console_device, |
200 | .unblank = sclp_console_unblank, | ||
201 | .flags = CON_PRINTBUFFER, | 219 | .flags = CON_PRINTBUFFER, |
202 | .index = 0 /* ttyS0 */ | 220 | .index = 0 /* ttyS0 */ |
203 | }; | 221 | }; |
@@ -241,6 +259,8 @@ sclp_console_init(void) | |||
241 | sclp_con_width_htab = 8; | 259 | sclp_con_width_htab = 8; |
242 | 260 | ||
243 | /* enable printk-access to this driver */ | 261 | /* enable printk-access to this driver */ |
262 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); | ||
263 | register_reboot_notifier(&on_reboot_nb); | ||
244 | register_console(&sclp_console); | 264 | register_console(&sclp_console); |
245 | return 0; | 265 | return 0; |
246 | } | 266 | } |
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index ad51738c4261..9854f19f5e62 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/bootmem.h> | 24 | #include <linux/bootmem.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/reboot.h> | ||
28 | |||
27 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
28 | #include "sclp.h" | 30 | #include "sclp.h" |
29 | 31 | ||
@@ -743,24 +745,30 @@ sclp_vt220_con_device(struct console *c, int *index) | |||
743 | return sclp_vt220_driver; | 745 | return sclp_vt220_driver; |
744 | } | 746 | } |
745 | 747 | ||
746 | /* | 748 | static int |
747 | * This routine is called from panic when the kernel is going to give up. | 749 | sclp_vt220_notify(struct notifier_block *self, |
748 | * We have to make sure that all buffers will be flushed to the SCLP. | 750 | unsigned long event, void *data) |
749 | * Note that this function may be called from within an interrupt context. | ||
750 | */ | ||
751 | static void | ||
752 | sclp_vt220_con_unblank(void) | ||
753 | { | 751 | { |
754 | __sclp_vt220_flush_buffer(); | 752 | __sclp_vt220_flush_buffer(); |
753 | return NOTIFY_OK; | ||
755 | } | 754 | } |
756 | 755 | ||
756 | static struct notifier_block on_panic_nb = { | ||
757 | .notifier_call = sclp_vt220_notify, | ||
758 | .priority = 1, | ||
759 | }; | ||
760 | |||
761 | static struct notifier_block on_reboot_nb = { | ||
762 | .notifier_call = sclp_vt220_notify, | ||
763 | .priority = 1, | ||
764 | }; | ||
765 | |||
757 | /* Structure needed to register with printk */ | 766 | /* Structure needed to register with printk */ |
758 | static struct console sclp_vt220_console = | 767 | static struct console sclp_vt220_console = |
759 | { | 768 | { |
760 | .name = SCLP_VT220_CONSOLE_NAME, | 769 | .name = SCLP_VT220_CONSOLE_NAME, |
761 | .write = sclp_vt220_con_write, | 770 | .write = sclp_vt220_con_write, |
762 | .device = sclp_vt220_con_device, | 771 | .device = sclp_vt220_con_device, |
763 | .unblank = sclp_vt220_con_unblank, | ||
764 | .flags = CON_PRINTBUFFER, | 772 | .flags = CON_PRINTBUFFER, |
765 | .index = SCLP_VT220_CONSOLE_INDEX | 773 | .index = SCLP_VT220_CONSOLE_INDEX |
766 | }; | 774 | }; |
@@ -776,6 +784,8 @@ sclp_vt220_con_init(void) | |||
776 | if (rc) | 784 | if (rc) |
777 | return rc; | 785 | return rc; |
778 | /* Attach linux console */ | 786 | /* Attach linux console */ |
787 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); | ||
788 | register_reboot_notifier(&on_reboot_nb); | ||
779 | register_console(&sclp_vt220_console); | 789 | register_console(&sclp_vt220_console); |
780 | return 0; | 790 | return 0; |
781 | } | 791 | } |