aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-03-30 16:41:23 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-30 16:41:23 -0800
commit79568b259e375ca02af4263b18abfb5d91e626c7 (patch)
tree0196c19c950d574a9d0c9af37c2213b68e482973
parent5c373c0215bd782a874318673a8e5193ad21a107 (diff)
downloadhistory-79568b259e375ca02af4263b18abfb5d91e626c7.tar.gz
[PATCH] vt: don't call unblank at irq time
This patch removes the call to unblank() from printk, and avoids calling unblank at irq() time _unless_ oops_in_progress is 1. I also export oops_in_progress() so drivers who care like radeonfb can test it and know what to do. I audited call sites of unblank_screen(), console_unblank(), etc... and I _hope_ I got them all, the patch includes a small patch to the s390 bust_spinlocks code that sets oops_in_progress back to 0 _after_ unblanking for example. I added a few might_sleep() to help us catch possible remaining callers. I'll soon write a document explaining fbdev locking. The current situation after this patch is that: - All callbacks have console_semaphore held (fbdev's are fully serialised). - Everything is called in schedule'able context, except the cfb_* rendering operations and cursor operations, with the special case of unblank who can be called at any time when "oops_in_progress" is true. A driver that needs to sleep in it's unblank implementation is welcome to test that variable and use a fallback path (or just do nothing if it's not simple). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/s390/mm/fault.c2
-rw-r--r--drivers/char/vt.c18
-rw-r--r--kernel/printk.c18
3 files changed, 29 insertions, 9 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index b1de24775c31ef..80306bc8c799b7 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -62,8 +62,8 @@ void bust_spinlocks(int yes)
oops_in_progress = 1;
} else {
int loglevel_save = console_loglevel;
- oops_in_progress = 0;
console_unblank();
+ oops_in_progress = 0;
/*
* OK, the message is on the console. Now we call printk()
* without oops_in_progress set so that printk will give klogd
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6229dd04ac314d..e5ef1dfc54826a 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2212,9 +2212,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
}
set_cursor(vc);
- if (!oops_in_progress)
- poke_blanked_console();
-
quit:
clear_bit(0, &printing);
}
@@ -2815,6 +2812,13 @@ void do_unblank_screen(int leaving_gfx)
{
struct vc_data *vc;
+ /* This should now always be called from a "sane" (read: can schedule)
+ * context for the sake of the low level drivers, except in the special
+ * case of oops_in_progress
+ */
+ if (!oops_in_progress)
+ might_sleep();
+
WARN_CONSOLE_UNLOCKED();
ignore_poke = 0;
@@ -2871,6 +2875,14 @@ void poke_blanked_console(void)
{
WARN_CONSOLE_UNLOCKED();
+ /* Add this so we quickly catch whoever might call us in a non
+ * safe context. Nowadays, unblank_screen() isn't to be called in
+ * atomic contexts and is allowed to schedule (with the special case
+ * of oops_in_progress, but that isn't of any concern for this
+ * function. --BenH.
+ */
+ might_sleep();
+
/* This isn't perfectly race free, but a race here would be mostly harmless,
* at worse, we'll do a spurrious blank and it's unlikely
*/
diff --git a/kernel/printk.c b/kernel/printk.c
index 5d5754964bf40a..1498689548d1e6 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,12 @@ int console_printk[4] = {
EXPORT_SYMBOL(console_printk);
+/*
+ * Low lever drivers may need that to know if they can schedule in
+ * their unblank() callback or not. So let's export it.
+ */
int oops_in_progress;
+EXPORT_SYMBOL(oops_in_progress);
/*
* console_sem protects the console_drivers list, and also
@@ -751,12 +756,15 @@ void console_unblank(void)
struct console *c;
/*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
*/
- if (down_trylock(&console_sem) != 0)
- return;
+ if (oops_in_progress) {
+ if (down_trylock(&console_sem) != 0)
+ return;
+ } else
+ acquire_console_sem();
+
console_locked = 1;
console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)