diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_uncore.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_uncore.c | 227 |
1 files changed, 177 insertions, 50 deletions
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 6a0c3fb2cbf0..46de8d75b4bf 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -43,23 +43,17 @@ static void assert_device_not_suspended(struct drm_i915_private *dev_priv) { - WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, - "Device suspended\n"); + WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, + "Device suspended\n"); } static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) { - u32 gt_thread_status_mask; - - if (IS_HASWELL(dev_priv->dev)) - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; - else - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; - /* w/a for a sporadic read returning 0 by waiting for the GT * thread to wake up. */ - if (wait_for_atomic_us((__raw_i915_read32(dev_priv, GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) + if (wait_for_atomic_us((__raw_i915_read32(dev_priv, GEN6_GT_THREAD_STATUS_REG) & + GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 500)) DRM_ERROR("GT thread status wait timed out\n"); } @@ -120,8 +114,7 @@ static void __gen7_gt_force_wake_mt_get(struct drm_i915_private *dev_priv, DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); /* WaRsForcewakeWaitTC0:ivb,hsw */ - if (INTEL_INFO(dev_priv->dev)->gen < 8) - __gen6_gt_wait_for_thread_c0(dev_priv); + __gen6_gt_wait_for_thread_c0(dev_priv); } static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) @@ -229,10 +222,6 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, FORCEWAKE_ACK_TIMEOUT_MS)) DRM_ERROR("Timed out: waiting for media to ack.\n"); } - - /* WaRsForcewakeWaitTC0:vlv */ - if (!IS_CHERRYVIEW(dev_priv->dev)) - __gen6_gt_wait_for_thread_c0(dev_priv); } static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, @@ -681,6 +670,38 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv) REG_RANGE((reg), 0x14000, 0x14400) || \ REG_RANGE((reg), 0x22000, 0x24000)) +#define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \ + REG_RANGE((reg), 0xB00, 0x2000) + +#define FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) \ + (REG_RANGE((reg), 0x2000, 0x2700) || \ + REG_RANGE((reg), 0x3000, 0x4000) || \ + REG_RANGE((reg), 0x5200, 0x8000) || \ + REG_RANGE((reg), 0x8140, 0x8160) || \ + REG_RANGE((reg), 0x8300, 0x8500) || \ + REG_RANGE((reg), 0x8C00, 0x8D00) || \ + REG_RANGE((reg), 0xB000, 0xB480) || \ + REG_RANGE((reg), 0xE000, 0xE900) || \ + REG_RANGE((reg), 0x24400, 0x24800)) + +#define FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) \ + (REG_RANGE((reg), 0x8130, 0x8140) || \ + REG_RANGE((reg), 0x8800, 0x8A00) || \ + REG_RANGE((reg), 0xD000, 0xD800) || \ + REG_RANGE((reg), 0x12000, 0x14000) || \ + REG_RANGE((reg), 0x1A000, 0x1EA00) || \ + REG_RANGE((reg), 0x30000, 0x40000)) + +#define FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg) \ + REG_RANGE((reg), 0x9400, 0x9800) + +#define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \ + ((reg) < 0x40000 &&\ + !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \ + !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \ + !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \ + !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) + static void ilk_dummy_write(struct drm_i915_private *dev_priv) { @@ -811,6 +832,45 @@ chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ REG_READ_FOOTER; \ } +#define SKL_NEEDS_FORCE_WAKE(dev_priv, reg) \ + ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg)) + +#define __gen9_read(x) \ +static u##x \ +gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ + REG_READ_HEADER(x); \ + if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ + val = __raw_i915_read##x(dev_priv, reg); \ + } else { \ + unsigned fwengine = 0; \ + if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_rendercount == 0) \ + fwengine = FORCEWAKE_RENDER; \ + } else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_mediacount == 0) \ + fwengine = FORCEWAKE_MEDIA; \ + } else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_rendercount == 0) \ + fwengine |= FORCEWAKE_RENDER; \ + if (dev_priv->uncore.fw_mediacount == 0) \ + fwengine |= FORCEWAKE_MEDIA; \ + } else { \ + if (dev_priv->uncore.fw_blittercount == 0) \ + fwengine = FORCEWAKE_BLITTER; \ + } \ + if (fwengine) \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \ + val = __raw_i915_read##x(dev_priv, reg); \ + if (fwengine) \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \ + } \ + REG_READ_FOOTER; \ +} + +__gen9_read(8) +__gen9_read(16) +__gen9_read(32) +__gen9_read(64) __chv_read(8) __chv_read(16) __chv_read(32) @@ -832,6 +892,7 @@ __gen4_read(16) __gen4_read(32) __gen4_read(64) +#undef __gen9_read #undef __chv_read #undef __vlv_read #undef __gen6_read @@ -969,6 +1030,69 @@ chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) REG_WRITE_FOOTER; \ } +static const u32 gen9_shadowed_regs[] = { + RING_TAIL(RENDER_RING_BASE), + RING_TAIL(GEN6_BSD_RING_BASE), + RING_TAIL(VEBOX_RING_BASE), + RING_TAIL(BLT_RING_BASE), + FORCEWAKE_BLITTER_GEN9, + FORCEWAKE_RENDER_GEN9, + FORCEWAKE_MEDIA_GEN9, + GEN6_RPNSWREQ, + GEN6_RC_VIDEO_FREQ, + /* TODO: Other registers are not yet used */ +}; + +static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg) +{ + int i; + for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++) + if (reg == gen9_shadowed_regs[i]) + return true; + + return false; +} + +#define __gen9_write(x) \ +static void \ +gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ + bool trace) { \ + REG_WRITE_HEADER; \ + if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \ + is_gen9_shadowed(dev_priv, reg)) { \ + __raw_i915_write##x(dev_priv, reg, val); \ + } else { \ + unsigned fwengine = 0; \ + if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_rendercount == 0) \ + fwengine = FORCEWAKE_RENDER; \ + } else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_mediacount == 0) \ + fwengine = FORCEWAKE_MEDIA; \ + } else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) { \ + if (dev_priv->uncore.fw_rendercount == 0) \ + fwengine |= FORCEWAKE_RENDER; \ + if (dev_priv->uncore.fw_mediacount == 0) \ + fwengine |= FORCEWAKE_MEDIA; \ + } else { \ + if (dev_priv->uncore.fw_blittercount == 0) \ + fwengine = FORCEWAKE_BLITTER; \ + } \ + if (fwengine) \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, \ + fwengine); \ + __raw_i915_write##x(dev_priv, reg, val); \ + if (fwengine) \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, \ + fwengine); \ + } \ + REG_WRITE_FOOTER; \ +} + +__gen9_write(8) +__gen9_write(16) +__gen9_write(32) +__gen9_write(64) __chv_write(8) __chv_write(16) __chv_write(32) @@ -994,6 +1118,7 @@ __gen4_write(16) __gen4_write(32) __gen4_write(64) +#undef __gen9_write #undef __chv_write #undef __gen8_write #undef __hsw_write @@ -1077,6 +1202,13 @@ void intel_uncore_init(struct drm_device *dev) switch (INTEL_INFO(dev)->gen) { default: + WARN_ON(1); + return; + case 9: + ASSIGN_WRITE_MMIO_VFUNCS(gen9); + ASSIGN_READ_MMIO_VFUNCS(gen9); + break; + case 8: if (IS_CHERRYVIEW(dev)) { ASSIGN_WRITE_MMIO_VFUNCS(chv); ASSIGN_READ_MMIO_VFUNCS(chv); @@ -1217,41 +1349,34 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev, return 0; } -static int i965_reset_complete(struct drm_device *dev) +static int i915_reset_complete(struct drm_device *dev) { u8 gdrst; - pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); - return (gdrst & GRDOM_RESET_ENABLE) == 0; + pci_read_config_byte(dev->pdev, I915_GDRST, &gdrst); + return (gdrst & GRDOM_RESET_STATUS) == 0; } -static int i965_do_reset(struct drm_device *dev) +static int i915_do_reset(struct drm_device *dev) { - int ret; - - /* FIXME: i965g/gm need a display save/restore for gpu reset. */ - return -ENODEV; - - /* - * Set the domains we want to reset (GRDOM/bits 2 and 3) as - * well as the reset bit (GR/bit 0). Setting the GR bit - * triggers the reset; when done, the hardware will clear it. - */ - pci_write_config_byte(dev->pdev, I965_GDRST, - GRDOM_RENDER | GRDOM_RESET_ENABLE); - ret = wait_for(i965_reset_complete(dev), 500); - if (ret) - return ret; + /* assert reset for at least 20 usec */ + pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE); + udelay(20); + pci_write_config_byte(dev->pdev, I915_GDRST, 0); - pci_write_config_byte(dev->pdev, I965_GDRST, - GRDOM_MEDIA | GRDOM_RESET_ENABLE); - - ret = wait_for(i965_reset_complete(dev), 500); - if (ret) - return ret; + return wait_for(i915_reset_complete(dev), 500); +} - pci_write_config_byte(dev->pdev, I965_GDRST, 0); +static int g4x_reset_complete(struct drm_device *dev) +{ + u8 gdrst; + pci_read_config_byte(dev->pdev, I915_GDRST, &gdrst); + return (gdrst & GRDOM_RESET_ENABLE) == 0; +} - return 0; +static int g33_do_reset(struct drm_device *dev) +{ + pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE); + return wait_for(g4x_reset_complete(dev), 500); } static int g4x_do_reset(struct drm_device *dev) @@ -1259,9 +1384,9 @@ static int g4x_do_reset(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - pci_write_config_byte(dev->pdev, I965_GDRST, + pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RENDER | GRDOM_RESET_ENABLE); - ret = wait_for(i965_reset_complete(dev), 500); + ret = wait_for(g4x_reset_complete(dev), 500); if (ret) return ret; @@ -1269,9 +1394,9 @@ static int g4x_do_reset(struct drm_device *dev) I915_WRITE(VDECCLK_GATE_D, I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE); POSTING_READ(VDECCLK_GATE_D); - pci_write_config_byte(dev->pdev, I965_GDRST, + pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_MEDIA | GRDOM_RESET_ENABLE); - ret = wait_for(i965_reset_complete(dev), 500); + ret = wait_for(g4x_reset_complete(dev), 500); if (ret) return ret; @@ -1279,7 +1404,7 @@ static int g4x_do_reset(struct drm_device *dev) I915_WRITE(VDECCLK_GATE_D, I915_READ(VDECCLK_GATE_D) & ~VCP_UNIT_CLOCK_GATE_DISABLE); POSTING_READ(VDECCLK_GATE_D); - pci_write_config_byte(dev->pdev, I965_GDRST, 0); + pci_write_config_byte(dev->pdev, I915_GDRST, 0); return 0; } @@ -1337,8 +1462,10 @@ int intel_gpu_reset(struct drm_device *dev) return ironlake_do_reset(dev); else if (IS_G4X(dev)) return g4x_do_reset(dev); - else if (IS_GEN4(dev)) - return i965_do_reset(dev); + else if (IS_G33(dev)) + return g33_do_reset(dev); + else if (INTEL_INFO(dev)->gen >= 3) + return i915_do_reset(dev); else return -ENODEV; } |