aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.