aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d92c92dea4ec..189041984aba 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -377,11 +377,12 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
377 */ 377 */
378void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) 378void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
379{ 379{
380 WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); 380 unsigned long irqflags;
381 381
382 /* Forcewake is atomic in case we get in here without the lock */ 382 spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
383 if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) 383 if (dev_priv->forcewake_count++ == 0)
384 dev_priv->display.force_wake_get(dev_priv); 384 dev_priv->display.force_wake_get(dev_priv);
385 spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
385} 386}
386 387
387void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) 388void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
@@ -401,10 +402,12 @@ void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
401 */ 402 */
402void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) 403void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
403{ 404{
404 WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); 405 unsigned long irqflags;
405 406
406 if (atomic_dec_and_test(&dev_priv->forcewake_count)) 407 spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
408 if (--dev_priv->forcewake_count == 0)
407 dev_priv->display.force_wake_put(dev_priv); 409 dev_priv->display.force_wake_put(dev_priv);
410 spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
408} 411}
409 412
410void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) 413void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@@ -606,9 +609,36 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags)
606static int gen6_do_reset(struct drm_device *dev, u8 flags) 609static int gen6_do_reset(struct drm_device *dev, u8 flags)
607{ 610{
608 struct drm_i915_private *dev_priv = dev->dev_private; 611 struct drm_i915_private *dev_priv = dev->dev_private;
612 int ret;
613 unsigned long irqflags;
609 614
610 I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL); 615 /* Hold gt_lock across reset to prevent any register access
611 return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); 616 * with forcewake not set correctly
617 */
618 spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
619
620 /* Reset the chip */
621
622 /* GEN6_GDRST is not in the gt power well, no need to check
623 * for fifo space for the write or forcewake the chip for
624 * the read
625 */
626 I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
627
628 /* Spin waiting for the device to ack the reset request */
629 ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
630
631 /* If reset with a user forcewake, try to restore, otherwise turn it off */
632 if (dev_priv->forcewake_count)
633 dev_priv->display.force_wake_get(dev_priv);
634 else
635 dev_priv->display.force_wake_put(dev_priv);
636
637 /* Restore fifo count */
638 dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
639
640 spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
641 return ret;
612} 642}
613 643
614/** 644/**
@@ -652,9 +682,6 @@ int i915_reset(struct drm_device *dev, u8 flags)
652 case 7: 682 case 7:
653 case 6: 683 case 6:
654 ret = gen6_do_reset(dev, flags); 684 ret = gen6_do_reset(dev, flags);
655 /* If reset with a user forcewake, try to restore */
656 if (atomic_read(&dev_priv->forcewake_count))
657 __gen6_gt_force_wake_get(dev_priv);
658 break; 685 break;
659 case 5: 686 case 5:
660 ret = ironlake_do_reset(dev, flags); 687 ret = ironlake_do_reset(dev, flags);
@@ -940,9 +967,14 @@ MODULE_LICENSE("GPL and additional rights");
940u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ 967u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
941 u##x val = 0; \ 968 u##x val = 0; \
942 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ 969 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
943 gen6_gt_force_wake_get(dev_priv); \ 970 unsigned long irqflags; \
971 spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
972 if (dev_priv->forcewake_count == 0) \
973 dev_priv->display.force_wake_get(dev_priv); \
944 val = read##y(dev_priv->regs + reg); \ 974 val = read##y(dev_priv->regs + reg); \
945 gen6_gt_force_wake_put(dev_priv); \ 975 if (dev_priv->forcewake_count == 0) \
976 dev_priv->display.force_wake_put(dev_priv); \
977 spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
946 } else { \ 978 } else { \
947 val = read##y(dev_priv->regs + reg); \ 979 val = read##y(dev_priv->regs + reg); \
948 } \ 980 } \