aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-06-23 15:56:12 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 16:47:40 -0400
commit8fd4bd22350784d5b2fe9274f6790ba353976415 (patch)
treea74d39c50f9a1ca74cfb47b08201c3a3d1e0baea
parent26df6d13406d1a53b0bda08bd712f1924affd7cd (diff)
vt/console: try harder to print output when panicing
Jesse's initial patch commit said: "At panic time (i.e. when oops_in_progress is set) we should try a bit harder to update the screen and make sure output gets to the VT, since some drivers are capable of flipping back to it. So make sure we try to unblank and update the display if called from a panic context." I've enhanced this to add a flag to the vc that console layer can set to indicate they want this behaviour to occur. This also adds support to fbcon for that flag and adds an fb flag for drivers to indicate they want to use the support. It enables this for KMS drivers. Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Acked-by: James Simmons <jsimmons@infradead.org> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/char/vt.c13
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c2
-rw-r--r--drivers/video/console/fbcon.c4
-rw-r--r--include/linux/console_struct.h1
-rw-r--r--include/linux/fb.h4
-rw-r--r--include/linux/vt_kern.h7
8 files changed, 27 insertions, 9 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 34bfb056d7a6..82f64ac21191 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -705,7 +705,10 @@ void redraw_screen(struct vc_data *vc, int is_switch)
705 update_attr(vc); 705 update_attr(vc);
706 clear_buffer_attributes(vc); 706 clear_buffer_attributes(vc);
707 } 707 }
708 if (update && vc->vc_mode != KD_GRAPHICS) 708
709 /* Forcibly update if we're panicing */
710 if ((update && vc->vc_mode != KD_GRAPHICS) ||
711 vt_force_oops_output(vc))
709 do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); 712 do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
710 } 713 }
711 set_cursor(vc); 714 set_cursor(vc);
@@ -743,6 +746,7 @@ static void visual_init(struct vc_data *vc, int num, int init)
743 vc->vc_hi_font_mask = 0; 746 vc->vc_hi_font_mask = 0;
744 vc->vc_complement_mask = 0; 747 vc->vc_complement_mask = 0;
745 vc->vc_can_do_color = 0; 748 vc->vc_can_do_color = 0;
749 vc->vc_panic_force_write = false;
746 vc->vc_sw->con_init(vc, init); 750 vc->vc_sw->con_init(vc, init);
747 if (!vc->vc_complement_mask) 751 if (!vc->vc_complement_mask)
748 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 752 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
@@ -2506,7 +2510,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2506 goto quit; 2510 goto quit;
2507 } 2511 }
2508 2512
2509 if (vc->vc_mode != KD_TEXT) 2513 if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
2510 goto quit; 2514 goto quit;
2511 2515
2512 /* undraw cursor first */ 2516 /* undraw cursor first */
@@ -3784,7 +3788,8 @@ void do_unblank_screen(int leaving_gfx)
3784 return; 3788 return;
3785 } 3789 }
3786 vc = vc_cons[fg_console].d; 3790 vc = vc_cons[fg_console].d;
3787 if (vc->vc_mode != KD_TEXT) 3791 /* Try to unblank in oops case too */
3792 if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
3788 return; /* but leave console_blanked != 0 */ 3793 return; /* but leave console_blanked != 0 */
3789 3794
3790 if (blankinterval) { 3795 if (blankinterval) {
@@ -3793,7 +3798,7 @@ void do_unblank_screen(int leaving_gfx)
3793 } 3798 }
3794 3799
3795 console_blanked = 0; 3800 console_blanked = 0;
3796 if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) 3801 if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
3797 /* Low-level driver cannot restore -> do it ourselves */ 3802 /* Low-level driver cannot restore -> do it ourselves */
3798 update_screen(vc); 3803 update_screen(vc);
3799 if (console_blank_hook) 3804 if (console_blank_hook)
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 54acd8b534df..a79525f434a8 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -130,7 +130,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
130 130
131 strcpy(info->fix.id, "inteldrmfb"); 131 strcpy(info->fix.id, "inteldrmfb");
132 132
133 info->flags = FBINFO_DEFAULT; 133 info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
134 info->fbops = &intelfb_ops; 134 info->fbops = &intelfb_ops;
135 135
136 /* setup aperture base/size for vesafb takeover */ 136 /* setup aperture base/size for vesafb takeover */
@@ -148,8 +148,6 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
148 info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; 148 info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
149 info->fix.smem_len = size; 149 info->fix.smem_len = size;
150 150
151 info->flags = FBINFO_DEFAULT;
152
153 info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, 151 info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset,
154 size); 152 size);
155 if (!info->screen_base) { 153 if (!info->screen_base) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 2fb2444d2322..099f637264aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -250,6 +250,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
250 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | 250 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
251 FBINFO_HWACCEL_FILLRECT | 251 FBINFO_HWACCEL_FILLRECT |
252 FBINFO_HWACCEL_IMAGEBLIT; 252 FBINFO_HWACCEL_IMAGEBLIT;
253 info->flags |= FBINFO_CAN_FORCE_OUTPUT;
253 info->fbops = &nouveau_fbcon_ops; 254 info->fbops = &nouveau_fbcon_ops;
254 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - 255 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
255 dev_priv->vm_vram_base; 256 dev_priv->vm_vram_base;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index dc1634bb0c11..dbf86962bdd1 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -224,7 +224,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
224 224
225 drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); 225 drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
226 226
227 info->flags = FBINFO_DEFAULT; 227 info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
228 info->fbops = &radeonfb_ops; 228 info->fbops = &radeonfb_ops;
229 229
230 tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; 230 tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3b3f5749af92..26bf7cbfecc2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -283,7 +283,8 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
283 struct fbcon_ops *ops = info->fbcon_par; 283 struct fbcon_ops *ops = info->fbcon_par;
284 284
285 return (info->state != FBINFO_STATE_RUNNING || 285 return (info->state != FBINFO_STATE_RUNNING ||
286 vc->vc_mode != KD_TEXT || ops->graphics); 286 vc->vc_mode != KD_TEXT || ops->graphics) &&
287 !vt_force_oops_output(vc);
287} 288}
288 289
289static inline int get_color(struct vc_data *vc, struct fb_info *info, 290static inline int get_color(struct vc_data *vc, struct fb_info *info,
@@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init)
1073 if (p->userfont) 1074 if (p->userfont)
1074 charcnt = FNTCHARCNT(p->fontdata); 1075 charcnt = FNTCHARCNT(p->fontdata);
1075 1076
1077 vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT);
1076 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); 1078 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
1077 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 1079 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
1078 if (charcnt == 256) { 1080 if (charcnt == 256) {
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index 38fe59dc89ae..d7d9acdccffb 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -105,6 +105,7 @@ struct vc_data {
105 struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ 105 struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
106 unsigned long vc_uni_pagedir; 106 unsigned long vc_uni_pagedir;
107 unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ 107 unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
108 bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
108 /* additional information is in vt_kern.h */ 109 /* additional information is in vt_kern.h */
109}; 110};
110 111
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 0c5659c41b01..f0268deca658 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -825,6 +825,10 @@ struct fb_tile_ops {
825 */ 825 */
826#define FBINFO_BE_MATH 0x100000 826#define FBINFO_BE_MATH 0x100000
827 827
828/* report to the VT layer that this fb driver can accept forced console
829 output like oopses */
830#define FBINFO_CAN_FORCE_OUTPUT 0x200000
831
828struct fb_info { 832struct fb_info {
829 int node; 833 int node;
830 int flags; 834 int flags;
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 7f56db4a79f0..56cce345aa8d 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -100,6 +100,13 @@ extern int unbind_con_driver(const struct consw *csw, int first, int last,
100 int deflt); 100 int deflt);
101int vty_init(const struct file_operations *console_fops); 101int vty_init(const struct file_operations *console_fops);
102 102
103static inline bool vt_force_oops_output(struct vc_data *vc)
104{
105 if (oops_in_progress && vc->vc_panic_force_write)
106 return true;
107 return false;
108}
109
103/* 110/*
104 * vc_screen.c shares this temporary buffer with the console write code so that 111 * vc_screen.c shares this temporary buffer with the console write code so that
105 * we can easily avoid touching user space while holding the console spinlock. 112 * we can easily avoid touching user space while holding the console spinlock.