diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-01-16 04:34:37 -0500 |
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-01-27 03:50:55 -0500 |
| commit | b2cff0dbbb7ef03e08865b906b236a06c6cf2e2f (patch) | |
| tree | d1667633d4854125c031818000d30346536f9572 /drivers/gpu | |
| parent | 51f67885842e36e0d0c853795cd02b129e19a20b (diff) | |
drm/i915: Reduce duplicated forcewake logic
Introduce a structure to track the individual forcewake domains and use
that to eliminate duplicate logic.
v2: - Rebase on latest dinq (Mika)
- for_each_fw_domain macro (Mika)
- Handle reset atomically, keeping the timer running (Mika)
- for_each_fw_domain parameter ordering (Chris)
- defer timer on new register access (Mika)
v3: - Fix forcewake_reset/get race by waiting pending timers
v4: - cond_resched and verbose warning on timer deletion (Chris)
- need to run pending timers manually on reset
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
Acked-by: Deepak S <deepak.s@linux.intel.com> (v2)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 65 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 54 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_uncore.c | 445 |
3 files changed, 246 insertions, 318 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ac517eb07c00..4d156e65837f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -1288,14 +1288,36 @@ static int ironlake_drpc_info(struct seq_file *m) | |||
| 1288 | return 0; | 1288 | return 0; |
| 1289 | } | 1289 | } |
| 1290 | 1290 | ||
| 1291 | static int vlv_drpc_info(struct seq_file *m) | 1291 | static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) |
| 1292 | { | 1292 | { |
| 1293 | struct drm_info_node *node = m->private; | ||
| 1294 | struct drm_device *dev = node->minor->dev; | ||
| 1295 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1296 | struct intel_uncore_forcewake_domain *fw_domain; | ||
| 1297 | const char *domain_names[] = { | ||
| 1298 | "render", | ||
| 1299 | "blitter", | ||
| 1300 | "media", | ||
| 1301 | }; | ||
| 1302 | int i; | ||
| 1303 | |||
| 1304 | spin_lock_irq(&dev_priv->uncore.lock); | ||
| 1305 | for_each_fw_domain(fw_domain, dev_priv, i) { | ||
| 1306 | seq_printf(m, "%s.wake_count = %u\n", | ||
| 1307 | domain_names[i], | ||
| 1308 | fw_domain->wake_count); | ||
| 1309 | } | ||
| 1310 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
| 1293 | 1311 | ||
| 1312 | return 0; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | static int vlv_drpc_info(struct seq_file *m) | ||
| 1316 | { | ||
| 1294 | struct drm_info_node *node = m->private; | 1317 | struct drm_info_node *node = m->private; |
| 1295 | struct drm_device *dev = node->minor->dev; | 1318 | struct drm_device *dev = node->minor->dev; |
| 1296 | struct drm_i915_private *dev_priv = dev->dev_private; | 1319 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1297 | u32 rpmodectl1, rcctl1, pw_status; | 1320 | u32 rpmodectl1, rcctl1, pw_status; |
| 1298 | unsigned fw_rendercount = 0, fw_mediacount = 0; | ||
| 1299 | 1321 | ||
| 1300 | intel_runtime_pm_get(dev_priv); | 1322 | intel_runtime_pm_get(dev_priv); |
| 1301 | 1323 | ||
| @@ -1327,22 +1349,11 @@ static int vlv_drpc_info(struct seq_file *m) | |||
| 1327 | seq_printf(m, "Media RC6 residency since boot: %u\n", | 1349 | seq_printf(m, "Media RC6 residency since boot: %u\n", |
| 1328 | I915_READ(VLV_GT_MEDIA_RC6)); | 1350 | I915_READ(VLV_GT_MEDIA_RC6)); |
| 1329 | 1351 | ||
| 1330 | spin_lock_irq(&dev_priv->uncore.lock); | 1352 | return i915_gen6_forcewake_count_info(m, NULL); |
| 1331 | fw_rendercount = dev_priv->uncore.fw_rendercount; | ||
| 1332 | fw_mediacount = dev_priv->uncore.fw_mediacount; | ||
| 1333 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
| 1334 | |||
| 1335 | seq_printf(m, "Forcewake Render Count = %u\n", fw_rendercount); | ||
| 1336 | seq_printf(m, "Forcewake Media Count = %u\n", fw_mediacount); | ||
| 1337 | |||
| 1338 | |||
| 1339 | return 0; | ||
| 1340 | } | 1353 | } |
| 1341 | 1354 | ||
| 1342 | |||
| 1343 | static int gen6_drpc_info(struct seq_file *m) | 1355 | static int gen6_drpc_info(struct seq_file *m) |
| 1344 | { | 1356 | { |
| 1345 | |||
| 1346 | struct drm_info_node *node = m->private; | 1357 | struct drm_info_node *node = m->private; |
| 1347 | struct drm_device *dev = node->minor->dev; | 1358 | struct drm_device *dev = node->minor->dev; |
| 1348 | struct drm_i915_private *dev_priv = dev->dev_private; | 1359 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -1356,7 +1367,7 @@ static int gen6_drpc_info(struct seq_file *m) | |||
| 1356 | intel_runtime_pm_get(dev_priv); | 1367 | intel_runtime_pm_get(dev_priv); |
| 1357 | 1368 | ||
| 1358 | spin_lock_irq(&dev_priv->uncore.lock); | 1369 | spin_lock_irq(&dev_priv->uncore.lock); |
| 1359 | forcewake_count = dev_priv->uncore.forcewake_count; | 1370 | forcewake_count = dev_priv->uncore.fw_domain[FW_DOMAIN_ID_RENDER].wake_count; |
| 1360 | spin_unlock_irq(&dev_priv->uncore.lock); | 1371 | spin_unlock_irq(&dev_priv->uncore.lock); |
| 1361 | 1372 | ||
| 1362 | if (forcewake_count) { | 1373 | if (forcewake_count) { |
| @@ -1984,30 +1995,6 @@ static int i915_execlists(struct seq_file *m, void *data) | |||
| 1984 | return 0; | 1995 | return 0; |
| 1985 | } | 1996 | } |
| 1986 | 1997 | ||
| 1987 | static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) | ||
| 1988 | { | ||
| 1989 | struct drm_info_node *node = m->private; | ||
| 1990 | struct drm_device *dev = node->minor->dev; | ||
| 1991 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1992 | unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0; | ||
| 1993 | |||
| 1994 | spin_lock_irq(&dev_priv->uncore.lock); | ||
| 1995 | if (IS_VALLEYVIEW(dev)) { | ||
| 1996 | fw_rendercount = dev_priv->uncore.fw_rendercount; | ||
| 1997 | fw_mediacount = dev_priv->uncore.fw_mediacount; | ||
| 1998 | } else | ||
| 1999 | forcewake_count = dev_priv->uncore.forcewake_count; | ||
| 2000 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
| 2001 | |||
| 2002 | if (IS_VALLEYVIEW(dev)) { | ||
| 2003 | seq_printf(m, "fw_rendercount = %u\n", fw_rendercount); | ||
| 2004 | seq_printf(m, "fw_mediacount = %u\n", fw_mediacount); | ||
| 2005 | } else | ||
| 2006 | seq_printf(m, "forcewake count = %u\n", forcewake_count); | ||
| 2007 | |||
| 2008 | return 0; | ||
| 2009 | } | ||
| 2010 | |||
| 2011 | static const char *swizzle_string(unsigned swizzle) | 1998 | static const char *swizzle_string(unsigned swizzle) |
| 2012 | { | 1999 | { |
| 2013 | switch (swizzle) { | 2000 | switch (swizzle) { |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3a32e0d81a9f..ac2082b022f3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -596,20 +596,45 @@ struct intel_uncore_funcs { | |||
| 596 | uint64_t val, bool trace); | 596 | uint64_t val, bool trace); |
| 597 | }; | 597 | }; |
| 598 | 598 | ||
| 599 | enum { | ||
| 600 | FW_DOMAIN_ID_RENDER = 0, | ||
| 601 | FW_DOMAIN_ID_BLITTER, | ||
| 602 | FW_DOMAIN_ID_MEDIA, | ||
| 603 | |||
| 604 | FW_DOMAIN_ID_COUNT | ||
| 605 | }; | ||
| 606 | |||
| 599 | struct intel_uncore { | 607 | struct intel_uncore { |
| 600 | spinlock_t lock; /** lock is also taken in irq contexts. */ | 608 | spinlock_t lock; /** lock is also taken in irq contexts. */ |
| 601 | 609 | ||
| 602 | struct intel_uncore_funcs funcs; | 610 | struct intel_uncore_funcs funcs; |
| 603 | 611 | ||
| 604 | unsigned fifo_count; | 612 | unsigned fifo_count; |
| 605 | unsigned forcewake_count; | 613 | unsigned fw_domains; |
| 606 | 614 | ||
| 607 | unsigned fw_rendercount; | 615 | struct intel_uncore_forcewake_domain { |
| 608 | unsigned fw_mediacount; | 616 | struct drm_i915_private *i915; |
| 609 | unsigned fw_blittercount; | 617 | int id; |
| 610 | 618 | unsigned wake_count; | |
| 611 | struct timer_list force_wake_timer; | 619 | struct timer_list timer; |
| 612 | }; | 620 | } fw_domain[FW_DOMAIN_ID_COUNT]; |
| 621 | #define FORCEWAKE_RENDER (1 << FW_DOMAIN_ID_RENDER) | ||
| 622 | #define FORCEWAKE_BLITTER (1 << FW_DOMAIN_ID_BLITTER) | ||
| 623 | #define FORCEWAKE_MEDIA (1 << FW_DOMAIN_ID_MEDIA) | ||
| 624 | #define FORCEWAKE_ALL (FORCEWAKE_RENDER | \ | ||
| 625 | FORCEWAKE_BLITTER | \ | ||
| 626 | FORCEWAKE_MEDIA) | ||
| 627 | }; | ||
| 628 | |||
| 629 | /* Iterate over initialised fw domains */ | ||
| 630 | #define for_each_fw_domain_mask(domain__, mask__, dev_priv__, i__) \ | ||
| 631 | for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \ | ||
| 632 | (i__) < FW_DOMAIN_ID_COUNT; \ | ||
| 633 | (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \ | ||
| 634 | if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__))) | ||
| 635 | |||
| 636 | #define for_each_fw_domain(domain__, dev_priv__, i__) \ | ||
| 637 | for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__) | ||
| 613 | 638 | ||
| 614 | #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ | 639 | #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ |
| 615 | func(is_mobile) sep \ | 640 | func(is_mobile) sep \ |
| @@ -3167,8 +3192,10 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, | |||
| 3167 | * must be set to prevent GT core from power down and stale values being | 3192 | * must be set to prevent GT core from power down and stale values being |
| 3168 | * returned. | 3193 | * returned. |
| 3169 | */ | 3194 | */ |
| 3170 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine); | 3195 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, |
| 3171 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine); | 3196 | unsigned fw_domains); |
| 3197 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, | ||
| 3198 | unsigned fw_domains); | ||
| 3172 | void assert_force_wake_inactive(struct drm_i915_private *dev_priv); | 3199 | void assert_force_wake_inactive(struct drm_i915_private *dev_priv); |
| 3173 | 3200 | ||
| 3174 | int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val); | 3201 | int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val); |
| @@ -3200,13 +3227,6 @@ void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); | |||
| 3200 | int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); | 3227 | int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); |
| 3201 | int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); | 3228 | int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); |
| 3202 | 3229 | ||
| 3203 | #define FORCEWAKE_RENDER (1 << 0) | ||
| 3204 | #define FORCEWAKE_MEDIA (1 << 1) | ||
| 3205 | #define FORCEWAKE_BLITTER (1 << 2) | ||
| 3206 | #define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA | \ | ||
| 3207 | FORCEWAKE_BLITTER) | ||
| 3208 | |||
| 3209 | |||
| 3210 | #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) | 3230 | #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) |
| 3211 | #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) | 3231 | #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) |
| 3212 | 3232 | ||
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 3d1ffacb7612..b35f3a9e6869 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c | |||
| @@ -67,7 +67,7 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, | 69 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, |
| 70 | int fw_engine) | 70 | int fw_engine) |
| 71 | { | 71 | { |
| 72 | if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0, | 72 | if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0, |
| 73 | FORCEWAKE_ACK_TIMEOUT_MS)) | 73 | FORCEWAKE_ACK_TIMEOUT_MS)) |
| @@ -93,7 +93,7 @@ static void __gen7_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static void __gen7_gt_force_wake_mt_get(struct drm_i915_private *dev_priv, | 95 | static void __gen7_gt_force_wake_mt_get(struct drm_i915_private *dev_priv, |
| 96 | int fw_engine) | 96 | int fw_engine) |
| 97 | { | 97 | { |
| 98 | u32 forcewake_ack; | 98 | u32 forcewake_ack; |
| 99 | 99 | ||
| @@ -129,7 +129,7 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | |||
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, | 131 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, |
| 132 | int fw_engine) | 132 | int fw_engine) |
| 133 | { | 133 | { |
| 134 | __raw_i915_write32(dev_priv, FORCEWAKE, 0); | 134 | __raw_i915_write32(dev_priv, FORCEWAKE, 0); |
| 135 | /* something from same cacheline, but !FORCEWAKE */ | 135 | /* something from same cacheline, but !FORCEWAKE */ |
| @@ -138,7 +138,7 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, | |||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static void __gen7_gt_force_wake_mt_put(struct drm_i915_private *dev_priv, | 140 | static void __gen7_gt_force_wake_mt_put(struct drm_i915_private *dev_priv, |
| 141 | int fw_engine) | 141 | int fw_engine) |
| 142 | { | 142 | { |
| 143 | __raw_i915_write32(dev_priv, FORCEWAKE_MT, | 143 | __raw_i915_write32(dev_priv, FORCEWAKE_MT, |
| 144 | _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 144 | _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
| @@ -187,7 +187,7 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) | |||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, | 189 | static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, |
| 190 | int fw_engine) | 190 | int fw_engine) |
| 191 | { | 191 | { |
| 192 | /* Check for Render Engine */ | 192 | /* Check for Render Engine */ |
| 193 | if (FORCEWAKE_RENDER & fw_engine) { | 193 | if (FORCEWAKE_RENDER & fw_engine) { |
| @@ -227,9 +227,8 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, | 229 | static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, |
| 230 | int fw_engine) | 230 | int fw_engine) |
| 231 | { | 231 | { |
| 232 | |||
| 233 | /* Check for Render Engine */ | 232 | /* Check for Render Engine */ |
| 234 | if (FORCEWAKE_RENDER & fw_engine) | 233 | if (FORCEWAKE_RENDER & fw_engine) |
| 235 | __raw_i915_write32(dev_priv, FORCEWAKE_VLV, | 234 | __raw_i915_write32(dev_priv, FORCEWAKE_VLV, |
| @@ -247,37 +246,6 @@ static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, | |||
| 247 | gen6_gt_check_fifodbg(dev_priv); | 246 | gen6_gt_check_fifodbg(dev_priv); |
| 248 | } | 247 | } |
| 249 | 248 | ||
| 250 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | ||
| 251 | { | ||
| 252 | if (fw_engine & FORCEWAKE_RENDER && | ||
| 253 | dev_priv->uncore.fw_rendercount++ != 0) | ||
| 254 | fw_engine &= ~FORCEWAKE_RENDER; | ||
| 255 | if (fw_engine & FORCEWAKE_MEDIA && | ||
| 256 | dev_priv->uncore.fw_mediacount++ != 0) | ||
| 257 | fw_engine &= ~FORCEWAKE_MEDIA; | ||
| 258 | |||
| 259 | if (fw_engine) | ||
| 260 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_engine); | ||
| 261 | } | ||
| 262 | |||
| 263 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | ||
| 264 | { | ||
| 265 | if (fw_engine & FORCEWAKE_RENDER) { | ||
| 266 | WARN_ON(!dev_priv->uncore.fw_rendercount); | ||
| 267 | if (--dev_priv->uncore.fw_rendercount != 0) | ||
| 268 | fw_engine &= ~FORCEWAKE_RENDER; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (fw_engine & FORCEWAKE_MEDIA) { | ||
| 272 | WARN_ON(!dev_priv->uncore.fw_mediacount); | ||
| 273 | if (--dev_priv->uncore.fw_mediacount != 0) | ||
| 274 | fw_engine &= ~FORCEWAKE_MEDIA; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (fw_engine) | ||
| 278 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw_engine); | ||
| 279 | } | ||
| 280 | |||
| 281 | static void __gen9_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | 249 | static void __gen9_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) |
| 282 | { | 250 | { |
| 283 | __raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9, | 251 | __raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9, |
| @@ -367,80 +335,72 @@ __gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | |||
| 367 | _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 335 | _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
| 368 | } | 336 | } |
| 369 | 337 | ||
| 370 | static void | 338 | static void gen6_force_wake_timer(unsigned long arg) |
| 371 | gen9_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | ||
| 372 | { | 339 | { |
| 373 | if (FORCEWAKE_RENDER & fw_engine) { | 340 | struct intel_uncore_forcewake_domain *domain = (void *)arg; |
| 374 | if (dev_priv->uncore.fw_rendercount++ == 0) | 341 | unsigned long irqflags; |
| 375 | dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||
| 376 | FORCEWAKE_RENDER); | ||
| 377 | } | ||
| 378 | 342 | ||
| 379 | if (FORCEWAKE_MEDIA & fw_engine) { | 343 | assert_device_not_suspended(domain->i915); |
| 380 | if (dev_priv->uncore.fw_mediacount++ == 0) | ||
| 381 | dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||
| 382 | FORCEWAKE_MEDIA); | ||
| 383 | } | ||
| 384 | 344 | ||
| 385 | if (FORCEWAKE_BLITTER & fw_engine) { | 345 | spin_lock_irqsave(&domain->i915->uncore.lock, irqflags); |
| 386 | if (dev_priv->uncore.fw_blittercount++ == 0) | 346 | if (WARN_ON(domain->wake_count == 0)) |
| 387 | dev_priv->uncore.funcs.force_wake_get(dev_priv, | 347 | domain->wake_count++; |
| 388 | FORCEWAKE_BLITTER); | 348 | |
| 389 | } | 349 | if (--domain->wake_count == 0) |
| 350 | domain->i915->uncore.funcs.force_wake_put(domain->i915, | ||
| 351 | 1 << domain->id); | ||
| 352 | |||
| 353 | spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags); | ||
| 390 | } | 354 | } |
| 391 | 355 | ||
| 392 | static void | 356 | void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) |
| 393 | gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | ||
| 394 | { | 357 | { |
| 395 | if (FORCEWAKE_RENDER & fw_engine) { | 358 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 396 | WARN_ON(dev_priv->uncore.fw_rendercount == 0); | 359 | unsigned long irqflags, fw = 0; |
| 397 | if (--dev_priv->uncore.fw_rendercount == 0) | 360 | struct intel_uncore_forcewake_domain *domain; |
| 398 | dev_priv->uncore.funcs.force_wake_put(dev_priv, | 361 | int id, active_domains, retry_count = 100; |
| 399 | FORCEWAKE_RENDER); | ||
| 400 | } | ||
| 401 | 362 | ||
| 402 | if (FORCEWAKE_MEDIA & fw_engine) { | 363 | /* Hold uncore.lock across reset to prevent any register access |
| 403 | WARN_ON(dev_priv->uncore.fw_mediacount == 0); | 364 | * with forcewake not set correctly. Wait until all pending |
| 404 | if (--dev_priv->uncore.fw_mediacount == 0) | 365 | * timers are run before holding. |
| 405 | dev_priv->uncore.funcs.force_wake_put(dev_priv, | 366 | */ |
| 406 | FORCEWAKE_MEDIA); | 367 | while (1) { |
| 407 | } | 368 | active_domains = 0; |
| 408 | 369 | ||
| 409 | if (FORCEWAKE_BLITTER & fw_engine) { | 370 | for_each_fw_domain(domain, dev_priv, id) { |
| 410 | WARN_ON(dev_priv->uncore.fw_blittercount == 0); | 371 | if (del_timer_sync(&domain->timer) == 0) |
| 411 | if (--dev_priv->uncore.fw_blittercount == 0) | 372 | continue; |
| 412 | dev_priv->uncore.funcs.force_wake_put(dev_priv, | ||
| 413 | FORCEWAKE_BLITTER); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | 373 | ||
| 417 | static void gen6_force_wake_timer(unsigned long arg) | 374 | gen6_force_wake_timer((unsigned long)domain); |
| 418 | { | 375 | } |
| 419 | struct drm_i915_private *dev_priv = (void *)arg; | ||
| 420 | unsigned long irqflags; | ||
| 421 | 376 | ||
| 422 | assert_device_not_suspended(dev_priv); | 377 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
| 423 | 378 | ||
| 424 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 379 | for_each_fw_domain(domain, dev_priv, id) { |
| 425 | WARN_ON(!dev_priv->uncore.forcewake_count); | 380 | if (timer_pending(&domain->timer)) |
| 381 | active_domains |= (1 << id); | ||
| 382 | } | ||
| 426 | 383 | ||
| 427 | if (--dev_priv->uncore.forcewake_count == 0) | 384 | if (active_domains == 0) |
| 428 | dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); | 385 | break; |
| 429 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | ||
| 430 | } | ||
| 431 | 386 | ||
| 432 | void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) | 387 | if (--retry_count == 0) { |
| 433 | { | 388 | DRM_ERROR("Timed out waiting for forcewake timers to finish\n"); |
| 434 | struct drm_i915_private *dev_priv = dev->dev_private; | 389 | break; |
| 435 | unsigned long irqflags; | 390 | } |
| 436 | 391 | ||
| 437 | if (del_timer_sync(&dev_priv->uncore.force_wake_timer)) | 392 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
| 438 | gen6_force_wake_timer((unsigned long)dev_priv); | 393 | cond_resched(); |
| 394 | } | ||
| 439 | 395 | ||
| 440 | /* Hold uncore.lock across reset to prevent any register access | 396 | WARN_ON(active_domains); |
| 441 | * with forcewake not set correctly | 397 | |
| 442 | */ | 398 | for_each_fw_domain(domain, dev_priv, id) |
| 443 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 399 | if (domain->wake_count) |
| 400 | fw |= 1 << id; | ||
| 401 | |||
| 402 | if (fw) | ||
| 403 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); | ||
| 444 | 404 | ||
| 445 | if (IS_VALLEYVIEW(dev)) | 405 | if (IS_VALLEYVIEW(dev)) |
| 446 | vlv_force_wake_reset(dev_priv); | 406 | vlv_force_wake_reset(dev_priv); |
| @@ -454,28 +414,6 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) | |||
| 454 | __gen9_gt_force_wake_mt_reset(dev_priv); | 414 | __gen9_gt_force_wake_mt_reset(dev_priv); |
| 455 | 415 | ||
| 456 | if (restore) { /* If reset with a user forcewake, try to restore */ | 416 | if (restore) { /* If reset with a user forcewake, try to restore */ |
| 457 | unsigned fw = 0; | ||
| 458 | |||
| 459 | if (IS_VALLEYVIEW(dev)) { | ||
| 460 | if (dev_priv->uncore.fw_rendercount) | ||
| 461 | fw |= FORCEWAKE_RENDER; | ||
| 462 | |||
| 463 | if (dev_priv->uncore.fw_mediacount) | ||
| 464 | fw |= FORCEWAKE_MEDIA; | ||
| 465 | } else if (IS_GEN9(dev)) { | ||
| 466 | if (dev_priv->uncore.fw_rendercount) | ||
| 467 | fw |= FORCEWAKE_RENDER; | ||
| 468 | |||
| 469 | if (dev_priv->uncore.fw_mediacount) | ||
| 470 | fw |= FORCEWAKE_MEDIA; | ||
| 471 | |||
| 472 | if (dev_priv->uncore.fw_blittercount) | ||
| 473 | fw |= FORCEWAKE_BLITTER; | ||
| 474 | } else { | ||
| 475 | if (dev_priv->uncore.forcewake_count) | ||
| 476 | fw = FORCEWAKE_ALL; | ||
| 477 | } | ||
| 478 | |||
| 479 | if (fw) | 417 | if (fw) |
| 480 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw); | 418 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw); |
| 481 | 419 | ||
| @@ -485,6 +423,9 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) | |||
| 485 | GT_FIFO_FREE_ENTRIES_MASK; | 423 | GT_FIFO_FREE_ENTRIES_MASK; |
| 486 | } | 424 | } |
| 487 | 425 | ||
| 426 | if (!restore) | ||
| 427 | assert_force_wake_inactive(dev_priv); | ||
| 428 | |||
| 488 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 429 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
| 489 | } | 430 | } |
| 490 | 431 | ||
| @@ -533,53 +474,59 @@ void intel_uncore_sanitize(struct drm_device *dev) | |||
| 533 | * be called at the beginning of the sequence followed by a call to | 474 | * be called at the beginning of the sequence followed by a call to |
| 534 | * gen6_gt_force_wake_put() at the end of the sequence. | 475 | * gen6_gt_force_wake_put() at the end of the sequence. |
| 535 | */ | 476 | */ |
| 536 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | 477 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, |
| 478 | unsigned fw_domains) | ||
| 537 | { | 479 | { |
| 538 | unsigned long irqflags; | 480 | unsigned long irqflags; |
| 481 | struct intel_uncore_forcewake_domain *domain; | ||
| 482 | int id; | ||
| 539 | 483 | ||
| 540 | if (!dev_priv->uncore.funcs.force_wake_get) | 484 | if (!dev_priv->uncore.funcs.force_wake_get) |
| 541 | return; | 485 | return; |
| 542 | 486 | ||
| 543 | WARN_ON(dev_priv->pm.suspended); | 487 | WARN_ON(dev_priv->pm.suspended); |
| 544 | 488 | ||
| 489 | fw_domains &= dev_priv->uncore.fw_domains; | ||
| 490 | |||
| 545 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 491 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
| 546 | 492 | ||
| 547 | if (IS_GEN9(dev_priv->dev)) { | 493 | for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) { |
| 548 | gen9_force_wake_get(dev_priv, fw_engine); | 494 | if (domain->wake_count++) |
| 549 | } else if (IS_VALLEYVIEW(dev_priv->dev)) { | 495 | fw_domains &= ~(1 << id); |
| 550 | vlv_force_wake_get(dev_priv, fw_engine); | ||
| 551 | } else { | ||
| 552 | if (dev_priv->uncore.forcewake_count++ == 0) | ||
| 553 | dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||
| 554 | FORCEWAKE_ALL); | ||
| 555 | } | 496 | } |
| 556 | 497 | ||
| 498 | if (fw_domains) | ||
| 499 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | ||
| 500 | |||
| 557 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 501 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
| 558 | } | 502 | } |
| 559 | 503 | ||
| 560 | /* | 504 | /* |
| 561 | * see gen6_gt_force_wake_get() | 505 | * see gen6_gt_force_wake_get() |
| 562 | */ | 506 | */ |
| 563 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | 507 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, |
| 508 | unsigned fw_domains) | ||
| 564 | { | 509 | { |
| 565 | unsigned long irqflags; | 510 | unsigned long irqflags; |
| 511 | struct intel_uncore_forcewake_domain *domain; | ||
| 512 | int id; | ||
| 566 | 513 | ||
| 567 | if (!dev_priv->uncore.funcs.force_wake_put) | 514 | if (!dev_priv->uncore.funcs.force_wake_put) |
| 568 | return; | 515 | return; |
| 569 | 516 | ||
| 517 | fw_domains &= dev_priv->uncore.fw_domains; | ||
| 518 | |||
| 570 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 519 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
| 571 | 520 | ||
| 572 | if (IS_GEN9(dev_priv->dev)) { | 521 | for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) { |
| 573 | gen9_force_wake_put(dev_priv, fw_engine); | 522 | if (WARN_ON(domain->wake_count == 0)) |
| 574 | } else if (IS_VALLEYVIEW(dev_priv->dev)) { | 523 | continue; |
| 575 | vlv_force_wake_put(dev_priv, fw_engine); | 524 | |
| 576 | } else { | 525 | if (--domain->wake_count) |
| 577 | WARN_ON(!dev_priv->uncore.forcewake_count); | 526 | continue; |
| 578 | if (--dev_priv->uncore.forcewake_count == 0) { | 527 | |
| 579 | dev_priv->uncore.forcewake_count++; | 528 | domain->wake_count++; |
| 580 | mod_timer_pinned(&dev_priv->uncore.force_wake_timer, | 529 | mod_timer_pinned(&domain->timer, jiffies + 1); |
| 581 | jiffies + 1); | ||
| 582 | } | ||
| 583 | } | 530 | } |
| 584 | 531 | ||
| 585 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 532 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
| @@ -587,10 +534,14 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | |||
| 587 | 534 | ||
| 588 | void assert_force_wake_inactive(struct drm_i915_private *dev_priv) | 535 | void assert_force_wake_inactive(struct drm_i915_private *dev_priv) |
| 589 | { | 536 | { |
| 537 | struct intel_uncore_forcewake_domain *domain; | ||
| 538 | int i; | ||
| 539 | |||
| 590 | if (!dev_priv->uncore.funcs.force_wake_get) | 540 | if (!dev_priv->uncore.funcs.force_wake_get) |
| 591 | return; | 541 | return; |
| 592 | 542 | ||
| 593 | WARN_ON(dev_priv->uncore.forcewake_count > 0); | 543 | for_each_fw_domain(domain, dev_priv, i) |
| 544 | WARN_ON(domain->wake_count); | ||
| 594 | } | 545 | } |
| 595 | 546 | ||
| 596 | /* We give fast paths for the really cool registers */ | 547 | /* We give fast paths for the really cool registers */ |
| @@ -753,19 +704,37 @@ __gen2_read(64) | |||
| 753 | trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ | 704 | trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ |
| 754 | return val | 705 | return val |
| 755 | 706 | ||
| 707 | static inline void __force_wake_get(struct drm_i915_private *dev_priv, | ||
| 708 | unsigned fw_domains) | ||
| 709 | { | ||
| 710 | struct intel_uncore_forcewake_domain *domain; | ||
| 711 | int i; | ||
| 712 | |||
| 713 | if (WARN_ON(!fw_domains)) | ||
| 714 | return; | ||
| 715 | |||
| 716 | /* Ideally GCC would be constant-fold and eliminate this loop */ | ||
| 717 | for_each_fw_domain_mask(domain, fw_domains, dev_priv, i) { | ||
| 718 | if (domain->wake_count) { | ||
| 719 | fw_domains &= ~(1 << i); | ||
| 720 | continue; | ||
| 721 | } | ||
| 722 | |||
| 723 | domain->wake_count++; | ||
| 724 | mod_timer_pinned(&domain->timer, jiffies + 1); | ||
| 725 | } | ||
| 726 | |||
| 727 | if (fw_domains) | ||
| 728 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | ||
| 729 | } | ||
| 730 | |||
| 756 | #define __gen6_read(x) \ | 731 | #define __gen6_read(x) \ |
| 757 | static u##x \ | 732 | static u##x \ |
| 758 | gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | 733 | gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ |
| 759 | GEN6_READ_HEADER(x); \ | 734 | GEN6_READ_HEADER(x); \ |
| 760 | hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ | 735 | hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ |
| 761 | if (dev_priv->uncore.forcewake_count == 0 && \ | 736 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) \ |
| 762 | NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ | 737 | __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ |
| 763 | dev_priv->uncore.funcs.force_wake_get(dev_priv, \ | ||
| 764 | FORCEWAKE_ALL); \ | ||
| 765 | dev_priv->uncore.forcewake_count++; \ | ||
| 766 | mod_timer_pinned(&dev_priv->uncore.force_wake_timer, \ | ||
| 767 | jiffies + 1); \ | ||
| 768 | } \ | ||
| 769 | val = __raw_i915_read##x(dev_priv, reg); \ | 738 | val = __raw_i915_read##x(dev_priv, reg); \ |
| 770 | hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ | 739 | hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ |
| 771 | GEN6_READ_FOOTER; \ | 740 | GEN6_READ_FOOTER; \ |
| @@ -774,45 +743,27 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | |||
| 774 | #define __vlv_read(x) \ | 743 | #define __vlv_read(x) \ |
| 775 | static u##x \ | 744 | static u##x \ |
| 776 | vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | 745 | vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ |
| 777 | unsigned fwengine = 0; \ | ||
| 778 | GEN6_READ_HEADER(x); \ | 746 | GEN6_READ_HEADER(x); \ |
| 779 | if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) { \ | 747 | if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) \ |
| 780 | if (dev_priv->uncore.fw_rendercount == 0) \ | 748 | __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ |
| 781 | fwengine = FORCEWAKE_RENDER; \ | 749 | else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) \ |
| 782 | } else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) { \ | 750 | __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ |
| 783 | if (dev_priv->uncore.fw_mediacount == 0) \ | ||
| 784 | fwengine = FORCEWAKE_MEDIA; \ | ||
| 785 | } \ | ||
| 786 | if (fwengine) \ | ||
| 787 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \ | ||
| 788 | val = __raw_i915_read##x(dev_priv, reg); \ | 751 | val = __raw_i915_read##x(dev_priv, reg); \ |
| 789 | if (fwengine) \ | ||
| 790 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \ | ||
| 791 | GEN6_READ_FOOTER; \ | 752 | GEN6_READ_FOOTER; \ |
| 792 | } | 753 | } |
| 793 | 754 | ||
| 794 | #define __chv_read(x) \ | 755 | #define __chv_read(x) \ |
| 795 | static u##x \ | 756 | static u##x \ |
| 796 | chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | 757 | chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ |
| 797 | unsigned fwengine = 0; \ | ||
| 798 | GEN6_READ_HEADER(x); \ | 758 | GEN6_READ_HEADER(x); \ |
| 799 | if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \ | 759 | if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \ |
| 800 | if (dev_priv->uncore.fw_rendercount == 0) \ | 760 | __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ |
| 801 | fwengine = FORCEWAKE_RENDER; \ | 761 | else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \ |
| 802 | } else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \ | 762 | __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ |
| 803 | if (dev_priv->uncore.fw_mediacount == 0) \ | 763 | else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \ |
| 804 | fwengine = FORCEWAKE_MEDIA; \ | 764 | __force_wake_get(dev_priv, \ |
| 805 | } else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \ | 765 | FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \ |
| 806 | if (dev_priv->uncore.fw_rendercount == 0) \ | ||
| 807 | fwengine |= FORCEWAKE_RENDER; \ | ||
| 808 | if (dev_priv->uncore.fw_mediacount == 0) \ | ||
| 809 | fwengine |= FORCEWAKE_MEDIA; \ | ||
| 810 | } \ | ||
| 811 | if (fwengine) \ | ||
| 812 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \ | ||
| 813 | val = __raw_i915_read##x(dev_priv, reg); \ | 766 | val = __raw_i915_read##x(dev_priv, reg); \ |
| 814 | if (fwengine) \ | ||
| 815 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \ | ||
| 816 | GEN6_READ_FOOTER; \ | 767 | GEN6_READ_FOOTER; \ |
| 817 | } | 768 | } |
| 818 | 769 | ||
| @@ -822,32 +773,21 @@ chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | |||
| 822 | #define __gen9_read(x) \ | 773 | #define __gen9_read(x) \ |
| 823 | static u##x \ | 774 | static u##x \ |
| 824 | gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ | 775 | gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ |
| 776 | unsigned fw_engine; \ | ||
| 825 | GEN6_READ_HEADER(x); \ | 777 | GEN6_READ_HEADER(x); \ |
| 826 | if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ | 778 | if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) \ |
| 827 | val = __raw_i915_read##x(dev_priv, reg); \ | 779 | fw_engine = 0; \ |
| 828 | } else { \ | 780 | else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \ |
| 829 | unsigned fwengine = 0; \ | 781 | fw_engine = FORCEWAKE_RENDER; \ |
| 830 | if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) { \ | 782 | else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \ |
| 831 | if (dev_priv->uncore.fw_rendercount == 0) \ | 783 | fw_engine = FORCEWAKE_MEDIA; \ |
| 832 | fwengine = FORCEWAKE_RENDER; \ | 784 | else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \ |
| 833 | } else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) { \ | 785 | fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ |
| 834 | if (dev_priv->uncore.fw_mediacount == 0) \ | 786 | else \ |
| 835 | fwengine = FORCEWAKE_MEDIA; \ | 787 | fw_engine = FORCEWAKE_BLITTER; \ |
| 836 | } else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) { \ | 788 | if (fw_engine) \ |
| 837 | if (dev_priv->uncore.fw_rendercount == 0) \ | 789 | __force_wake_get(dev_priv, fw_engine); \ |
| 838 | fwengine |= FORCEWAKE_RENDER; \ | 790 | val = __raw_i915_read##x(dev_priv, reg); \ |
| 839 | if (dev_priv->uncore.fw_mediacount == 0) \ | ||
| 840 | fwengine |= FORCEWAKE_MEDIA; \ | ||
| 841 | } else { \ | ||
| 842 | if (dev_priv->uncore.fw_blittercount == 0) \ | ||
| 843 | fwengine = FORCEWAKE_BLITTER; \ | ||
| 844 | } \ | ||
| 845 | if (fwengine) \ | ||
| 846 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \ | ||
| 847 | val = __raw_i915_read##x(dev_priv, reg); \ | ||
| 848 | if (fwengine) \ | ||
| 849 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \ | ||
| 850 | } \ | ||
| 851 | GEN6_READ_FOOTER; \ | 791 | GEN6_READ_FOOTER; \ |
| 852 | } | 792 | } |
| 853 | 793 | ||
| @@ -981,17 +921,9 @@ static void \ | |||
| 981 | gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ | 921 | gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ |
| 982 | GEN6_WRITE_HEADER; \ | 922 | GEN6_WRITE_HEADER; \ |
| 983 | hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ | 923 | hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ |
| 984 | if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) { \ | 924 | if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) \ |
| 985 | if (dev_priv->uncore.forcewake_count == 0) \ | 925 | __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ |
| 986 | dev_priv->uncore.funcs.force_wake_get(dev_priv, \ | 926 | __raw_i915_write##x(dev_priv, reg, val); \ |
| 987 | FORCEWAKE_ALL); \ | ||
| 988 | __raw_i915_write##x(dev_priv, reg, val); \ | ||
| 989 | if (dev_priv->uncore.forcewake_count == 0) \ | ||
| 990 | dev_priv->uncore.funcs.force_wake_put(dev_priv, \ | ||
| 991 | FORCEWAKE_ALL); \ | ||
| 992 | } else { \ | ||
| 993 | __raw_i915_write##x(dev_priv, reg, val); \ | ||
| 994 | } \ | ||
| 995 | hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ | 927 | hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ |
| 996 | hsw_unclaimed_reg_detect(dev_priv); \ | 928 | hsw_unclaimed_reg_detect(dev_priv); \ |
| 997 | GEN6_WRITE_FOOTER; \ | 929 | GEN6_WRITE_FOOTER; \ |
| @@ -1000,28 +932,17 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace | |||
| 1000 | #define __chv_write(x) \ | 932 | #define __chv_write(x) \ |
| 1001 | static void \ | 933 | static void \ |
| 1002 | chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ | 934 | chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ |
| 1003 | unsigned fwengine = 0; \ | ||
| 1004 | bool shadowed = is_gen8_shadowed(dev_priv, reg); \ | 935 | bool shadowed = is_gen8_shadowed(dev_priv, reg); \ |
| 1005 | GEN6_WRITE_HEADER; \ | 936 | GEN6_WRITE_HEADER; \ |
| 1006 | if (!shadowed) { \ | 937 | if (!shadowed) { \ |
| 1007 | if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \ | 938 | if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \ |
| 1008 | if (dev_priv->uncore.fw_rendercount == 0) \ | 939 | __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ |
| 1009 | fwengine = FORCEWAKE_RENDER; \ | 940 | else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \ |
| 1010 | } else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \ | 941 | __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ |
| 1011 | if (dev_priv->uncore.fw_mediacount == 0) \ | 942 | else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \ |
| 1012 | fwengine = FORCEWAKE_MEDIA; \ | 943 | __force_wake_get(dev_priv, FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \ |
| 1013 | } else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \ | ||
| 1014 | if (dev_priv->uncore.fw_rendercount == 0) \ | ||
| 1015 | fwengine |= FORCEWAKE_RENDER; \ | ||
| 1016 | if (dev_priv->uncore.fw_mediacount == 0) \ | ||
| 1017 | fwengine |= FORCEWAKE_MEDIA; \ | ||
| 1018 | } \ | ||
| 1019 | } \ | 944 | } \ |
| 1020 | if (fwengine) \ | ||
| 1021 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \ | ||
| 1022 | __raw_i915_write##x(dev_priv, reg, val); \ | 945 | __raw_i915_write##x(dev_priv, reg, val); \ |
| 1023 | if (fwengine) \ | ||
| 1024 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \ | ||
| 1025 | GEN6_WRITE_FOOTER; \ | 946 | GEN6_WRITE_FOOTER; \ |
| 1026 | } | 947 | } |
| 1027 | 948 | ||
| @@ -1052,35 +973,22 @@ static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg) | |||
| 1052 | static void \ | 973 | static void \ |
| 1053 | gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ | 974 | gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ |
| 1054 | bool trace) { \ | 975 | bool trace) { \ |
| 976 | unsigned fw_engine; \ | ||
| 1055 | GEN6_WRITE_HEADER; \ | 977 | GEN6_WRITE_HEADER; \ |
| 1056 | if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \ | 978 | if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \ |
| 1057 | is_gen9_shadowed(dev_priv, reg)) { \ | 979 | is_gen9_shadowed(dev_priv, reg)) \ |
| 1058 | __raw_i915_write##x(dev_priv, reg, val); \ | 980 | fw_engine = 0; \ |
| 1059 | } else { \ | 981 | else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \ |
| 1060 | unsigned fwengine = 0; \ | 982 | fw_engine = FORCEWAKE_RENDER; \ |
| 1061 | if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) { \ | 983 | else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \ |
| 1062 | if (dev_priv->uncore.fw_rendercount == 0) \ | 984 | fw_engine = FORCEWAKE_MEDIA; \ |
| 1063 | fwengine = FORCEWAKE_RENDER; \ | 985 | else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \ |
| 1064 | } else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) { \ | 986 | fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ |
| 1065 | if (dev_priv->uncore.fw_mediacount == 0) \ | 987 | else \ |
| 1066 | fwengine = FORCEWAKE_MEDIA; \ | 988 | fw_engine = FORCEWAKE_BLITTER; \ |
| 1067 | } else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) { \ | 989 | if (fw_engine) \ |
| 1068 | if (dev_priv->uncore.fw_rendercount == 0) \ | 990 | __force_wake_get(dev_priv, fw_engine); \ |
| 1069 | fwengine |= FORCEWAKE_RENDER; \ | 991 | __raw_i915_write##x(dev_priv, reg, val); \ |
| 1070 | if (dev_priv->uncore.fw_mediacount == 0) \ | ||
| 1071 | fwengine |= FORCEWAKE_MEDIA; \ | ||
| 1072 | } else { \ | ||
| 1073 | if (dev_priv->uncore.fw_blittercount == 0) \ | ||
| 1074 | fwengine = FORCEWAKE_BLITTER; \ | ||
| 1075 | } \ | ||
| 1076 | if (fwengine) \ | ||
| 1077 | dev_priv->uncore.funcs.force_wake_get(dev_priv, \ | ||
| 1078 | fwengine); \ | ||
| 1079 | __raw_i915_write##x(dev_priv, reg, val); \ | ||
| 1080 | if (fwengine) \ | ||
| 1081 | dev_priv->uncore.funcs.force_wake_put(dev_priv, \ | ||
| 1082 | fwengine); \ | ||
| 1083 | } \ | ||
| 1084 | GEN6_WRITE_FOOTER; \ | 992 | GEN6_WRITE_FOOTER; \ |
| 1085 | } | 993 | } |
| 1086 | 994 | ||
| @@ -1132,21 +1040,24 @@ do { \ | |||
| 1132 | void intel_uncore_init(struct drm_device *dev) | 1040 | void intel_uncore_init(struct drm_device *dev) |
| 1133 | { | 1041 | { |
| 1134 | struct drm_i915_private *dev_priv = dev->dev_private; | 1042 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1135 | 1043 | struct intel_uncore_forcewake_domain *domain; | |
| 1136 | setup_timer(&dev_priv->uncore.force_wake_timer, | 1044 | int i; |
| 1137 | gen6_force_wake_timer, (unsigned long)dev_priv); | ||
| 1138 | 1045 | ||
| 1139 | __intel_uncore_early_sanitize(dev, false); | 1046 | __intel_uncore_early_sanitize(dev, false); |
| 1140 | 1047 | ||
| 1141 | if (IS_GEN9(dev)) { | 1048 | if (IS_GEN9(dev)) { |
| 1142 | dev_priv->uncore.funcs.force_wake_get = __gen9_force_wake_get; | 1049 | dev_priv->uncore.funcs.force_wake_get = __gen9_force_wake_get; |
| 1143 | dev_priv->uncore.funcs.force_wake_put = __gen9_force_wake_put; | 1050 | dev_priv->uncore.funcs.force_wake_put = __gen9_force_wake_put; |
| 1051 | dev_priv->uncore.fw_domains = FORCEWAKE_RENDER | | ||
| 1052 | FORCEWAKE_BLITTER | FORCEWAKE_MEDIA; | ||
| 1144 | } else if (IS_VALLEYVIEW(dev)) { | 1053 | } else if (IS_VALLEYVIEW(dev)) { |
| 1145 | dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; | 1054 | dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; |
| 1146 | dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; | 1055 | dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; |
| 1056 | dev_priv->uncore.fw_domains = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; | ||
| 1147 | } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 1057 | } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
| 1148 | dev_priv->uncore.funcs.force_wake_get = __gen7_gt_force_wake_mt_get; | 1058 | dev_priv->uncore.funcs.force_wake_get = __gen7_gt_force_wake_mt_get; |
| 1149 | dev_priv->uncore.funcs.force_wake_put = __gen7_gt_force_wake_mt_put; | 1059 | dev_priv->uncore.funcs.force_wake_put = __gen7_gt_force_wake_mt_put; |
| 1060 | dev_priv->uncore.fw_domains = FORCEWAKE_RENDER; | ||
| 1150 | } else if (IS_IVYBRIDGE(dev)) { | 1061 | } else if (IS_IVYBRIDGE(dev)) { |
| 1151 | u32 ecobus; | 1062 | u32 ecobus; |
| 1152 | 1063 | ||
| @@ -1178,11 +1089,21 @@ void intel_uncore_init(struct drm_device *dev) | |||
| 1178 | dev_priv->uncore.funcs.force_wake_put = | 1089 | dev_priv->uncore.funcs.force_wake_put = |
| 1179 | __gen6_gt_force_wake_put; | 1090 | __gen6_gt_force_wake_put; |
| 1180 | } | 1091 | } |
| 1092 | dev_priv->uncore.fw_domains = FORCEWAKE_RENDER; | ||
| 1181 | } else if (IS_GEN6(dev)) { | 1093 | } else if (IS_GEN6(dev)) { |
| 1182 | dev_priv->uncore.funcs.force_wake_get = | 1094 | dev_priv->uncore.funcs.force_wake_get = |
| 1183 | __gen6_gt_force_wake_get; | 1095 | __gen6_gt_force_wake_get; |
| 1184 | dev_priv->uncore.funcs.force_wake_put = | 1096 | dev_priv->uncore.funcs.force_wake_put = |
| 1185 | __gen6_gt_force_wake_put; | 1097 | __gen6_gt_force_wake_put; |
| 1098 | dev_priv->uncore.fw_domains = FORCEWAKE_RENDER; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | for_each_fw_domain(domain, dev_priv, i) { | ||
| 1102 | domain->i915 = dev_priv; | ||
| 1103 | domain->id = i; | ||
| 1104 | |||
| 1105 | setup_timer(&domain->timer, gen6_force_wake_timer, | ||
| 1106 | (unsigned long)domain); | ||
| 1186 | } | 1107 | } |
| 1187 | 1108 | ||
| 1188 | switch (INTEL_INFO(dev)->gen) { | 1109 | switch (INTEL_INFO(dev)->gen) { |
