From patchwork Tue Aug 25 20:52:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 43807 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n7PKxlWs019041 for ; Tue, 25 Aug 2009 20:59:47 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E6A169E79E; Tue, 25 Aug 2009 13:59:46 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org X-Greylist: delayed 399 seconds by postgrey-1.30 at gabe; Tue, 25 Aug 2009 13:59:44 PDT Received: from outbound-mail-40.bluehost.com (outbound-mail-40.bluehost.com [69.89.20.194]) by gabe.freedesktop.org (Postfix) with SMTP id D397A9E768 for ; Tue, 25 Aug 2009 13:59:44 -0700 (PDT) Received: (qmail 17919 invoked by uid 0); 25 Aug 2009 20:53:04 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by outboundproxy2.bluehost.com with SMTP; 25 Aug 2009 20:53:04 -0000 Received: from [75.111.28.251] (helo=jbarnes-g45) by box514.bluehost.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1Mg30q-00017X-HU; Tue, 25 Aug 2009 14:53:04 -0600 Date: Tue, 25 Aug 2009 13:52:55 -0700 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org, eric@anholt.net Message-ID: <20090825135255.10c7b681@jbarnes-g45> X-Mailer: Claws Mail 3.7.2 (GTK+ 2.17.5; i486-pc-linux-gnu) Mime-Version: 1.0 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 75.111.28.251 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915: fix kernelfb mode X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org The kernelfb_mode struct isn't correct for multi-CRTC configurations or configurations where CRTC 2 isn't enabled. Fix that up for both the shared fb and per-CRTC fb cases so that panic & sysrq work as expected. Tested-by: Jason Wessel Signed-off-by: Jesse Barnes Tested-by: Shuang He diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 1d30802..042fc29 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -52,6 +52,17 @@ struct intelfb_par { uint32_t crtc_ids[2]; }; +/* + * Track each CRTCs intelfb mode config for restoration at panic or + * sysrq time. + */ +struct intelfb_console_restore { + struct drm_mode_set mode_sets[I915_NUM_PIPE]; + int num_crtcs; +}; + +static struct intelfb_console_restore console_restore; + static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) @@ -412,21 +423,6 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) } EXPORT_SYMBOL(intelfb_resize); -static struct drm_mode_set kernelfb_mode; - -static int intelfb_panic(struct notifier_block *n, unsigned long ununsed, - void *panic_str) -{ - DRM_ERROR("panic occurred, switching back to text console\n"); - - intelfb_restore(); - return 0; -} - -static struct notifier_block paniced = { - .notifier_call = intelfb_panic, -}; - static int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height, uint32_t surface_width, uint32_t surface_height, @@ -625,7 +621,9 @@ out: return ret; } -static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc) +static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_mode_set *set) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; @@ -701,10 +699,7 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc * DRM_INFO("fb%d: %s frame buffer device\n", info->node, info->fix.id); - /* Switch back to kernel console on panic */ - kernelfb_mode = *modeset; - atomic_notifier_chain_register(&panic_notifier_list, &paniced); - DRM_DEBUG("registered panic notifier\n"); + *set = *modeset; return 0; } @@ -713,12 +708,15 @@ static int intelfb_multi_fb_probe(struct drm_device *dev) { struct drm_crtc *crtc; - int ret = 0; + int ret = 0, crtc_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - ret = intelfb_multi_fb_probe_crtc(dev, crtc); + struct drm_mode_set *set = + &console_restore.mode_sets[crtc_count++]; + ret = intelfb_multi_fb_probe_crtc(dev, crtc, set); if (ret) return ret; + console_restore.num_crtcs++; } return ret; } @@ -812,7 +810,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev) * set configuration. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *intel_crtc; + + if (!drm_helper_crtc_in_use(crtc) || !crtc->desired_mode) + continue; + + intel_crtc = to_intel_crtc(crtc); modeset = &intel_crtc->mode_set; modeset->fb = &intel_fb->base; @@ -833,7 +836,7 @@ static int intelfb_single_fb_probe(struct drm_device *dev) for (i = conn_count; i < INTELFB_CONN_LIMIT; i++) modeset->connectors[i] = NULL; - par->crtc_ids[crtc_count++] = crtc->base.id; + par->crtc_ids[crtc_count] = crtc->base.id; modeset->num_connectors = conn_count; if (modeset->crtc->desired_mode) { @@ -842,6 +845,10 @@ static int intelfb_single_fb_probe(struct drm_device *dev) modeset->mode = drm_mode_duplicate(dev, modeset->crtc->desired_mode); } + + console_restore.mode_sets[crtc_count] = *modeset; + console_restore.num_crtcs++; + crtc_count++; } par->crtc_count = crtc_count; @@ -855,11 +862,6 @@ static int intelfb_single_fb_probe(struct drm_device *dev) DRM_INFO("fb%d: %s frame buffer device\n", info->node, info->fix.id); - /* Switch back to kernel console on panic */ - kernelfb_mode = *modeset; - atomic_notifier_chain_register(&panic_notifier_list, &paniced); - DRM_DEBUG("registered panic notifier\n"); - return 0; } @@ -870,13 +872,30 @@ static int intelfb_single_fb_probe(struct drm_device *dev) */ void intelfb_restore(void) { - int ret; - if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { - DRM_ERROR("Failed to restore crtc configuration: %d\n", - ret); + int ret, i; + + for (i = 0; i < console_restore.num_crtcs; i++) { + struct drm_mode_set *set = &console_restore.mode_sets[i]; + if ((ret = drm_crtc_helper_set_config(set)) != 0) { + DRM_ERROR("Failed to restore crtc configuration: %d\n", + ret); + } } } +static int intelfb_panic(struct notifier_block *n, unsigned long ununsed, + void *panic_str) +{ + DRM_ERROR("panic occurred, switching back to text console\n"); + + intelfb_restore(); + return 0; +} + +static struct notifier_block paniced = { + .notifier_call = intelfb_panic, +}; + static void intelfb_restore_work_fn(struct work_struct *ignored) { intelfb_restore(); @@ -924,6 +943,7 @@ int intelfb_probe(struct drm_device *dev) ret = intelfb_single_fb_probe(dev); } + atomic_notifier_chain_register(&panic_notifier_list, &paniced); register_sysrq_key('v', &sysrq_intelfb_restore_op); return ret; @@ -946,7 +966,7 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) } atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); - memset(&kernelfb_mode, 0, sizeof(struct drm_mode_set)); + memset(&console_restore, 0, sizeof(struct intelfb_console_restore)); return 0; } EXPORT_SYMBOL(intelfb_remove);