Message ID | 20090825135255.10c7b681@jbarnes-g45 (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
On Tue, 25 Aug 2009 13:52:55 -0700 Jesse Barnes <jbarnes@virtuousgeek.org> wrote: > 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. Err configurations where CRTC 1 (we have 0 and 1, no 2) isn't enabled.
On Tue, 25 Aug 2009 14:01:27 -0700 Jesse Barnes <jbarnes@virtuousgeek.org> wrote: > On Tue, 25 Aug 2009 13:52:55 -0700 > Jesse Barnes <jbarnes@virtuousgeek.org> wrote: > > > 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. > > Err configurations where CRTC 1 (we have 0 and 1, no 2) isn't enabled. And: Tested-by: Shuang He <shuang.he@intel.com>
On Wed, Aug 26, 2009 at 6:52 AM, Jesse Barnes<jbarnes@virtuousgeek.org> wrote: > 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. My merged drm_fb code sent to dri-devel does this and I think it does it better, it would be great if you could test it. it might need some more bits. Dave. > > Tested-by: Jason Wessel <jason.wessel@windriver.com> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> > > 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); > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx >
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);