From d70bed1947772f34d66ada3bd923bfc12ea2452b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2011 00:30:34 -0700 Subject: drm/i915: Hold struct_mutex during i915_save_state/i915_restore_state Lots of register access in these functions, some of which requires the struct mutex. These functions now hold the struct mutex across the calls to i915_save_display and i915_restore_display, and so the internal mutex calls in those functions have been removed. To ensure that no-one else was calling them (and hence violating the new required locking invarient), those functions have been made static. gen6_enable_rps locks the struct mutex, and so i915_restore_state unlocks the mutex around calls to that function. Reviewed-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_suspend.c | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eddabf68e97a..1c8bfb1300d7 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); 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; -- cgit v1.2.3 From dc501fbc4389f6c15a8da14684b5926e0d9553da Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 29 Jun 2011 11:41:51 -0700 Subject: drm/i915: Don't call describe_obj on NULL pointers Reported-by: Pavel Roskin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38777 Cc: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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); -- cgit v1.2.3 From 79d2427338e8da362678de32a1c8af1dc8a9810a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jun 2011 11:27:47 +0100 Subject: drm/i915/overlay: Fix unpinning along init error paths As pointed out by Dan Carpenter, it was seemingly possible to hit an error whilst mapping the buffer for the regs (except the only likely error returns should not happen during init) and so leak a pin count on the bo. To handle this we would need to reacquire the struct mutex, so for simplicity rearrange for the lock to be held for the entire function. For extra pedagogy, test that we only call init once. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_overlay.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') 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; } -- cgit v1.2.3 From f71d4af4cd475aced6d9ec9730b03885ac80b833 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 28 Jun 2011 13:00:41 -0700 Subject: drm/i915: move IRQ function table init to i915_irq.c This lets us make the various IRQ functions static and helps avoid problems like the one fixed in "drm/i915: Use chipset-specific irq installers" where one of the exported functions was called rather than the chipset specific version. This also fixes a UMS-mode bug -- the correct irq functions for IRL and later chips were only getting loaded in the KMS path. Signed-off-by: Jesse Barnes Reviewed-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_dma.c | 31 +--------------- drivers/gpu/drm/i915/i915_drv.c | 8 ----- drivers/gpu/drm/i915/i915_drv.h | 30 +--------------- drivers/gpu/drm/i915/i915_irq.c | 78 ++++++++++++++++++++++++++++++----------- 4 files changed, 60 insertions(+), 87 deletions(-) (limited to 'drivers/gpu') 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 1c8bfb1300d7..f245c588ae95 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1031,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); @@ -1068,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..226d8b296e69 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; @@ -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; + } +} -- cgit v1.2.3 From 2b1ecb7337592a7bf0989efac46a5b52daab769e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 1 Jul 2011 11:08:56 -0700 Subject: drm/i915: apply HWSTAM writes to Ivy Bridge as well In an attempt to fix 38862 and 38863. Signed-off-by: Jesse Barnes Tested-by: Kenneth Graunke Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 226d8b296e69..3b03f85ea627 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1740,7 +1740,7 @@ static 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 -- cgit v1.2.3