Skip to content

Commit

Permalink
drm/i915: Disable all outputs early, before KMS takeover
Browse files Browse the repository at this point in the history
If the outputs are active and continuing to access the GATT when we
teardown the PTEs, then there is a potential for us to hang the GPU.
The hang tends to be a PGTBL_ER with either an invalid host access or
an invalid display plane fetch.

v2: Reorder IRQ initialisation to defer until after GEM is setup.

Reported-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Tested-by: Daniel Vetter <daniel.vetter@ffwll.ch> (855GM)
Tested-by: Pekka Enberg <penberg@kernel.org>
           # note that this doesn't fix the underlying problem of the
             PGTBL_ER and pipe underruns being reported immediately upon
             init on his 965GM MacBook
Reported-and-tested-by: Rick Bramley <richard.bramley@hp.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=35635
Reported-and-tested-by: Zdenek Kabelac <zdenek.kabelac@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36048
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
  • Loading branch information
Chris Wilson authored and Keith Packard committed May 10, 2011
1 parent 9c23f7f commit 2c7111d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
31 changes: 22 additions & 9 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1176,11 +1176,11 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
return can_switch;
}

static int i915_load_modeset_init(struct drm_device *dev)
static int i915_load_gem_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long prealloc_size, gtt_size, mappable_size;
int ret = 0;
int ret;

prealloc_size = dev_priv->mm.gtt->stolen_size;
gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
Expand All @@ -1204,7 +1204,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
ret = i915_gem_init_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
if (ret)
goto out;
return ret;

/* Try to set up FBC with a reasonable compressed buffer size */
if (I915_HAS_FBC(dev) && i915_powersave) {
Expand All @@ -1222,6 +1222,13 @@ static int i915_load_modeset_init(struct drm_device *dev)

/* Allow hardware batchbuffers unless told otherwise. */
dev_priv->allow_batchbuffer = 1;
return 0;
}

static int i915_load_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;

ret = intel_parse_bios(dev);
if (ret)
Expand All @@ -1236,7 +1243,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
*/
ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
if (ret && ret != -ENODEV)
goto cleanup_ringbuffer;
goto out;

intel_register_dsm_handler();

Expand All @@ -1253,10 +1260,16 @@ static int i915_load_modeset_init(struct drm_device *dev)

intel_modeset_init(dev);

ret = drm_irq_install(dev);
ret = i915_load_gem_init(dev);
if (ret)
goto cleanup_vga_switcheroo;

intel_modeset_gem_init(dev);

ret = drm_irq_install(dev);
if (ret)
goto cleanup_gem;

/* Always safe in the mode setting case. */
/* FIXME: do pre/post-mode set stuff in core KMS code */
dev->vblank_disable_allowed = 1;
Expand All @@ -1274,14 +1287,14 @@ static int i915_load_modeset_init(struct drm_device *dev)

cleanup_irq:
drm_irq_uninstall(dev);
cleanup_gem:
mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
cleanup_vga_switcheroo:
vga_switcheroo_unregister_client(dev->pdev);
cleanup_vga_client:
vga_client_register(dev->pdev, NULL, NULL, NULL);
cleanup_ringbuffer:
mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
out:
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }

/* modesetting */
extern void intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_gem_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
extern void i8xx_disable_fbc(struct drm_device *dev);
Expand Down
17 changes: 11 additions & 6 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -6627,6 +6627,9 @@ static void intel_setup_outputs(struct drm_device *dev)
}

intel_panel_setup_backlight(dev);

/* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev);
}

static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
Expand Down Expand Up @@ -7573,13 +7576,12 @@ void intel_modeset_init(struct drm_device *dev)
intel_crtc_init(dev, i);
}

/* Just disable it once at startup */
i915_disable_vga(dev);
intel_setup_outputs(dev);

intel_enable_clock_gating(dev);

/* Just disable it once at startup */
i915_disable_vga(dev);

if (IS_IRONLAKE_M(dev)) {
ironlake_enable_drps(dev);
intel_init_emon(dev);
Expand All @@ -7588,12 +7590,15 @@ void intel_modeset_init(struct drm_device *dev)
if (IS_GEN6(dev))
gen6_enable_rps(dev_priv);

if (IS_IRONLAKE_M(dev))
ironlake_enable_rc6(dev);

INIT_WORK(&dev_priv->idle_work, intel_idle_update);
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
(unsigned long)dev);
}

void intel_modeset_gem_init(struct drm_device *dev)
{
if (IS_IRONLAKE_M(dev))
ironlake_enable_rc6(dev);

intel_setup_overlay(dev);
}
Expand Down

0 comments on commit 2c7111d

Please sign in to comment.