drm: add KGDB/KDB support
authorJesse Barnes <jbarnes@virtuousgeek.org>
Thu, 5 Aug 2010 14:22:31 +0000 (09:22 -0500)
committerJason Wessel <jason.wessel@windriver.com>
Thu, 5 Aug 2010 14:22:31 +0000 (09:22 -0500)
Implement the callbacks for KDB entry/exit via the drm helpers.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
drivers/gpu/drm/drm_fb_helper.c
include/drm/drm_crtc_helper.h
include/drm/drm_fb_helper.h

index 7196620..6245add 100644 (file)
@@ -241,6 +241,80 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
        return 0;
 }
 
+int drm_fb_helper_debug_enter(struct fb_info *info)
+{
+       struct drm_fb_helper *helper = info->par;
+       struct drm_crtc_helper_funcs *funcs;
+       int i;
+
+       if (list_empty(&kernel_fb_helper_list))
+               return false;
+
+       list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
+               for (i = 0; i < helper->crtc_count; i++) {
+                       struct drm_mode_set *mode_set =
+                               &helper->crtc_info[i].mode_set;
+
+                       if (!mode_set->crtc->enabled)
+                               continue;
+
+                       funcs = mode_set->crtc->helper_private;
+                       funcs->mode_set_base_atomic(mode_set->crtc,
+                                                   mode_set->fb,
+                                                   mode_set->x,
+                                                   mode_set->y);
+
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_debug_enter);
+
+/* Find the real fb for a given fb helper CRTC */
+static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc *c;
+
+       list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
+               if (crtc->base.id == c->base.id)
+                       return c->fb;
+       }
+
+       return NULL;
+}
+
+int drm_fb_helper_debug_leave(struct fb_info *info)
+{
+       struct drm_fb_helper *helper = info->par;
+       struct drm_crtc *crtc;
+       struct drm_crtc_helper_funcs *funcs;
+       struct drm_framebuffer *fb;
+       int i;
+
+       for (i = 0; i < helper->crtc_count; i++) {
+               struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
+               crtc = mode_set->crtc;
+               funcs = crtc->helper_private;
+               fb = drm_mode_config_fb(crtc);
+
+               if (!crtc->enabled)
+                       continue;
+
+               if (!fb) {
+                       DRM_ERROR("no fb to restore??\n");
+                       continue;
+               }
+
+               funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
+                                           crtc->y);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_debug_leave);
+
 bool drm_fb_helper_force_kernel_mode(void)
 {
        int i = 0;
index 1121f77..10f7d03 100644 (file)
@@ -60,6 +60,8 @@ struct drm_crtc_helper_funcs {
        /* Move the crtc on the current fb to the given position *optional* */
        int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
                             struct drm_framebuffer *old_fb);
+       int (*mode_set_base_atomic)(struct drm_crtc *crtc,
+                                   struct drm_framebuffer *fb, int x, int y);
 
        /* reload the current crtc LUT */
        void (*load_lut)(struct drm_crtc *crtc);
index f0a6afc..f22e7fe 100644 (file)
@@ -32,6 +32,8 @@
 
 struct drm_fb_helper;
 
+#include <linux/kgdb.h>
+
 struct drm_fb_helper_crtc {
        uint32_t crtc_id;
        struct drm_mode_set mode_set;
@@ -78,6 +80,7 @@ struct drm_fb_helper_connector {
 
 struct drm_fb_helper {
        struct drm_framebuffer *fb;
+       struct drm_framebuffer *saved_fb;
        struct drm_device *dev;
        struct drm_display_mode *mode;
        int crtc_count;
@@ -126,5 +129,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
 bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
+int drm_fb_helper_debug_enter(struct fb_info *info);
+int drm_fb_helper_debug_leave(struct fb_info *info);
 
 #endif