diff options
author | Kenneth Graunke <kenneth@whitecape.org> | 2010-09-11 03:17:19 -0700 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-21 11:19:48 +0100 |
commit | 0573ed4a947d7a563db197511611d8a9039feb41 (patch) | |
tree | 21355b9a4ca6549eccad99b62e0f5addc38186c4 /drivers/gpu/drm/i915 | |
parent | eeccdcac07c1e21d25e7d3cf70030059a3017f0c (diff) |
drm/i915: Add support for GPU soft reset on Ironlake.
Ironlake's graphics reset register has to be accessed via the MCHBAR,
rather than via PCI config space, which requires some refactoring.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 3 |
3 files changed, 27 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 45027d5ad1e..e88aabdfd1d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -334,6 +334,24 @@ static int i965_reset_complete(struct drm_device *dev) return gdrst & 0x1; } +static int i965_do_reset(struct drm_device *dev, u8 flags) +{ + u8 gdrst; + + pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); + pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1); + + return wait_for(i965_reset_complete(dev), 500); +} + +static int ironlake_do_reset(struct drm_device *dev, u8 flags) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); + I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1); + return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); +} + /** * i965_reset - reset chip after a hang * @dev: drm device to reset @@ -353,12 +371,12 @@ static int i965_reset_complete(struct drm_device *dev) int i965_reset(struct drm_device *dev, u8 flags) { drm_i915_private_t *dev_priv = dev->dev_private; - u8 gdrst; /* * We really should only reset the display subsystem if we actually * need to */ bool need_display = true; + int ret; mutex_lock(&dev->struct_mutex); @@ -375,11 +393,11 @@ int i965_reset(struct drm_device *dev, u8 flags) * well as the reset bit (GR/bit 0). Setting the GR bit * triggers the reset; when done, the hardware will clear it. */ - pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); - pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1); - - /* Wait for the hardware to reset (but no more than 500 ms) */ - if (wait_for(i965_reset_complete(dev), 500)) { + if (IS_IRONLAKE(dev)) + ret = ironlake_do_reset(dev, flags); + else + ret = i965_do_reset(dev, flags); + if (ret) { WARN(true, "i915: Failed to reset chip\n"); mutex_unlock(&dev->struct_mutex); return -EIO; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b1dc943a02c..a5197e13d94 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -398,6 +398,7 @@ static void i915_error_work_func(struct work_struct *work) if (atomic_read(&dev_priv->mm.wedged)) { switch (INTEL_INFO(dev)->gen) { + case 5: case 4: DRM_DEBUG_DRIVER("resetting chip\n"); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 565a7a3ccd4..b46e580421e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -110,7 +110,8 @@ #define LBB 0xf4 /* Graphics reset regs */ -#define I965_GDRST 0xc0 +#define I965_GDRST 0xc0 /* PCI config register */ +#define ILK_GDSR 0x2ca4 /* MCHBAR offset */ #define GRDOM_FULL (0<<2) #define GRDOM_RENDER (1<<2) #define GRDOM_MEDIA (3<<2) |