diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 89 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_sysfs.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 7 | ||||
-rw-r--r-- | include/uapi/drm/i915_drm.h | 8 |
7 files changed, 117 insertions, 61 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b16d47280f9..c6e8df737566 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -917,9 +917,11 @@ struct i915_ums_state { | |||
917 | int mm_suspended; | 917 | int mm_suspended; |
918 | }; | 918 | }; |
919 | 919 | ||
920 | #define MAX_L3_SLICES 2 | ||
920 | struct intel_l3_parity { | 921 | struct intel_l3_parity { |
921 | u32 *remap_info; | 922 | u32 *remap_info[MAX_L3_SLICES]; |
922 | struct work_struct error_work; | 923 | struct work_struct error_work; |
924 | int which_slice; | ||
923 | }; | 925 | }; |
924 | 926 | ||
925 | struct i915_gem_mm { | 927 | struct i915_gem_mm { |
@@ -1686,6 +1688,7 @@ struct drm_i915_file_private { | |||
1686 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) | 1688 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) |
1687 | 1689 | ||
1688 | #define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) | 1690 | #define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) |
1691 | #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_GPU_CACHE(dev)) | ||
1689 | 1692 | ||
1690 | #define GT_FREQUENCY_MULTIPLIER 50 | 1693 | #define GT_FREQUENCY_MULTIPLIER 50 |
1691 | 1694 | ||
@@ -1946,7 +1949,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); | |||
1946 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); | 1949 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); |
1947 | int __must_check i915_gem_init(struct drm_device *dev); | 1950 | int __must_check i915_gem_init(struct drm_device *dev); |
1948 | int __must_check i915_gem_init_hw(struct drm_device *dev); | 1951 | int __must_check i915_gem_init_hw(struct drm_device *dev); |
1949 | void i915_gem_l3_remap(struct drm_device *dev); | 1952 | void i915_gem_l3_remap(struct drm_device *dev, int slice); |
1950 | void i915_gem_init_swizzling(struct drm_device *dev); | 1953 | void i915_gem_init_swizzling(struct drm_device *dev); |
1951 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 1954 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
1952 | int __must_check i915_gpu_idle(struct drm_device *dev); | 1955 | int __must_check i915_gpu_idle(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d00d24f7a976..21a3d69679ee 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -4222,16 +4222,15 @@ i915_gem_idle(struct drm_device *dev) | |||
4222 | return 0; | 4222 | return 0; |
4223 | } | 4223 | } |
4224 | 4224 | ||
4225 | void i915_gem_l3_remap(struct drm_device *dev) | 4225 | void i915_gem_l3_remap(struct drm_device *dev, int slice) |
4226 | { | 4226 | { |
4227 | drm_i915_private_t *dev_priv = dev->dev_private; | 4227 | drm_i915_private_t *dev_priv = dev->dev_private; |
4228 | u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200); | ||
4229 | u32 *remap_info = dev_priv->l3_parity.remap_info[slice]; | ||
4228 | u32 misccpctl; | 4230 | u32 misccpctl; |
4229 | int i; | 4231 | int i; |
4230 | 4232 | ||
4231 | if (!HAS_L3_GPU_CACHE(dev)) | 4233 | if (!HAS_L3_GPU_CACHE(dev) || !remap_info) |
4232 | return; | ||
4233 | |||
4234 | if (!dev_priv->l3_parity.remap_info) | ||
4235 | return; | 4234 | return; |
4236 | 4235 | ||
4237 | misccpctl = I915_READ(GEN7_MISCCPCTL); | 4236 | misccpctl = I915_READ(GEN7_MISCCPCTL); |
@@ -4239,17 +4238,17 @@ void i915_gem_l3_remap(struct drm_device *dev) | |||
4239 | POSTING_READ(GEN7_MISCCPCTL); | 4238 | POSTING_READ(GEN7_MISCCPCTL); |
4240 | 4239 | ||
4241 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { | 4240 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { |
4242 | u32 remap = I915_READ(GEN7_L3LOG_BASE + i); | 4241 | u32 remap = I915_READ(reg_base + i); |
4243 | if (remap && remap != dev_priv->l3_parity.remap_info[i/4]) | 4242 | if (remap && remap != remap_info[i/4]) |
4244 | DRM_DEBUG("0x%x was already programmed to %x\n", | 4243 | DRM_DEBUG("0x%x was already programmed to %x\n", |
4245 | GEN7_L3LOG_BASE + i, remap); | 4244 | reg_base + i, remap); |
4246 | if (remap && !dev_priv->l3_parity.remap_info[i/4]) | 4245 | if (remap && !remap_info[i/4]) |
4247 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); | 4246 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); |
4248 | I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->l3_parity.remap_info[i/4]); | 4247 | I915_WRITE(reg_base + i, remap_info[i/4]); |
4249 | } | 4248 | } |
4250 | 4249 | ||
4251 | /* Make sure all the writes land before disabling dop clock gating */ | 4250 | /* Make sure all the writes land before disabling dop clock gating */ |
4252 | POSTING_READ(GEN7_L3LOG_BASE); | 4251 | POSTING_READ(reg_base); |
4253 | 4252 | ||
4254 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | 4253 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); |
4255 | } | 4254 | } |
@@ -4343,7 +4342,7 @@ int | |||
4343 | i915_gem_init_hw(struct drm_device *dev) | 4342 | i915_gem_init_hw(struct drm_device *dev) |
4344 | { | 4343 | { |
4345 | drm_i915_private_t *dev_priv = dev->dev_private; | 4344 | drm_i915_private_t *dev_priv = dev->dev_private; |
4346 | int ret; | 4345 | int ret, i; |
4347 | 4346 | ||
4348 | if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) | 4347 | if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) |
4349 | return -EIO; | 4348 | return -EIO; |
@@ -4362,7 +4361,8 @@ i915_gem_init_hw(struct drm_device *dev) | |||
4362 | I915_WRITE(GEN7_MSG_CTL, temp); | 4361 | I915_WRITE(GEN7_MSG_CTL, temp); |
4363 | } | 4362 | } |
4364 | 4363 | ||
4365 | i915_gem_l3_remap(dev); | 4364 | for (i = 0; i < NUM_L3_SLICES(dev); i++) |
4365 | i915_gem_l3_remap(dev, i); | ||
4366 | 4366 | ||
4367 | i915_gem_init_swizzling(dev); | 4367 | i915_gem_init_swizzling(dev); |
4368 | 4368 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a610f5abcc41..60a7bac4fc3b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -888,9 +888,10 @@ static void ivybridge_parity_work(struct work_struct *work) | |||
888 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | 888 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, |
889 | l3_parity.error_work); | 889 | l3_parity.error_work); |
890 | u32 error_status, row, bank, subbank; | 890 | u32 error_status, row, bank, subbank; |
891 | char *parity_event[5]; | 891 | char *parity_event[6]; |
892 | uint32_t misccpctl; | 892 | uint32_t misccpctl; |
893 | unsigned long flags; | 893 | unsigned long flags; |
894 | uint8_t slice = 0; | ||
894 | 895 | ||
895 | /* We must turn off DOP level clock gating to access the L3 registers. | 896 | /* We must turn off DOP level clock gating to access the L3 registers. |
896 | * In order to prevent a get/put style interface, acquire struct mutex | 897 | * In order to prevent a get/put style interface, acquire struct mutex |
@@ -898,45 +899,64 @@ static void ivybridge_parity_work(struct work_struct *work) | |||
898 | */ | 899 | */ |
899 | mutex_lock(&dev_priv->dev->struct_mutex); | 900 | mutex_lock(&dev_priv->dev->struct_mutex); |
900 | 901 | ||
902 | /* If we've screwed up tracking, just let the interrupt fire again */ | ||
903 | if (WARN_ON(!dev_priv->l3_parity.which_slice)) | ||
904 | goto out; | ||
905 | |||
901 | misccpctl = I915_READ(GEN7_MISCCPCTL); | 906 | misccpctl = I915_READ(GEN7_MISCCPCTL); |
902 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | 907 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); |
903 | POSTING_READ(GEN7_MISCCPCTL); | 908 | POSTING_READ(GEN7_MISCCPCTL); |
904 | 909 | ||
905 | error_status = I915_READ(GEN7_L3CDERRST1); | 910 | while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { |
906 | row = GEN7_PARITY_ERROR_ROW(error_status); | 911 | u32 reg; |
907 | bank = GEN7_PARITY_ERROR_BANK(error_status); | ||
908 | subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); | ||
909 | 912 | ||
910 | I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | | 913 | slice--; |
911 | GEN7_L3CDERRST1_ENABLE); | 914 | if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev))) |
912 | POSTING_READ(GEN7_L3CDERRST1); | 915 | break; |
913 | 916 | ||
914 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | 917 | dev_priv->l3_parity.which_slice &= ~(1<<slice); |
915 | 918 | ||
916 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 919 | reg = GEN7_L3CDERRST1 + (slice * 0x200); |
917 | ilk_enable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); | ||
918 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
919 | 920 | ||
920 | mutex_unlock(&dev_priv->dev->struct_mutex); | 921 | error_status = I915_READ(reg); |
922 | row = GEN7_PARITY_ERROR_ROW(error_status); | ||
923 | bank = GEN7_PARITY_ERROR_BANK(error_status); | ||
924 | subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); | ||
925 | |||
926 | I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); | ||
927 | POSTING_READ(reg); | ||
928 | |||
929 | parity_event[0] = I915_L3_PARITY_UEVENT "=1"; | ||
930 | parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); | ||
931 | parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); | ||
932 | parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); | ||
933 | parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); | ||
934 | parity_event[5] = NULL; | ||
935 | |||
936 | kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, | ||
937 | KOBJ_CHANGE, parity_event); | ||
921 | 938 | ||
922 | parity_event[0] = I915_L3_PARITY_UEVENT "=1"; | 939 | DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", |
923 | parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); | 940 | slice, row, bank, subbank); |
924 | parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); | ||
925 | parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); | ||
926 | parity_event[4] = NULL; | ||
927 | 941 | ||
928 | kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, | 942 | kfree(parity_event[4]); |
929 | KOBJ_CHANGE, parity_event); | 943 | kfree(parity_event[3]); |
944 | kfree(parity_event[2]); | ||
945 | kfree(parity_event[1]); | ||
946 | } | ||
930 | 947 | ||
931 | DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", | 948 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); |
932 | row, bank, subbank); | ||
933 | 949 | ||
934 | kfree(parity_event[3]); | 950 | out: |
935 | kfree(parity_event[2]); | 951 | WARN_ON(dev_priv->l3_parity.which_slice); |
936 | kfree(parity_event[1]); | 952 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
953 | ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev)); | ||
954 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
955 | |||
956 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
937 | } | 957 | } |
938 | 958 | ||
939 | static void ivybridge_parity_error_irq_handler(struct drm_device *dev) | 959 | static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir) |
940 | { | 960 | { |
941 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 961 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
942 | 962 | ||
@@ -944,9 +964,16 @@ static void ivybridge_parity_error_irq_handler(struct drm_device *dev) | |||
944 | return; | 964 | return; |
945 | 965 | ||
946 | spin_lock(&dev_priv->irq_lock); | 966 | spin_lock(&dev_priv->irq_lock); |
947 | ilk_disable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); | 967 | ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev)); |
948 | spin_unlock(&dev_priv->irq_lock); | 968 | spin_unlock(&dev_priv->irq_lock); |
949 | 969 | ||
970 | iir &= GT_PARITY_ERROR(dev); | ||
971 | if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1) | ||
972 | dev_priv->l3_parity.which_slice |= 1 << 1; | ||
973 | |||
974 | if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) | ||
975 | dev_priv->l3_parity.which_slice |= 1 << 0; | ||
976 | |||
950 | queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); | 977 | queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); |
951 | } | 978 | } |
952 | 979 | ||
@@ -981,8 +1008,8 @@ static void snb_gt_irq_handler(struct drm_device *dev, | |||
981 | i915_handle_error(dev, false); | 1008 | i915_handle_error(dev, false); |
982 | } | 1009 | } |
983 | 1010 | ||
984 | if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) | 1011 | if (gt_iir & GT_PARITY_ERROR(dev)) |
985 | ivybridge_parity_error_irq_handler(dev); | 1012 | ivybridge_parity_error_irq_handler(dev, gt_iir); |
986 | } | 1013 | } |
987 | 1014 | ||
988 | #define HPD_STORM_DETECT_PERIOD 1000 | 1015 | #define HPD_STORM_DETECT_PERIOD 1000 |
@@ -2221,8 +2248,8 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) | |||
2221 | dev_priv->gt_irq_mask = ~0; | 2248 | dev_priv->gt_irq_mask = ~0; |
2222 | if (HAS_L3_GPU_CACHE(dev)) { | 2249 | if (HAS_L3_GPU_CACHE(dev)) { |
2223 | /* L3 parity interrupt is always unmasked. */ | 2250 | /* L3 parity interrupt is always unmasked. */ |
2224 | dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT; | 2251 | dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev); |
2225 | gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; | 2252 | gt_irqs |= GT_PARITY_ERROR(dev); |
2226 | } | 2253 | } |
2227 | 2254 | ||
2228 | gt_irqs |= GT_RENDER_USER_INTERRUPT; | 2255 | gt_irqs |= GT_RENDER_USER_INTERRUPT; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index af6f93ca7296..c4f9bef6d073 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -927,6 +927,7 @@ | |||
927 | #define GT_BLT_USER_INTERRUPT (1 << 22) | 927 | #define GT_BLT_USER_INTERRUPT (1 << 22) |
928 | #define GT_BSD_CS_ERROR_INTERRUPT (1 << 15) | 928 | #define GT_BSD_CS_ERROR_INTERRUPT (1 << 15) |
929 | #define GT_BSD_USER_INTERRUPT (1 << 12) | 929 | #define GT_BSD_USER_INTERRUPT (1 << 12) |
930 | #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */ | ||
930 | #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */ | 931 | #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */ |
931 | #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4) | 932 | #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4) |
932 | #define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3) | 933 | #define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3) |
@@ -937,6 +938,10 @@ | |||
937 | #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ | 938 | #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ |
938 | #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ | 939 | #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ |
939 | 940 | ||
941 | #define GT_PARITY_ERROR(dev) \ | ||
942 | (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ | ||
943 | IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0) | ||
944 | |||
940 | /* These are all the "old" interrupts */ | 945 | /* These are all the "old" interrupts */ |
941 | #define ILK_BSD_USER_INTERRUPT (1<<5) | 946 | #define ILK_BSD_USER_INTERRUPT (1<<5) |
942 | #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) | 947 | #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) |
@@ -4747,6 +4752,7 @@ | |||
4747 | 4752 | ||
4748 | /* IVYBRIDGE DPF */ | 4753 | /* IVYBRIDGE DPF */ |
4749 | #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ | 4754 | #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ |
4755 | #define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */ | ||
4750 | #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) | 4756 | #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) |
4751 | #define GEN7_PARITY_ERROR_VALID (1<<13) | 4757 | #define GEN7_PARITY_ERROR_VALID (1<<13) |
4752 | #define GEN7_L3CDERRST1_BANK_MASK (3<<11) | 4758 | #define GEN7_L3CDERRST1_BANK_MASK (3<<11) |
@@ -4760,6 +4766,7 @@ | |||
4760 | #define GEN7_L3CDERRST1_ENABLE (1<<7) | 4766 | #define GEN7_L3CDERRST1_ENABLE (1<<7) |
4761 | 4767 | ||
4762 | #define GEN7_L3LOG_BASE 0xB070 | 4768 | #define GEN7_L3LOG_BASE 0xB070 |
4769 | #define HSW_L3LOG_BASE_SLICE1 0xB270 | ||
4763 | #define GEN7_L3LOG_SIZE 0x80 | 4770 | #define GEN7_L3LOG_SIZE 0x80 |
4764 | 4771 | ||
4765 | #define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ | 4772 | #define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 71f6de24444e..3a8bf0c9b5ce 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
@@ -119,6 +119,7 @@ i915_l3_read(struct file *filp, struct kobject *kobj, | |||
119 | struct drm_device *drm_dev = dminor->dev; | 119 | struct drm_device *drm_dev = dminor->dev; |
120 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | 120 | struct drm_i915_private *dev_priv = drm_dev->dev_private; |
121 | uint32_t misccpctl; | 121 | uint32_t misccpctl; |
122 | int slice = (int)(uintptr_t)attr->private; | ||
122 | int i, ret; | 123 | int i, ret; |
123 | 124 | ||
124 | count = round_down(count, 4); | 125 | count = round_down(count, 4); |
@@ -134,9 +135,9 @@ i915_l3_read(struct file *filp, struct kobject *kobj, | |||
134 | return ret; | 135 | return ret; |
135 | 136 | ||
136 | if (IS_HASWELL(drm_dev)) { | 137 | if (IS_HASWELL(drm_dev)) { |
137 | if (dev_priv->l3_parity.remap_info) | 138 | if (dev_priv->l3_parity.remap_info[slice]) |
138 | memcpy(buf, | 139 | memcpy(buf, |
139 | dev_priv->l3_parity.remap_info + (offset/4), | 140 | dev_priv->l3_parity.remap_info[slice] + (offset/4), |
140 | count); | 141 | count); |
141 | else | 142 | else |
142 | memset(buf, 0, count); | 143 | memset(buf, 0, count); |
@@ -168,6 +169,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
168 | struct drm_device *drm_dev = dminor->dev; | 169 | struct drm_device *drm_dev = dminor->dev; |
169 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | 170 | struct drm_i915_private *dev_priv = drm_dev->dev_private; |
170 | u32 *temp = NULL; /* Just here to make handling failures easy */ | 171 | u32 *temp = NULL; /* Just here to make handling failures easy */ |
172 | int slice = (int)(uintptr_t)attr->private; | ||
171 | int ret; | 173 | int ret; |
172 | 174 | ||
173 | ret = l3_access_valid(drm_dev, offset); | 175 | ret = l3_access_valid(drm_dev, offset); |
@@ -178,7 +180,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
178 | if (ret) | 180 | if (ret) |
179 | return ret; | 181 | return ret; |
180 | 182 | ||
181 | if (!dev_priv->l3_parity.remap_info) { | 183 | if (!dev_priv->l3_parity.remap_info[slice]) { |
182 | temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); | 184 | temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); |
183 | if (!temp) { | 185 | if (!temp) { |
184 | mutex_unlock(&drm_dev->struct_mutex); | 186 | mutex_unlock(&drm_dev->struct_mutex); |
@@ -198,11 +200,11 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
198 | * at this point it is left as a TODO. | 200 | * at this point it is left as a TODO. |
199 | */ | 201 | */ |
200 | if (temp) | 202 | if (temp) |
201 | dev_priv->l3_parity.remap_info = temp; | 203 | dev_priv->l3_parity.remap_info[slice] = temp; |
202 | 204 | ||
203 | memcpy(dev_priv->l3_parity.remap_info + (offset/4), buf, count); | 205 | memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); |
204 | 206 | ||
205 | i915_gem_l3_remap(drm_dev); | 207 | i915_gem_l3_remap(drm_dev, slice); |
206 | 208 | ||
207 | mutex_unlock(&drm_dev->struct_mutex); | 209 | mutex_unlock(&drm_dev->struct_mutex); |
208 | 210 | ||
@@ -214,7 +216,17 @@ static struct bin_attribute dpf_attrs = { | |||
214 | .size = GEN7_L3LOG_SIZE, | 216 | .size = GEN7_L3LOG_SIZE, |
215 | .read = i915_l3_read, | 217 | .read = i915_l3_read, |
216 | .write = i915_l3_write, | 218 | .write = i915_l3_write, |
217 | .mmap = NULL | 219 | .mmap = NULL, |
220 | .private = (void *)0 | ||
221 | }; | ||
222 | |||
223 | static struct bin_attribute dpf_attrs_1 = { | ||
224 | .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)}, | ||
225 | .size = GEN7_L3LOG_SIZE, | ||
226 | .read = i915_l3_read, | ||
227 | .write = i915_l3_write, | ||
228 | .mmap = NULL, | ||
229 | .private = (void *)1 | ||
218 | }; | 230 | }; |
219 | 231 | ||
220 | static ssize_t gt_cur_freq_mhz_show(struct device *kdev, | 232 | static ssize_t gt_cur_freq_mhz_show(struct device *kdev, |
@@ -525,6 +537,13 @@ void i915_setup_sysfs(struct drm_device *dev) | |||
525 | ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); | 537 | ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); |
526 | if (ret) | 538 | if (ret) |
527 | DRM_ERROR("l3 parity sysfs setup failed\n"); | 539 | DRM_ERROR("l3 parity sysfs setup failed\n"); |
540 | |||
541 | if (NUM_L3_SLICES(dev) > 1) { | ||
542 | ret = device_create_bin_file(&dev->primary->kdev, | ||
543 | &dpf_attrs_1); | ||
544 | if (ret) | ||
545 | DRM_ERROR("l3 parity slice 1 setup failed\n"); | ||
546 | } | ||
528 | } | 547 | } |
529 | 548 | ||
530 | ret = 0; | 549 | ret = 0; |
@@ -548,6 +567,7 @@ void i915_teardown_sysfs(struct drm_device *dev) | |||
548 | sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs); | 567 | sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs); |
549 | else | 568 | else |
550 | sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs); | 569 | sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs); |
570 | device_remove_bin_file(&dev->primary->kdev, &dpf_attrs_1); | ||
551 | device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); | 571 | device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); |
552 | #ifdef CONFIG_PM | 572 | #ifdef CONFIG_PM |
553 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); | 573 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 686e5b23481d..958b7d8fea8b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -570,7 +570,7 @@ static int init_render_ring(struct intel_ring_buffer *ring) | |||
570 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); | 570 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); |
571 | 571 | ||
572 | if (HAS_L3_GPU_CACHE(dev)) | 572 | if (HAS_L3_GPU_CACHE(dev)) |
573 | I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); | 573 | I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); |
574 | 574 | ||
575 | return ret; | 575 | return ret; |
576 | } | 576 | } |
@@ -1000,7 +1000,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) | |||
1000 | if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) | 1000 | if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) |
1001 | I915_WRITE_IMR(ring, | 1001 | I915_WRITE_IMR(ring, |
1002 | ~(ring->irq_enable_mask | | 1002 | ~(ring->irq_enable_mask | |
1003 | GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); | 1003 | GT_PARITY_ERROR(dev))); |
1004 | else | 1004 | else |
1005 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); | 1005 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); |
1006 | ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); | 1006 | ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); |
@@ -1020,8 +1020,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) | |||
1020 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 1020 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1021 | if (--ring->irq_refcount == 0) { | 1021 | if (--ring->irq_refcount == 0) { |
1022 | if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) | 1022 | if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) |
1023 | I915_WRITE_IMR(ring, | 1023 | I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); |
1024 | ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); | ||
1025 | else | 1024 | else |
1026 | I915_WRITE_IMR(ring, ~0); | 1025 | I915_WRITE_IMR(ring, ~0); |
1027 | ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); | 1026 | ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); |
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 55bb5729bd78..3a4e97bd8607 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h | |||
@@ -38,10 +38,10 @@ | |||
38 | * | 38 | * |
39 | * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch | 39 | * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch |
40 | * event from the gpu l3 cache. Additional information supplied is ROW, | 40 | * event from the gpu l3 cache. Additional information supplied is ROW, |
41 | * BANK, SUBBANK of the affected cacheline. Userspace should keep track of | 41 | * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep |
42 | * these events and if a specific cache-line seems to have a persistent | 42 | * track of these events and if a specific cache-line seems to have a |
43 | * error remap it with the l3 remapping tool supplied in intel-gpu-tools. | 43 | * persistent error remap it with the l3 remapping tool supplied in |
44 | * The value supplied with the event is always 1. | 44 | * intel-gpu-tools. The value supplied with the event is always 1. |
45 | * | 45 | * |
46 | * I915_ERROR_UEVENT - Generated upon error detection, currently only via | 46 | * I915_ERROR_UEVENT - Generated upon error detection, currently only via |
47 | * hangcheck. The error detection event is a good indicator of when things | 47 | * hangcheck. The error detection event is a good indicator of when things |