OSDN Git Service

i915: switch back to fbcon on panic
authorJesse Barnes <jbarnes@jbarnes-t61.(none)>
Wed, 18 Jun 2008 20:57:39 +0000 (13:57 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 18 Jun 2008 20:57:39 +0000 (13:57 -0700)
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

index 856ec86..64a8fc9 100644 (file)
@@ -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);