diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-01 16:38:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-01 16:38:59 -0700 |
commit | c66a86d0cdce3bad2da794f114cc37377d242c3d (patch) | |
tree | 4603bb4a464439275c07ebf66ec4a69ebc8fafc3 /drivers/gpu | |
parent | c9e0b8454582b413bc64c16693c7979417cad3eb (diff) | |
parent | 2b1ecb7337592a7bf0989efac46a5b52daab769e (diff) |
Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/keithp/linux-2.6
* 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/keithp/linux-2.6:
drm/i915: apply HWSTAM writes to Ivy Bridge as well
drm/i915: move IRQ function table init to i915_irq.c
drm/i915/overlay: Fix unpinning along init error paths
drm/i915: Don't call describe_obj on NULL pointers
drm/i915: Hold struct_mutex during i915_save_state/i915_restore_state
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 80 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 17 |
7 files changed, 94 insertions, 109 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4d46441cbe2d..0a893f7400fa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1207,13 +1207,17 @@ static int i915_context_status(struct seq_file *m, void *unused) if (ret) return ret; - seq_printf(m, "power context "); - describe_obj(m, dev_priv->pwrctx); - seq_printf(m, "\n"); + if (dev_priv->pwrctx) { + seq_printf(m, "power context "); + describe_obj(m, dev_priv->pwrctx); + seq_printf(m, "\n"); + } - seq_printf(m, "render context "); - describe_obj(m, dev_priv->renderctx); - seq_printf(m, "\n"); + if (dev_priv->renderctx) { + seq_printf(m, "render context "); + describe_obj(m, dev_priv->renderctx); + seq_printf(m, "\n"); + } mutex_unlock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2b79588541e7..e1787022d6c8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1266,30 +1266,6 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_modeset_gem_init(dev); - if (IS_IVYBRIDGE(dev)) { - /* Share pre & uninstall handlers with ILK/SNB */ - dev->driver->irq_handler = ivybridge_irq_handler; - dev->driver->irq_preinstall = ironlake_irq_preinstall; - dev->driver->irq_postinstall = ivybridge_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; - dev->driver->enable_vblank = ivybridge_enable_vblank; - dev->driver->disable_vblank = ivybridge_disable_vblank; - } else if (HAS_PCH_SPLIT(dev)) { - dev->driver->irq_handler = ironlake_irq_handler; - dev->driver->irq_preinstall = ironlake_irq_preinstall; - dev->driver->irq_postinstall = ironlake_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; - dev->driver->enable_vblank = ironlake_enable_vblank; - dev->driver->disable_vblank = ironlake_disable_vblank; - } else { - dev->driver->irq_preinstall = i915_driver_irq_preinstall; - dev->driver->irq_postinstall = i915_driver_irq_postinstall; - dev->driver->irq_uninstall = i915_driver_irq_uninstall; - dev->driver->irq_handler = i915_driver_irq_handler; - dev->driver->enable_vblank = i915_enable_vblank; - dev->driver->disable_vblank = i915_disable_vblank; - } - ret = drm_irq_install(dev); if (ret) goto cleanup_gem; @@ -2017,12 +1993,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) /* enable GEM by default */ dev_priv->has_gem = 1; - dev->driver->get_vblank_counter = i915_get_vblank_counter; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { - dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ - dev->driver->get_vblank_counter = gm45_get_vblank_counter; - } + intel_irq_init(dev); /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 609358faaa90..013d304455b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -765,14 +765,6 @@ static struct drm_driver driver = { .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, - .enable_vblank = i915_enable_vblank, - .disable_vblank = i915_disable_vblank, - .get_vblank_timestamp = i915_get_vblank_timestamp, - .get_scanout_position = i915_get_crtc_scanoutpos, - .irq_preinstall = i915_driver_irq_preinstall, - .irq_postinstall = i915_driver_irq_postinstall, - .irq_uninstall = i915_driver_irq_uninstall, - .irq_handler = i915_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .master_create = i915_master_create, .master_destroy = i915_master_destroy, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eddabf68e97a..f245c588ae95 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -997,8 +997,6 @@ extern unsigned int i915_enable_fbc; extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_resume(struct drm_device *dev); -extern void i915_save_display(struct drm_device *dev); -extern void i915_restore_display(struct drm_device *dev); extern int i915_master_create(struct drm_device *dev, struct drm_master *master); extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); @@ -1033,33 +1031,12 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); -extern void i915_driver_irq_preinstall(struct drm_device * dev); -extern int i915_driver_irq_postinstall(struct drm_device *dev); -extern void i915_driver_irq_uninstall(struct drm_device * dev); - -extern irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS); -extern void ironlake_irq_preinstall(struct drm_device *dev); -extern int ironlake_irq_postinstall(struct drm_device *dev); -extern void ironlake_irq_uninstall(struct drm_device *dev); - -extern irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS); -extern void ivybridge_irq_preinstall(struct drm_device *dev); -extern int ivybridge_irq_postinstall(struct drm_device *dev); -extern void ivybridge_irq_uninstall(struct drm_device *dev); +extern void intel_irq_init(struct drm_device *dev); extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int i915_enable_vblank(struct drm_device *dev, int crtc); -extern void i915_disable_vblank(struct drm_device *dev, int crtc); -extern int ironlake_enable_vblank(struct drm_device *dev, int crtc); -extern void ironlake_disable_vblank(struct drm_device *dev, int crtc); -extern int ivybridge_enable_vblank(struct drm_device *dev, int crtc); -extern void ivybridge_disable_vblank(struct drm_device *dev, int crtc); -extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); -extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -1070,13 +1047,6 @@ void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void intel_enable_asle (struct drm_device *dev); -int i915_get_vblank_timestamp(struct drm_device *dev, int crtc, - int *max_error, - struct timeval *vblank_time, - unsigned flags); - -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, - int *vpos, int *hpos); #ifdef CONFIG_DEBUG_FS extern void i915_destroy_error_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ae2b49969b99..3b03f85ea627 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -152,7 +152,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ -u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long high_frame; @@ -184,7 +184,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) return (high1 << 8) | low; } -u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int reg = PIPE_FRMCOUNT_GM45(pipe); @@ -198,7 +198,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) return I915_READ(reg); } -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, +static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, int *vpos, int *hpos) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -264,7 +264,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, return ret; } -int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, +static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error, struct timeval *vblank_time, unsigned flags) @@ -462,7 +462,7 @@ static void pch_irq_handler(struct drm_device *dev) DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); } -irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -550,7 +550,7 @@ done: return ret; } -irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1209,7 +1209,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) } } -irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1454,7 +1454,7 @@ int i915_irq_wait(struct drm_device *dev, void *data, /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -int i915_enable_vblank(struct drm_device *dev, int pipe) +static int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1478,7 +1478,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) return 0; } -int ironlake_enable_vblank(struct drm_device *dev, int pipe) +static int ironlake_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1494,7 +1494,7 @@ int ironlake_enable_vblank(struct drm_device *dev, int pipe) return 0; } -int ivybridge_enable_vblank(struct drm_device *dev, int pipe) +static int ivybridge_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1513,7 +1513,7 @@ int ivybridge_enable_vblank(struct drm_device *dev, int pipe) /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -void i915_disable_vblank(struct drm_device *dev, int pipe) +static void i915_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1529,7 +1529,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -void ironlake_disable_vblank(struct drm_device *dev, int pipe) +static void ironlake_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1540,7 +1540,7 @@ void ironlake_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -void ivybridge_disable_vblank(struct drm_device *dev, int pipe) +static void ivybridge_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1728,7 +1728,7 @@ repeat: /* drm_dma.h hooks */ -void ironlake_irq_preinstall(struct drm_device *dev) +static void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1740,7 +1740,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { /* Workaround stalls observed on Sandy Bridge GPUs by * making the blitter command streamer generate a * write to the Hardware Status Page for @@ -1769,7 +1769,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) POSTING_READ(SDEIER); } -int ironlake_irq_postinstall(struct drm_device *dev) +static int ironlake_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ @@ -1841,7 +1841,7 @@ int ironlake_irq_postinstall(struct drm_device *dev) return 0; } -int ivybridge_irq_postinstall(struct drm_device *dev) +static int ivybridge_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ @@ -1891,7 +1891,7 @@ int ivybridge_irq_postinstall(struct drm_device *dev) return 0; } -void i915_driver_irq_preinstall(struct drm_device * dev) +static void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -1918,7 +1918,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev) * Must be called after intel_modeset_init or hotplug interrupts won't be * enabled correctly. */ -int i915_driver_irq_postinstall(struct drm_device *dev) +static int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; @@ -1994,7 +1994,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) return 0; } -void ironlake_irq_uninstall(struct drm_device *dev) +static void ironlake_irq_uninstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2014,7 +2014,7 @@ void ironlake_irq_uninstall(struct drm_device *dev) I915_WRITE(GTIIR, I915_READ(GTIIR)); } -void i915_driver_irq_uninstall(struct drm_device * dev) +static void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -2040,3 +2040,41 @@ void i915_driver_irq_uninstall(struct drm_device * dev) I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); } + +void intel_irq_init(struct drm_device *dev) +{ + dev->driver->get_vblank_counter = i915_get_vblank_counter; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { + dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ + dev->driver->get_vblank_counter = gm45_get_vblank_counter; + } + + + dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; + dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; + + if (IS_IVYBRIDGE(dev)) { + /* Share pre & uninstall handlers with ILK/SNB */ + dev->driver->irq_handler = ivybridge_irq_handler; + dev->driver->irq_preinstall = ironlake_irq_preinstall; + dev->driver->irq_postinstall = ivybridge_irq_postinstall; + dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->enable_vblank = ivybridge_enable_vblank; + dev->driver->disable_vblank = ivybridge_disable_vblank; + } else if (HAS_PCH_SPLIT(dev)) { + dev->driver->irq_handler = ironlake_irq_handler; + dev->driver->irq_preinstall = ironlake_irq_preinstall; + dev->driver->irq_postinstall = ironlake_irq_postinstall; + dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->enable_vblank = ironlake_enable_vblank; + dev->driver->disable_vblank = ironlake_disable_vblank; + } else { + dev->driver->irq_preinstall = i915_driver_irq_preinstall; + dev->driver->irq_postinstall = i915_driver_irq_postinstall; + dev->driver->irq_uninstall = i915_driver_irq_uninstall; + dev->driver->irq_handler = i915_driver_irq_handler; + dev->driver->enable_vblank = i915_enable_vblank; + dev->driver->disable_vblank = i915_disable_vblank; + } +} diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index e8152d23d5b6..5257cfc34c35 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -597,7 +597,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) return; } -void i915_save_display(struct drm_device *dev) +static void i915_save_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -678,7 +678,6 @@ void i915_save_display(struct drm_device *dev) } /* VGA state */ - mutex_lock(&dev->struct_mutex); dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); @@ -688,10 +687,9 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); i915_save_vga(dev); - mutex_unlock(&dev->struct_mutex); } -void i915_restore_display(struct drm_device *dev) +static void i915_restore_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -783,7 +781,6 @@ void i915_restore_display(struct drm_device *dev) else I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); - mutex_lock(&dev->struct_mutex); I915_WRITE(VGA0, dev_priv->saveVGA0); I915_WRITE(VGA1, dev_priv->saveVGA1); I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); @@ -791,7 +788,6 @@ void i915_restore_display(struct drm_device *dev) udelay(150); i915_restore_vga(dev); - mutex_unlock(&dev->struct_mutex); } int i915_save_state(struct drm_device *dev) @@ -801,6 +797,8 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + mutex_lock(&dev->struct_mutex); + /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -840,6 +838,8 @@ int i915_save_state(struct drm_device *dev) for (i = 0; i < 3; i++) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -850,6 +850,8 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); + mutex_lock(&dev->struct_mutex); + /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); @@ -867,6 +869,7 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(IER, dev_priv->saveIER); I915_WRITE(IMR, dev_priv->saveIMR); } + mutex_unlock(&dev->struct_mutex); intel_init_clock_gating(dev); @@ -878,6 +881,8 @@ int i915_restore_state(struct drm_device *dev) if (IS_GEN6(dev)) gen6_enable_rps(dev_priv); + mutex_lock(&dev->struct_mutex); + /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); @@ -891,6 +896,8 @@ int i915_restore_state(struct drm_device *dev) for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); + mutex_unlock(&dev->struct_mutex); + intel_i2c_reset(dev); return 0; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 56a8e2aea19c..9e2959bc91cd 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev) overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); if (!overlay) return; + + mutex_lock(&dev->struct_mutex); + if (WARN_ON(dev_priv->overlay)) + goto out_free; + overlay->dev = dev; reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); @@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev) goto out_free; overlay->reg_bo = reg_bo; - mutex_lock(&dev->struct_mutex); - if (OVERLAY_NEEDS_PHYSICAL(dev)) { ret = i915_gem_attach_phys_object(dev, reg_bo, I915_GEM_PHYS_OVERLAY_REGS, @@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev) } } - mutex_unlock(&dev->struct_mutex); - /* init all values */ overlay->color_key = 0x0101fe; overlay->brightness = -19; @@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev) regs = intel_overlay_map_regs(overlay); if (!regs) - goto out_free_bo; + goto out_unpin_bo; memset(regs, 0, sizeof(struct overlay_registers)); update_polyphase_filter(regs); @@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev) intel_overlay_unmap_regs(overlay, regs); dev_priv->overlay = overlay; + mutex_unlock(&dev->struct_mutex); DRM_INFO("initialized overlay support\n"); return; out_unpin_bo: - i915_gem_object_unpin(reg_bo); + if (!OVERLAY_NEEDS_PHYSICAL(dev)) + i915_gem_object_unpin(reg_bo); out_free_bo: drm_gem_object_unreference(®_bo->base); - mutex_unlock(&dev->struct_mutex); out_free: + mutex_unlock(&dev->struct_mutex); kfree(overlay); return; } |