diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 94 |
1 files changed, 60 insertions, 34 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a1103fc6597d..308f81913562 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -368,11 +368,12 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | |||
| 368 | */ | 368 | */ |
| 369 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | 369 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) |
| 370 | { | 370 | { |
| 371 | WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | 371 | unsigned long irqflags; |
| 372 | 372 | ||
| 373 | /* Forcewake is atomic in case we get in here without the lock */ | 373 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); |
| 374 | if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) | 374 | if (dev_priv->forcewake_count++ == 0) |
| 375 | dev_priv->display.force_wake_get(dev_priv); | 375 | dev_priv->display.force_wake_get(dev_priv); |
| 376 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 376 | } | 377 | } |
| 377 | 378 | ||
| 378 | void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | 379 | void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
| @@ -392,10 +393,12 @@ void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | |||
| 392 | */ | 393 | */ |
| 393 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | 394 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
| 394 | { | 395 | { |
| 395 | WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | 396 | unsigned long irqflags; |
| 396 | 397 | ||
| 397 | if (atomic_dec_and_test(&dev_priv->forcewake_count)) | 398 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); |
| 399 | if (--dev_priv->forcewake_count == 0) | ||
| 398 | dev_priv->display.force_wake_put(dev_priv); | 400 | dev_priv->display.force_wake_put(dev_priv); |
| 401 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 399 | } | 402 | } |
| 400 | 403 | ||
| 401 | void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | 404 | void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) |
| @@ -597,9 +600,36 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags) | |||
| 597 | static int gen6_do_reset(struct drm_device *dev, u8 flags) | 600 | static int gen6_do_reset(struct drm_device *dev, u8 flags) |
| 598 | { | 601 | { |
| 599 | struct drm_i915_private *dev_priv = dev->dev_private; | 602 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 603 | int ret; | ||
| 604 | unsigned long irqflags; | ||
| 600 | 605 | ||
| 601 | I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL); | 606 | /* Hold gt_lock across reset to prevent any register access |
| 602 | return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); | 607 | * with forcewake not set correctly |
| 608 | */ | ||
| 609 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 610 | |||
| 611 | /* Reset the chip */ | ||
| 612 | |||
| 613 | /* GEN6_GDRST is not in the gt power well, no need to check | ||
| 614 | * for fifo space for the write or forcewake the chip for | ||
| 615 | * the read | ||
| 616 | */ | ||
| 617 | I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL); | ||
| 618 | |||
| 619 | /* Spin waiting for the device to ack the reset request */ | ||
| 620 | ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); | ||
| 621 | |||
| 622 | /* If reset with a user forcewake, try to restore, otherwise turn it off */ | ||
| 623 | if (dev_priv->forcewake_count) | ||
| 624 | dev_priv->display.force_wake_get(dev_priv); | ||
| 625 | else | ||
| 626 | dev_priv->display.force_wake_put(dev_priv); | ||
| 627 | |||
| 628 | /* Restore fifo count */ | ||
| 629 | dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 630 | |||
| 631 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 632 | return ret; | ||
| 603 | } | 633 | } |
| 604 | 634 | ||
| 605 | /** | 635 | /** |
| @@ -643,9 +673,6 @@ int i915_reset(struct drm_device *dev, u8 flags) | |||
| 643 | case 7: | 673 | case 7: |
| 644 | case 6: | 674 | case 6: |
| 645 | ret = gen6_do_reset(dev, flags); | 675 | ret = gen6_do_reset(dev, flags); |
| 646 | /* If reset with a user forcewake, try to restore */ | ||
| 647 | if (atomic_read(&dev_priv->forcewake_count)) | ||
| 648 | __gen6_gt_force_wake_get(dev_priv); | ||
| 649 | break; | 676 | break; |
| 650 | case 5: | 677 | case 5: |
| 651 | ret = ironlake_do_reset(dev, flags); | 678 | ret = ironlake_do_reset(dev, flags); |
| @@ -810,6 +837,21 @@ static struct vm_operations_struct i915_gem_vm_ops = { | |||
| 810 | .close = drm_gem_vm_close, | 837 | .close = drm_gem_vm_close, |
| 811 | }; | 838 | }; |
| 812 | 839 | ||
| 840 | static const struct file_operations i915_driver_fops = { | ||
| 841 | .owner = THIS_MODULE, | ||
| 842 | .open = drm_open, | ||
| 843 | .release = drm_release, | ||
| 844 | .unlocked_ioctl = drm_ioctl, | ||
| 845 | .mmap = drm_gem_mmap, | ||
| 846 | .poll = drm_poll, | ||
| 847 | .fasync = drm_fasync, | ||
| 848 | .read = drm_read, | ||
| 849 | #ifdef CONFIG_COMPAT | ||
| 850 | .compat_ioctl = i915_compat_ioctl, | ||
| 851 | #endif | ||
| 852 | .llseek = noop_llseek, | ||
| 853 | }; | ||
| 854 | |||
| 813 | static struct drm_driver driver = { | 855 | static struct drm_driver driver = { |
| 814 | /* Don't use MTRRs here; the Xserver or userspace app should | 856 | /* Don't use MTRRs here; the Xserver or userspace app should |
| 815 | * deal with them for Intel hardware. | 857 | * deal with them for Intel hardware. |
| @@ -843,21 +885,7 @@ static struct drm_driver driver = { | |||
| 843 | .dumb_map_offset = i915_gem_mmap_gtt, | 885 | .dumb_map_offset = i915_gem_mmap_gtt, |
| 844 | .dumb_destroy = i915_gem_dumb_destroy, | 886 | .dumb_destroy = i915_gem_dumb_destroy, |
| 845 | .ioctls = i915_ioctls, | 887 | .ioctls = i915_ioctls, |
| 846 | .fops = { | 888 | .fops = &i915_driver_fops, |
| 847 | .owner = THIS_MODULE, | ||
| 848 | .open = drm_open, | ||
| 849 | .release = drm_release, | ||
| 850 | .unlocked_ioctl = drm_ioctl, | ||
| 851 | .mmap = drm_gem_mmap, | ||
| 852 | .poll = drm_poll, | ||
| 853 | .fasync = drm_fasync, | ||
| 854 | .read = drm_read, | ||
| 855 | #ifdef CONFIG_COMPAT | ||
| 856 | .compat_ioctl = i915_compat_ioctl, | ||
| 857 | #endif | ||
| 858 | .llseek = noop_llseek, | ||
| 859 | }, | ||
| 860 | |||
| 861 | .name = DRIVER_NAME, | 889 | .name = DRIVER_NAME, |
| 862 | .desc = DRIVER_DESC, | 890 | .desc = DRIVER_DESC, |
| 863 | .date = DRIVER_DATE, | 891 | .date = DRIVER_DATE, |
| @@ -922,20 +950,18 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
| 922 | MODULE_DESCRIPTION(DRIVER_DESC); | 950 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 923 | MODULE_LICENSE("GPL and additional rights"); | 951 | MODULE_LICENSE("GPL and additional rights"); |
| 924 | 952 | ||
| 925 | /* We give fast paths for the really cool registers */ | ||
| 926 | #define NEEDS_FORCE_WAKE(dev_priv, reg) \ | ||
| 927 | (((dev_priv)->info->gen >= 6) && \ | ||
| 928 | ((reg) < 0x40000) && \ | ||
| 929 | ((reg) != FORCEWAKE) && \ | ||
| 930 | ((reg) != ECOBUS)) | ||
| 931 | |||
| 932 | #define __i915_read(x, y) \ | 953 | #define __i915_read(x, y) \ |
| 933 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | 954 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ |
| 934 | u##x val = 0; \ | 955 | u##x val = 0; \ |
| 935 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ | 956 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ |
| 936 | gen6_gt_force_wake_get(dev_priv); \ | 957 | unsigned long irqflags; \ |
| 958 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ | ||
| 959 | if (dev_priv->forcewake_count == 0) \ | ||
| 960 | dev_priv->display.force_wake_get(dev_priv); \ | ||
| 937 | val = read##y(dev_priv->regs + reg); \ | 961 | val = read##y(dev_priv->regs + reg); \ |
| 938 | gen6_gt_force_wake_put(dev_priv); \ | 962 | if (dev_priv->forcewake_count == 0) \ |
| 963 | dev_priv->display.force_wake_put(dev_priv); \ | ||
| 964 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ | ||
| 939 | } else { \ | 965 | } else { \ |
| 940 | val = read##y(dev_priv->regs + reg); \ | 966 | val = read##y(dev_priv->regs + reg); \ |
| 941 | } \ | 967 | } \ |
