diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 9934e3a..a43319d 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -566,6 +566,31 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) } EXPORT_SYMBOL(intelfb_resize); +static struct fb_info *panic_fb; + +extern int set_console(int nr); +extern int vt_waitactive(int vt); + +int intelfb_panic(struct notifier_block *n, unsigned long ununsed, + void *panic_str) +{ + /* Force a switch back to our FB console */ + panic_fb->var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; + fb_set_var(panic_fb, &panic_fb->var); + + set_console(0); + vt_waitactive(0); + + printk(KERN_ERR "panic! switched back to text console\n"); + + return 0; +} +EXPORT_SYMBOL(intelfb_panic); + +static struct notifier_block paniced = { + .notifier_call = intelfb_panic, +}; + int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output) { struct fb_info *info; @@ -763,6 +788,11 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_outp printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + + /* Switch back to kernel console on panic */ + panic_fb = info; + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + return 0; } EXPORT_SYMBOL(intelfb_probe); @@ -783,6 +813,9 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) drm_framebuffer_destroy(fb); framebuffer_release(info); } + + panic_fb = NULL; + atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); return 0; } EXPORT_SYMBOL(intelfb_remove);