From 7010d500072977f63a0bac08f2141d69dbd19595 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 18 Jun 2008 13:57:39 -0700 Subject: [PATCH] i915: switch back to fbcon on panic Normally when X is running, panic messages will be invisible and the machine will just appear to hard hang. This patch adds support for switching back to the fbcon framebuffer on panic (through the use of a panic notifier registration) so we can see what happened. Note that in order to be really useful, X will have to run its VT in something other than KD_GRAPHICS mode. Also, not all kernel errors result in panics, some go through BUG() which may trigger another type of event, not resulting in a switch. --- linux-core/intel_fb.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 856ec868..64a8fc94 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -581,6 +581,22 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) } EXPORT_SYMBOL(intelfb_resize); +static struct drm_mode_set panic_mode; + +int intelfb_panic(struct notifier_block *n, unsigned long ununsed, + void *panic_str) +{ + DRM_ERROR("panic occurred, switching back to text console\n"); + drm_crtc_helper_set_config(&panic_mode); + + return 0; +} +EXPORT_SYMBOL(intelfb_panic); + +static struct notifier_block paniced = { + .notifier_call = intelfb_panic, +}; + int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height, uint32_t surface_width, uint32_t surface_height, struct intel_framebuffer **intel_fb_p) @@ -831,6 +847,12 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc * printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + + /* Switch back to kernel console on panic */ + panic_mode = *modeset; + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + printk(KERN_INFO "registered panic notifier\n"); + return 0; } @@ -952,6 +974,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev) printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + + /* Switch back to kernel console on panic */ + panic_mode = *modeset; + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + printk(KERN_INFO "registered panic notifier\n"); + return 0; } @@ -1005,6 +1033,9 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) drm_bo_usage_deref_unlocked(&intel_fb->bo); framebuffer_release(info); } + + atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); + memset(&panic_mode, 0, sizeof(struct drm_mode_set)); return 0; } EXPORT_SYMBOL(intelfb_remove);