-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
linux-999-i915-Fix-random-GPU-hang-Bug-156851.patch
184 lines (172 loc) · 6.3 KB
/
linux-999-i915-Fix-random-GPU-hang-Bug-156851.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
From patchwork Thu Sep 15 07:27:32 2016
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: DRM: i915: Fix random GPU hang, Bug 156851
From: bobcao3 <bobcaocheng@163.com>
X-Patchwork-Id: 9332989
Message-Id: <20160915072732.11950-1-bobcaocheng@163.com>
To: Daniel Vetter <daniel.vetter@intel.com>,
Jani Nikula <jani.nikula@linux.intel.com>, David Airlie <airlied@linux.ie>
Cc: Cheng Cao <bobcaocheng@163.com>, intel-gfx@lists.freedesktop.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
Icenowy Zheng <icenowy@aosc.xyz>
Date: Thu, 15 Sep 2016 15:27:32 +0800
Signed-off-by: Cheng Cao <bobcaocheng@163.com>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++
drivers/gpu/drm/i915/i915_gem_stolen.c | 61 ++++++++++++++++-----------------
drivers/gpu/drm/i915/i915_reg.h | 6 ++++
drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++++++++++-
4 files changed, 60 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 7a30af7..0b05dd9 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2907,6 +2907,12 @@ static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
if (bdw_gmch_ctl > 4)
bdw_gmch_ctl = 4;
#endif
+#ifdef CONFIG_X86_64
+ /* Limit 64b platforms to a 4GB GGTT */
+ /* DMA 4GB protection */
+ if (bdw_gmch_ctl > 8)
+ bdw_gmch_ctl = 8;
+#endif
return bdw_gmch_ctl << 20;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 66be299a1..da272ae 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -352,47 +352,44 @@ static void gen8_get_stolen_reserved(struct drm_i915_private *dev_priv,
unsigned long *base, unsigned long *size)
{
uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
+ unsigned long stolen_top;
+ struct i915_ggtt *ggtt = &dev_priv->ggtt;
*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
case GEN8_STOLEN_RESERVED_1M:
- *size = 1024 * 1024;
+ *size = 1 << 10 << 10;
break;
case GEN8_STOLEN_RESERVED_2M:
- *size = 2 * 1024 * 1024;
+ *size = 2 << 10 << 10;
break;
case GEN8_STOLEN_RESERVED_4M:
- *size = 4 * 1024 * 1024;
+ *size = 4 << 10 << 10;
break;
case GEN8_STOLEN_RESERVED_8M:
- *size = 8 * 1024 * 1024;
+ *size = 8 << 10 << 10;
break;
default:
- *size = 8 * 1024 * 1024;
- MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
- }
-}
-
-static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
- unsigned long *base, unsigned long *size)
-{
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
- unsigned long stolen_top;
+ /* Whatever if it is a BDW device or SKL device
+ * Or others devices..
+ * This way is always going to work on 5th
+ * generation Intel Processer
+ */
+ stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
- stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
+ *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
- *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
+ /* MLIMIT - MBASE => PEG */
+ /* -- mobile-5th-gen-core-family-datasheet-vol-2.pdf */
+ if (*base == 0) {
+ *size = 0;
+ MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
+ } else
+ *size = stolen_top - *base;
- /* On these platforms, the register doesn't have a size field, so the
- * size is the distance between the base and the top of the stolen
- * memory. We also have the genuine case where base is zero and there's
- * nothing reserved. */
- if (*base == 0)
- *size = 0;
- else
- *size = stolen_top - *base;
+ break;
+ }
}
int i915_gem_init_stolen(struct drm_device *dev)
@@ -442,14 +439,14 @@ int i915_gem_init_stolen(struct drm_device *dev)
gen7_get_stolen_reserved(dev_priv, &reserved_base,
&reserved_size);
break;
+ case 8:
+ gen8_get_stolen_reserved(dev_priv, &reserved_base,
+ &reserved_size);
+ break;
default:
- if (IS_BROADWELL(dev_priv) ||
- IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
- bdw_get_stolen_reserved(dev_priv, &reserved_base,
- &reserved_size);
- else
- gen8_get_stolen_reserved(dev_priv, &reserved_base,
- &reserved_size);
+ // FIXME: This seemed like going to work
+ gen8_get_stolen_reserved(dev_priv, &reserved_base,
+ &reserved_size);
break;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index bf2cad3..3dce37b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1748,6 +1748,12 @@ enum skl_disp_power_wells {
#define RING_INDIRECT_CTX_OFFSET(base) _MMIO((base)+0x1c8) /* gen8+ */
#define RING_CTX_TIMESTAMP(base) _MMIO((base)+0x3a8) /* gen8+ */
+// 64 bit, low 32 preserved
+#define IOTLB_INVALID(base) _MMIO((base)+0x508 + 4) /* gen8+ */
+#define IOTLB_INVALID_IVT (1<<31)
+#define IOTLB_GLOBAL_INV_REQ (1<<28)
+#define IOTLB_INVALID_IAIG (1<<25)
+
#define ERROR_GEN6 _MMIO(0x40a0)
#define GEN7_ERR_INT _MMIO(0x44040)
#define ERR_INT_POISON (1<<31)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 1d3161b..84dafcb 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -498,7 +498,25 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
* arises: do we still need this and if so how should we go about
* invalidating the TLB?
*/
- if (IS_GEN(dev_priv, 6, 7)) {
+ /* Respond to this question:
+ * According to mobile-5th-gen-core-family-datasheet-vol-2 from Intel
+ * There are registers for invalidation, set those registers will
+ * cause the hardware to perform IOTLB invalidation.
+ */
+ if (IS_GEN8(dev_priv)) {
+ i915_reg_t reg = IOTLB_INVALID(engine->mmio_base);
+
+ /* ring should be idle before issuing a sync flush*/
+ WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
+
+ I915_WRITE(reg, 0x0 | IOTLB_INVALID_IVT | IOTLB_GLOBAL_INV_REQ);
+
+ if (intel_wait_for_register(dev_priv,
+ reg, IOTLB_INVALID_IAIG, 0,
+ 1000))
+ DRM_ERROR("%s: wait for TLB invalidation timed out\n",
+ engine->name);
+ } else if (IS_GEN(dev_priv, 6, 7)) {
i915_reg_t reg = RING_INSTPM(engine->mmio_base);
/* ring should be idle before issuing a sync flush*/