diff options
author | Dave Airlie <airlied@redhat.com> | 2018-05-03 20:31:10 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-05-03 20:32:21 -0400 |
commit | 8eb008c80841e3410ef2c043093478ea36bb5ff1 (patch) | |
tree | 82498a129afd515046e53b92d916e4dbc83d449e | |
parent | 0ab390262c4920f26f8202063a268d5fc829728e (diff) | |
parent | fadec6eefe232696c5c471b40df33e6db616e854 (diff) |
Merge tag 'drm-intel-next-2018-04-13' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
First drm/i915 feature batch heading for v4.18:
- drm-next backmerge to fix build (Rodrigo)
- GPU documentation improvements (Kevin)
- GuC and HuC refactoring, host/GuC communication, logging, fixes, and more
(mostly Michal and Michał, also Jackie, Michel and Piotr)
- PSR and PSR2 enabling and fixes (DK, José, Rodrigo and Chris)
- Selftest updates (Chris, Daniele)
- DPLL management refactoring (Lucas)
- DP MST fixes (Lyude and DK)
- Watermark refactoring and changes to support NV12 (Mahesh)
- NV12 prep work (Chandra)
- Icelake Combo PHY enablers (Manasi)
- Perf OA refactoring and ICL enabling (Lionel)
- ICL enabling (Oscar, Paulo, Nabendu, Mika, Kelvin, Michel)
- Workarounds refactoring (Oscar)
- HDCP fixes and improvements (Ramalingam, Radhakrishna)
- Power management fixes (Imre)
- Various display fixes (Maarten, Ville, Vidya, Jani, Gaurav)
- debugfs for FIFO underrun clearing (Maarten)
- Execlist improvements (Chris)
- Reset improvements (Chris)
- Plenty of things here and there I overlooked and/or didn't understand... (Everyone)
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87lgd2cze8.fsf@intel.com
87 files changed, 7246 insertions, 3711 deletions
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 41dc881b00dc..055df45596c1 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst | |||
@@ -58,6 +58,12 @@ Intel GVT-g Host Support(vGPU device model) | |||
58 | .. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c | 58 | .. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c |
59 | :internal: | 59 | :internal: |
60 | 60 | ||
61 | Workarounds | ||
62 | ----------- | ||
63 | |||
64 | .. kernel-doc:: drivers/gpu/drm/i915/intel_workarounds.c | ||
65 | :doc: Hardware workarounds | ||
66 | |||
61 | Display Hardware Handling | 67 | Display Hardware Handling |
62 | ========================= | 68 | ========================= |
63 | 69 | ||
@@ -249,6 +255,103 @@ Memory Management and Command Submission | |||
249 | This sections covers all things related to the GEM implementation in the | 255 | This sections covers all things related to the GEM implementation in the |
250 | i915 driver. | 256 | i915 driver. |
251 | 257 | ||
258 | Intel GPU Basics | ||
259 | ---------------- | ||
260 | |||
261 | An Intel GPU has multiple engines. There are several engine types. | ||
262 | |||
263 | - RCS engine is for rendering 3D and performing compute, this is named | ||
264 | `I915_EXEC_RENDER` in user space. | ||
265 | - BCS is a blitting (copy) engine, this is named `I915_EXEC_BLT` in user | ||
266 | space. | ||
267 | - VCS is a video encode and decode engine, this is named `I915_EXEC_BSD` | ||
268 | in user space | ||
269 | - VECS is video enhancement engine, this is named `I915_EXEC_VEBOX` in user | ||
270 | space. | ||
271 | - The enumeration `I915_EXEC_DEFAULT` does not refer to specific engine; | ||
272 | instead it is to be used by user space to specify a default rendering | ||
273 | engine (for 3D) that may or may not be the same as RCS. | ||
274 | |||
275 | The Intel GPU family is a family of integrated GPU's using Unified | ||
276 | Memory Access. For having the GPU "do work", user space will feed the | ||
277 | GPU batch buffers via one of the ioctls `DRM_IOCTL_I915_GEM_EXECBUFFER2` | ||
278 | or `DRM_IOCTL_I915_GEM_EXECBUFFER2_WR`. Most such batchbuffers will | ||
279 | instruct the GPU to perform work (for example rendering) and that work | ||
280 | needs memory from which to read and memory to which to write. All memory | ||
281 | is encapsulated within GEM buffer objects (usually created with the ioctl | ||
282 | `DRM_IOCTL_I915_GEM_CREATE`). An ioctl providing a batchbuffer for the GPU | ||
283 | to create will also list all GEM buffer objects that the batchbuffer reads | ||
284 | and/or writes. For implementation details of memory management see | ||
285 | `GEM BO Management Implementation Details`_. | ||
286 | |||
287 | The i915 driver allows user space to create a context via the ioctl | ||
288 | `DRM_IOCTL_I915_GEM_CONTEXT_CREATE` which is identified by a 32-bit | ||
289 | integer. Such a context should be viewed by user-space as -loosely- | ||
290 | analogous to the idea of a CPU process of an operating system. The i915 | ||
291 | driver guarantees that commands issued to a fixed context are to be | ||
292 | executed so that writes of a previously issued command are seen by | ||
293 | reads of following commands. Actions issued between different contexts | ||
294 | (even if from the same file descriptor) are NOT given that guarantee | ||
295 | and the only way to synchronize across contexts (even from the same | ||
296 | file descriptor) is through the use of fences. At least as far back as | ||
297 | Gen4, also have that a context carries with it a GPU HW context; | ||
298 | the HW context is essentially (most of atleast) the state of a GPU. | ||
299 | In addition to the ordering guarantees, the kernel will restore GPU | ||
300 | state via HW context when commands are issued to a context, this saves | ||
301 | user space the need to restore (most of atleast) the GPU state at the | ||
302 | start of each batchbuffer. The non-deprecated ioctls to submit batchbuffer | ||
303 | work can pass that ID (in the lower bits of drm_i915_gem_execbuffer2::rsvd1) | ||
304 | to identify what context to use with the command. | ||
305 | |||
306 | The GPU has its own memory management and address space. The kernel | ||
307 | driver maintains the memory translation table for the GPU. For older | ||
308 | GPUs (i.e. those before Gen8), there is a single global such translation | ||
309 | table, a global Graphics Translation Table (GTT). For newer generation | ||
310 | GPUs each context has its own translation table, called Per-Process | ||
311 | Graphics Translation Table (PPGTT). Of important note, is that although | ||
312 | PPGTT is named per-process it is actually per context. When user space | ||
313 | submits a batchbuffer, the kernel walks the list of GEM buffer objects | ||
314 | used by the batchbuffer and guarantees that not only is the memory of | ||
315 | each such GEM buffer object resident but it is also present in the | ||
316 | (PP)GTT. If the GEM buffer object is not yet placed in the (PP)GTT, | ||
317 | then it is given an address. Two consequences of this are: the kernel | ||
318 | needs to edit the batchbuffer submitted to write the correct value of | ||
319 | the GPU address when a GEM BO is assigned a GPU address and the kernel | ||
320 | might evict a different GEM BO from the (PP)GTT to make address room | ||
321 | for another GEM BO. Consequently, the ioctls submitting a batchbuffer | ||
322 | for execution also include a list of all locations within buffers that | ||
323 | refer to GPU-addresses so that the kernel can edit the buffer correctly. | ||
324 | This process is dubbed relocation. | ||
325 | |||
326 | GEM BO Management Implementation Details | ||
327 | ---------------------------------------- | ||
328 | |||
329 | .. kernel-doc:: drivers/gpu/drm/i915/i915_vma.h | ||
330 | :doc: Virtual Memory Address | ||
331 | |||
332 | Buffer Object Eviction | ||
333 | ---------------------- | ||
334 | |||
335 | This section documents the interface functions for evicting buffer | ||
336 | objects to make space available in the virtual gpu address spaces. Note | ||
337 | that this is mostly orthogonal to shrinking buffer objects caches, which | ||
338 | has the goal to make main memory (shared with the gpu through the | ||
339 | unified memory architecture) available. | ||
340 | |||
341 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_evict.c | ||
342 | :internal: | ||
343 | |||
344 | Buffer Object Memory Shrinking | ||
345 | ------------------------------ | ||
346 | |||
347 | This section documents the interface function for shrinking memory usage | ||
348 | of buffer object caches. Shrinking is used to make main memory | ||
349 | available. Note that this is mostly orthogonal to evicting buffer | ||
350 | objects, which has the goal to make space in gpu virtual address spaces. | ||
351 | |||
352 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_shrinker.c | ||
353 | :internal: | ||
354 | |||
252 | Batchbuffer Parsing | 355 | Batchbuffer Parsing |
253 | ------------------- | 356 | ------------------- |
254 | 357 | ||
@@ -267,6 +370,12 @@ Batchbuffer Pools | |||
267 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_batch_pool.c | 370 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_batch_pool.c |
268 | :internal: | 371 | :internal: |
269 | 372 | ||
373 | User Batchbuffer Execution | ||
374 | -------------------------- | ||
375 | |||
376 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_execbuffer.c | ||
377 | :doc: User command execution | ||
378 | |||
270 | Logical Rings, Logical Ring Contexts and Execlists | 379 | Logical Rings, Logical Ring Contexts and Execlists |
271 | -------------------------------------------------- | 380 | -------------------------------------------------- |
272 | 381 | ||
@@ -312,28 +421,14 @@ Object Tiling IOCTLs | |||
312 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_tiling.c | 421 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_tiling.c |
313 | :doc: buffer object tiling | 422 | :doc: buffer object tiling |
314 | 423 | ||
315 | Buffer Object Eviction | 424 | WOPCM |
316 | ---------------------- | 425 | ===== |
317 | |||
318 | This section documents the interface functions for evicting buffer | ||
319 | objects to make space available in the virtual gpu address spaces. Note | ||
320 | that this is mostly orthogonal to shrinking buffer objects caches, which | ||
321 | has the goal to make main memory (shared with the gpu through the | ||
322 | unified memory architecture) available. | ||
323 | |||
324 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_evict.c | ||
325 | :internal: | ||
326 | |||
327 | Buffer Object Memory Shrinking | ||
328 | ------------------------------ | ||
329 | 426 | ||
330 | This section documents the interface function for shrinking memory usage | 427 | WOPCM Layout |
331 | of buffer object caches. Shrinking is used to make main memory | 428 | ------------ |
332 | available. Note that this is mostly orthogonal to evicting buffer | ||
333 | objects, which has the goal to make space in gpu virtual address spaces. | ||
334 | 429 | ||
335 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_shrinker.c | 430 | .. kernel-doc:: drivers/gpu/drm/i915/intel_wopcm.c |
336 | :internal: | 431 | :doc: WOPCM Layout |
337 | 432 | ||
338 | GuC | 433 | GuC |
339 | === | 434 | === |
@@ -359,6 +454,12 @@ GuC Firmware Layout | |||
359 | .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_fwif.h | 454 | .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_fwif.h |
360 | :doc: GuC Firmware Layout | 455 | :doc: GuC Firmware Layout |
361 | 456 | ||
457 | GuC Address Space | ||
458 | ----------------- | ||
459 | |||
460 | .. kernel-doc:: drivers/gpu/drm/i915/intel_guc.c | ||
461 | :doc: GuC Address Space | ||
462 | |||
362 | Tracing | 463 | Tracing |
363 | ======= | 464 | ======= |
364 | 465 | ||
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 108d21f34777..80efee1ff7f3 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug | |||
@@ -25,6 +25,7 @@ config DRM_I915_DEBUG | |||
25 | select X86_MSR # used by igt/pm_rpm | 25 | select X86_MSR # used by igt/pm_rpm |
26 | select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) | 26 | select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) |
27 | select DRM_DEBUG_MM if DRM=y | 27 | select DRM_DEBUG_MM if DRM=y |
28 | select STACKDEPOT if DRM=y # for DRM_DEBUG_MM | ||
28 | select DRM_DEBUG_MM_SELFTEST | 29 | select DRM_DEBUG_MM_SELFTEST |
29 | select SW_SYNC # signaling validation framework (igt/syncobj*) | 30 | select SW_SYNC # signaling validation framework (igt/syncobj*) |
30 | select DRM_I915_SW_FENCE_DEBUG_OBJECTS | 31 | select DRM_I915_SW_FENCE_DEBUG_OBJECTS |
@@ -89,6 +90,18 @@ config DRM_I915_SW_FENCE_CHECK_DAG | |||
89 | 90 | ||
90 | If in doubt, say "N". | 91 | If in doubt, say "N". |
91 | 92 | ||
93 | config DRM_I915_DEBUG_GUC | ||
94 | bool "Enable additional driver debugging for GuC" | ||
95 | depends on DRM_I915 | ||
96 | default n | ||
97 | help | ||
98 | Choose this option to turn on extra driver debugging that may affect | ||
99 | performance but will help resolve GuC related issues. | ||
100 | |||
101 | Recommended for driver developers only. | ||
102 | |||
103 | If in doubt, say "N". | ||
104 | |||
92 | config DRM_I915_SELFTEST | 105 | config DRM_I915_SELFTEST |
93 | bool "Enable selftests upon driver load" | 106 | bool "Enable selftests upon driver load" |
94 | depends on DRM_I915 | 107 | depends on DRM_I915 |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4eee91a3a236..9bee52a949a9 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -12,7 +12,7 @@ | |||
12 | # Note the danger in using -Wall -Wextra is that when CI updates gcc we | 12 | # Note the danger in using -Wall -Wextra is that when CI updates gcc we |
13 | # will most likely get a sudden build breakage... Hopefully we will fix | 13 | # will most likely get a sudden build breakage... Hopefully we will fix |
14 | # new warnings before CI updates! | 14 | # new warnings before CI updates! |
15 | subdir-ccflags-y := -Wall -Wextra | 15 | subdir-ccflags-y := -Wall -Wextra -Wvla |
16 | subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) | 16 | subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) |
17 | subdir-ccflags-y += $(call cc-disable-warning, type-limits) | 17 | subdir-ccflags-y += $(call cc-disable-warning, type-limits) |
18 | subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) | 18 | subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) |
@@ -43,7 +43,8 @@ i915-y := i915_drv.o \ | |||
43 | intel_csr.o \ | 43 | intel_csr.o \ |
44 | intel_device_info.o \ | 44 | intel_device_info.o \ |
45 | intel_pm.o \ | 45 | intel_pm.o \ |
46 | intel_runtime_pm.o | 46 | intel_runtime_pm.o \ |
47 | intel_workarounds.o | ||
47 | 48 | ||
48 | i915-$(CONFIG_COMPAT) += i915_ioc32.o | 49 | i915-$(CONFIG_COMPAT) += i915_ioc32.o |
49 | i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o | 50 | i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o |
@@ -79,7 +80,8 @@ i915-y += i915_cmd_parser.o \ | |||
79 | intel_lrc.o \ | 80 | intel_lrc.o \ |
80 | intel_mocs.o \ | 81 | intel_mocs.o \ |
81 | intel_ringbuffer.o \ | 82 | intel_ringbuffer.o \ |
82 | intel_uncore.o | 83 | intel_uncore.o \ |
84 | intel_wopcm.o | ||
83 | 85 | ||
84 | # general-purpose microcontroller (GuC) support | 86 | # general-purpose microcontroller (GuC) support |
85 | i915-y += intel_uc.o \ | 87 | i915-y += intel_uc.o \ |
@@ -171,7 +173,8 @@ i915-y += i915_perf.o \ | |||
171 | i915_oa_glk.o \ | 173 | i915_oa_glk.o \ |
172 | i915_oa_cflgt2.o \ | 174 | i915_oa_cflgt2.o \ |
173 | i915_oa_cflgt3.o \ | 175 | i915_oa_cflgt3.o \ |
174 | i915_oa_cnl.o | 176 | i915_oa_cnl.o \ |
177 | i915_oa_icl.o | ||
175 | 178 | ||
176 | ifeq ($(CONFIG_DRM_I915_GVT),y) | 179 | ifeq ($(CONFIG_DRM_I915_GVT),y) |
177 | i915-y += intel_gvt.o | 180 | i915-y += intel_gvt.o |
diff --git a/drivers/gpu/drm/i915/gvt/debugfs.c b/drivers/gpu/drm/i915/gvt/debugfs.c index 32a66dfdf112..f7d0078eb61b 100644 --- a/drivers/gpu/drm/i915/gvt/debugfs.c +++ b/drivers/gpu/drm/i915/gvt/debugfs.c | |||
@@ -122,18 +122,7 @@ static int vgpu_mmio_diff_show(struct seq_file *s, void *unused) | |||
122 | seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff); | 122 | seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff); |
123 | return 0; | 123 | return 0; |
124 | } | 124 | } |
125 | 125 | DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff); | |
126 | static int vgpu_mmio_diff_open(struct inode *inode, struct file *file) | ||
127 | { | ||
128 | return single_open(file, vgpu_mmio_diff_show, inode->i_private); | ||
129 | } | ||
130 | |||
131 | static const struct file_operations vgpu_mmio_diff_fops = { | ||
132 | .open = vgpu_mmio_diff_open, | ||
133 | .read = seq_read, | ||
134 | .llseek = seq_lseek, | ||
135 | .release = single_release, | ||
136 | }; | ||
137 | 126 | ||
138 | /** | 127 | /** |
139 | * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU | 128 | * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 89f7ff2c652e..2e6652a9bb9e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -1215,20 +1215,20 @@ static int i915_frequency_info(struct seq_file *m, void *unused) | |||
1215 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 : | 1215 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 : |
1216 | rp_state_cap >> 16) & 0xff; | 1216 | rp_state_cap >> 16) & 0xff; |
1217 | max_freq *= (IS_GEN9_BC(dev_priv) || | 1217 | max_freq *= (IS_GEN9_BC(dev_priv) || |
1218 | IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); | 1218 | INTEL_GEN(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1); |
1219 | seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", | 1219 | seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", |
1220 | intel_gpu_freq(dev_priv, max_freq)); | 1220 | intel_gpu_freq(dev_priv, max_freq)); |
1221 | 1221 | ||
1222 | max_freq = (rp_state_cap & 0xff00) >> 8; | 1222 | max_freq = (rp_state_cap & 0xff00) >> 8; |
1223 | max_freq *= (IS_GEN9_BC(dev_priv) || | 1223 | max_freq *= (IS_GEN9_BC(dev_priv) || |
1224 | IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); | 1224 | INTEL_GEN(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1); |
1225 | seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", | 1225 | seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", |
1226 | intel_gpu_freq(dev_priv, max_freq)); | 1226 | intel_gpu_freq(dev_priv, max_freq)); |
1227 | 1227 | ||
1228 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 16 : | 1228 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 16 : |
1229 | rp_state_cap >> 0) & 0xff; | 1229 | rp_state_cap >> 0) & 0xff; |
1230 | max_freq *= (IS_GEN9_BC(dev_priv) || | 1230 | max_freq *= (IS_GEN9_BC(dev_priv) || |
1231 | IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); | 1231 | INTEL_GEN(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1); |
1232 | seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", | 1232 | seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", |
1233 | intel_gpu_freq(dev_priv, max_freq)); | 1233 | intel_gpu_freq(dev_priv, max_freq)); |
1234 | seq_printf(m, "Max overclocked frequency: %dMHz\n", | 1234 | seq_printf(m, "Max overclocked frequency: %dMHz\n", |
@@ -1796,9 +1796,9 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) | |||
1796 | { | 1796 | { |
1797 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 1797 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
1798 | struct intel_rps *rps = &dev_priv->gt_pm.rps; | 1798 | struct intel_rps *rps = &dev_priv->gt_pm.rps; |
1799 | int ret = 0; | ||
1800 | int gpu_freq, ia_freq; | ||
1801 | unsigned int max_gpu_freq, min_gpu_freq; | 1799 | unsigned int max_gpu_freq, min_gpu_freq; |
1800 | int gpu_freq, ia_freq; | ||
1801 | int ret; | ||
1802 | 1802 | ||
1803 | if (!HAS_LLC(dev_priv)) | 1803 | if (!HAS_LLC(dev_priv)) |
1804 | return -ENODEV; | 1804 | return -ENODEV; |
@@ -1809,13 +1809,12 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) | |||
1809 | if (ret) | 1809 | if (ret) |
1810 | goto out; | 1810 | goto out; |
1811 | 1811 | ||
1812 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 1812 | min_gpu_freq = rps->min_freq; |
1813 | max_gpu_freq = rps->max_freq; | ||
1814 | if (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) { | ||
1813 | /* Convert GT frequency to 50 HZ units */ | 1815 | /* Convert GT frequency to 50 HZ units */ |
1814 | min_gpu_freq = rps->min_freq_softlimit / GEN9_FREQ_SCALER; | 1816 | min_gpu_freq /= GEN9_FREQ_SCALER; |
1815 | max_gpu_freq = rps->max_freq_softlimit / GEN9_FREQ_SCALER; | 1817 | max_gpu_freq /= GEN9_FREQ_SCALER; |
1816 | } else { | ||
1817 | min_gpu_freq = rps->min_freq_softlimit; | ||
1818 | max_gpu_freq = rps->max_freq_softlimit; | ||
1819 | } | 1818 | } |
1820 | 1819 | ||
1821 | seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); | 1820 | seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); |
@@ -1828,7 +1827,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) | |||
1828 | seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", | 1827 | seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", |
1829 | intel_gpu_freq(dev_priv, (gpu_freq * | 1828 | intel_gpu_freq(dev_priv, (gpu_freq * |
1830 | (IS_GEN9_BC(dev_priv) || | 1829 | (IS_GEN9_BC(dev_priv) || |
1831 | IS_CANNONLAKE(dev_priv) ? | 1830 | INTEL_GEN(dev_priv) >= 10 ? |
1832 | GEN9_FREQ_SCALER : 1))), | 1831 | GEN9_FREQ_SCALER : 1))), |
1833 | ((ia_freq >> 0) & 0xff) * 100, | 1832 | ((ia_freq >> 0) & 0xff) * 100, |
1834 | ((ia_freq >> 8) & 0xff) * 100); | 1833 | ((ia_freq >> 8) & 0xff) * 100); |
@@ -1923,8 +1922,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | |||
1923 | 1922 | ||
1924 | static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring) | 1923 | static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring) |
1925 | { | 1924 | { |
1926 | seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u)", | 1925 | seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u, emit: %u)", |
1927 | ring->space, ring->head, ring->tail); | 1926 | ring->space, ring->head, ring->tail, ring->emit); |
1928 | } | 1927 | } |
1929 | 1928 | ||
1930 | static int i915_context_status(struct seq_file *m, void *unused) | 1929 | static int i915_context_status(struct seq_file *m, void *unused) |
@@ -2326,30 +2325,45 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) | |||
2326 | return 0; | 2325 | return 0; |
2327 | } | 2326 | } |
2328 | 2327 | ||
2329 | static void i915_guc_log_info(struct seq_file *m, | 2328 | static const char * |
2330 | struct drm_i915_private *dev_priv) | 2329 | stringify_guc_log_type(enum guc_log_buffer_type type) |
2331 | { | 2330 | { |
2332 | struct intel_guc *guc = &dev_priv->guc; | 2331 | switch (type) { |
2332 | case GUC_ISR_LOG_BUFFER: | ||
2333 | return "ISR"; | ||
2334 | case GUC_DPC_LOG_BUFFER: | ||
2335 | return "DPC"; | ||
2336 | case GUC_CRASH_DUMP_LOG_BUFFER: | ||
2337 | return "CRASH"; | ||
2338 | default: | ||
2339 | MISSING_CASE(type); | ||
2340 | } | ||
2333 | 2341 | ||
2334 | seq_puts(m, "\nGuC logging stats:\n"); | 2342 | return ""; |
2343 | } | ||
2335 | 2344 | ||
2336 | seq_printf(m, "\tISR: flush count %10u, overflow count %10u\n", | 2345 | static void i915_guc_log_info(struct seq_file *m, |
2337 | guc->log.flush_count[GUC_ISR_LOG_BUFFER], | 2346 | struct drm_i915_private *dev_priv) |
2338 | guc->log.total_overflow_count[GUC_ISR_LOG_BUFFER]); | 2347 | { |
2348 | struct intel_guc_log *log = &dev_priv->guc.log; | ||
2349 | enum guc_log_buffer_type type; | ||
2339 | 2350 | ||
2340 | seq_printf(m, "\tDPC: flush count %10u, overflow count %10u\n", | 2351 | if (!intel_guc_log_relay_enabled(log)) { |
2341 | guc->log.flush_count[GUC_DPC_LOG_BUFFER], | 2352 | seq_puts(m, "GuC log relay disabled\n"); |
2342 | guc->log.total_overflow_count[GUC_DPC_LOG_BUFFER]); | 2353 | return; |
2354 | } | ||
2343 | 2355 | ||
2344 | seq_printf(m, "\tCRASH: flush count %10u, overflow count %10u\n", | 2356 | seq_puts(m, "GuC logging stats:\n"); |
2345 | guc->log.flush_count[GUC_CRASH_DUMP_LOG_BUFFER], | ||
2346 | guc->log.total_overflow_count[GUC_CRASH_DUMP_LOG_BUFFER]); | ||
2347 | 2357 | ||
2348 | seq_printf(m, "\tTotal flush interrupt count: %u\n", | 2358 | seq_printf(m, "\tRelay full count: %u\n", |
2349 | guc->log.flush_interrupt_count); | 2359 | log->relay.full_count); |
2350 | 2360 | ||
2351 | seq_printf(m, "\tCapture miss count: %u\n", | 2361 | for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { |
2352 | guc->log.capture_miss_count); | 2362 | seq_printf(m, "\t%s:\tflush count %10u, overflow count %10u\n", |
2363 | stringify_guc_log_type(type), | ||
2364 | log->stats[type].flush, | ||
2365 | log->stats[type].sampled_overflow); | ||
2366 | } | ||
2353 | } | 2367 | } |
2354 | 2368 | ||
2355 | static void i915_guc_client_info(struct seq_file *m, | 2369 | static void i915_guc_client_info(struct seq_file *m, |
@@ -2379,14 +2393,19 @@ static int i915_guc_info(struct seq_file *m, void *data) | |||
2379 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 2393 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
2380 | const struct intel_guc *guc = &dev_priv->guc; | 2394 | const struct intel_guc *guc = &dev_priv->guc; |
2381 | 2395 | ||
2382 | if (!USES_GUC_SUBMISSION(dev_priv)) | 2396 | if (!USES_GUC(dev_priv)) |
2383 | return -ENODEV; | 2397 | return -ENODEV; |
2384 | 2398 | ||
2399 | i915_guc_log_info(m, dev_priv); | ||
2400 | |||
2401 | if (!USES_GUC_SUBMISSION(dev_priv)) | ||
2402 | return 0; | ||
2403 | |||
2385 | GEM_BUG_ON(!guc->execbuf_client); | 2404 | GEM_BUG_ON(!guc->execbuf_client); |
2386 | 2405 | ||
2387 | seq_printf(m, "Doorbell map:\n"); | 2406 | seq_printf(m, "\nDoorbell map:\n"); |
2388 | seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); | 2407 | seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); |
2389 | seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline); | 2408 | seq_printf(m, "Doorbell next cacheline: 0x%x\n", guc->db_cacheline); |
2390 | 2409 | ||
2391 | seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); | 2410 | seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); |
2392 | i915_guc_client_info(m, dev_priv, guc->execbuf_client); | 2411 | i915_guc_client_info(m, dev_priv, guc->execbuf_client); |
@@ -2396,8 +2415,6 @@ static int i915_guc_info(struct seq_file *m, void *data) | |||
2396 | i915_guc_client_info(m, dev_priv, guc->preempt_client); | 2415 | i915_guc_client_info(m, dev_priv, guc->preempt_client); |
2397 | } | 2416 | } |
2398 | 2417 | ||
2399 | i915_guc_log_info(m, dev_priv); | ||
2400 | |||
2401 | /* Add more as required ... */ | 2418 | /* Add more as required ... */ |
2402 | 2419 | ||
2403 | return 0; | 2420 | return 0; |
@@ -2496,35 +2513,73 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) | |||
2496 | return 0; | 2513 | return 0; |
2497 | } | 2514 | } |
2498 | 2515 | ||
2499 | static int i915_guc_log_control_get(void *data, u64 *val) | 2516 | static int i915_guc_log_level_get(void *data, u64 *val) |
2500 | { | 2517 | { |
2501 | struct drm_i915_private *dev_priv = data; | 2518 | struct drm_i915_private *dev_priv = data; |
2502 | 2519 | ||
2503 | if (!HAS_GUC(dev_priv)) | 2520 | if (!USES_GUC(dev_priv)) |
2504 | return -ENODEV; | 2521 | return -ENODEV; |
2505 | 2522 | ||
2506 | if (!dev_priv->guc.log.vma) | 2523 | *val = intel_guc_log_level_get(&dev_priv->guc.log); |
2507 | return -EINVAL; | ||
2508 | |||
2509 | *val = i915_modparams.guc_log_level; | ||
2510 | 2524 | ||
2511 | return 0; | 2525 | return 0; |
2512 | } | 2526 | } |
2513 | 2527 | ||
2514 | static int i915_guc_log_control_set(void *data, u64 val) | 2528 | static int i915_guc_log_level_set(void *data, u64 val) |
2515 | { | 2529 | { |
2516 | struct drm_i915_private *dev_priv = data; | 2530 | struct drm_i915_private *dev_priv = data; |
2517 | 2531 | ||
2518 | if (!HAS_GUC(dev_priv)) | 2532 | if (!USES_GUC(dev_priv)) |
2519 | return -ENODEV; | 2533 | return -ENODEV; |
2520 | 2534 | ||
2521 | return intel_guc_log_control(&dev_priv->guc, val); | 2535 | return intel_guc_log_level_set(&dev_priv->guc.log, val); |
2522 | } | 2536 | } |
2523 | 2537 | ||
2524 | DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_control_fops, | 2538 | DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_level_fops, |
2525 | i915_guc_log_control_get, i915_guc_log_control_set, | 2539 | i915_guc_log_level_get, i915_guc_log_level_set, |
2526 | "%lld\n"); | 2540 | "%lld\n"); |
2527 | 2541 | ||
2542 | static int i915_guc_log_relay_open(struct inode *inode, struct file *file) | ||
2543 | { | ||
2544 | struct drm_i915_private *dev_priv = inode->i_private; | ||
2545 | |||
2546 | if (!USES_GUC(dev_priv)) | ||
2547 | return -ENODEV; | ||
2548 | |||
2549 | file->private_data = &dev_priv->guc.log; | ||
2550 | |||
2551 | return intel_guc_log_relay_open(&dev_priv->guc.log); | ||
2552 | } | ||
2553 | |||
2554 | static ssize_t | ||
2555 | i915_guc_log_relay_write(struct file *filp, | ||
2556 | const char __user *ubuf, | ||
2557 | size_t cnt, | ||
2558 | loff_t *ppos) | ||
2559 | { | ||
2560 | struct intel_guc_log *log = filp->private_data; | ||
2561 | |||
2562 | intel_guc_log_relay_flush(log); | ||
2563 | |||
2564 | return cnt; | ||
2565 | } | ||
2566 | |||
2567 | static int i915_guc_log_relay_release(struct inode *inode, struct file *file) | ||
2568 | { | ||
2569 | struct drm_i915_private *dev_priv = inode->i_private; | ||
2570 | |||
2571 | intel_guc_log_relay_close(&dev_priv->guc.log); | ||
2572 | |||
2573 | return 0; | ||
2574 | } | ||
2575 | |||
2576 | static const struct file_operations i915_guc_log_relay_fops = { | ||
2577 | .owner = THIS_MODULE, | ||
2578 | .open = i915_guc_log_relay_open, | ||
2579 | .write = i915_guc_log_relay_write, | ||
2580 | .release = i915_guc_log_relay_release, | ||
2581 | }; | ||
2582 | |||
2528 | static const char *psr2_live_status(u32 val) | 2583 | static const char *psr2_live_status(u32 val) |
2529 | { | 2584 | { |
2530 | static const char * const live_status[] = { | 2585 | static const char * const live_status[] = { |
@@ -2569,14 +2624,13 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) | |||
2569 | 2624 | ||
2570 | mutex_lock(&dev_priv->psr.lock); | 2625 | mutex_lock(&dev_priv->psr.lock); |
2571 | seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled)); | 2626 | seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled)); |
2572 | seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active)); | ||
2573 | seq_printf(m, "Busy frontbuffer bits: 0x%03x\n", | 2627 | seq_printf(m, "Busy frontbuffer bits: 0x%03x\n", |
2574 | dev_priv->psr.busy_frontbuffer_bits); | 2628 | dev_priv->psr.busy_frontbuffer_bits); |
2575 | seq_printf(m, "Re-enable work scheduled: %s\n", | 2629 | seq_printf(m, "Re-enable work scheduled: %s\n", |
2576 | yesno(work_busy(&dev_priv->psr.work.work))); | 2630 | yesno(work_busy(&dev_priv->psr.work.work))); |
2577 | 2631 | ||
2578 | if (HAS_DDI(dev_priv)) { | 2632 | if (HAS_DDI(dev_priv)) { |
2579 | if (dev_priv->psr.psr2_support) | 2633 | if (dev_priv->psr.psr2_enabled) |
2580 | enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE; | 2634 | enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE; |
2581 | else | 2635 | else |
2582 | enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; | 2636 | enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; |
@@ -2624,7 +2678,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) | |||
2624 | 2678 | ||
2625 | seq_printf(m, "Performance_Counter: %u\n", psrperf); | 2679 | seq_printf(m, "Performance_Counter: %u\n", psrperf); |
2626 | } | 2680 | } |
2627 | if (dev_priv->psr.psr2_support) { | 2681 | if (dev_priv->psr.psr2_enabled) { |
2628 | u32 psr2 = I915_READ(EDP_PSR2_STATUS); | 2682 | u32 psr2 = I915_READ(EDP_PSR2_STATUS); |
2629 | 2683 | ||
2630 | seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", | 2684 | seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", |
@@ -3231,7 +3285,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) | |||
3231 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { | 3285 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
3232 | struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; | 3286 | struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; |
3233 | 3287 | ||
3234 | seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id); | 3288 | seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name, |
3289 | pll->info->id); | ||
3235 | seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n", | 3290 | seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n", |
3236 | pll->state.crtc_mask, pll->active_mask, yesno(pll->on)); | 3291 | pll->state.crtc_mask, pll->active_mask, yesno(pll->on)); |
3237 | seq_printf(m, " tracked hardware state:\n"); | 3292 | seq_printf(m, " tracked hardware state:\n"); |
@@ -3567,7 +3622,8 @@ static ssize_t i915_displayport_test_active_write(struct file *file, | |||
3567 | 3622 | ||
3568 | static int i915_displayport_test_active_show(struct seq_file *m, void *data) | 3623 | static int i915_displayport_test_active_show(struct seq_file *m, void *data) |
3569 | { | 3624 | { |
3570 | struct drm_device *dev = m->private; | 3625 | struct drm_i915_private *dev_priv = m->private; |
3626 | struct drm_device *dev = &dev_priv->drm; | ||
3571 | struct drm_connector *connector; | 3627 | struct drm_connector *connector; |
3572 | struct drm_connector_list_iter conn_iter; | 3628 | struct drm_connector_list_iter conn_iter; |
3573 | struct intel_dp *intel_dp; | 3629 | struct intel_dp *intel_dp; |
@@ -3601,10 +3657,8 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data) | |||
3601 | static int i915_displayport_test_active_open(struct inode *inode, | 3657 | static int i915_displayport_test_active_open(struct inode *inode, |
3602 | struct file *file) | 3658 | struct file *file) |
3603 | { | 3659 | { |
3604 | struct drm_i915_private *dev_priv = inode->i_private; | ||
3605 | |||
3606 | return single_open(file, i915_displayport_test_active_show, | 3660 | return single_open(file, i915_displayport_test_active_show, |
3607 | &dev_priv->drm); | 3661 | inode->i_private); |
3608 | } | 3662 | } |
3609 | 3663 | ||
3610 | static const struct file_operations i915_displayport_test_active_fops = { | 3664 | static const struct file_operations i915_displayport_test_active_fops = { |
@@ -3618,7 +3672,8 @@ static const struct file_operations i915_displayport_test_active_fops = { | |||
3618 | 3672 | ||
3619 | static int i915_displayport_test_data_show(struct seq_file *m, void *data) | 3673 | static int i915_displayport_test_data_show(struct seq_file *m, void *data) |
3620 | { | 3674 | { |
3621 | struct drm_device *dev = m->private; | 3675 | struct drm_i915_private *dev_priv = m->private; |
3676 | struct drm_device *dev = &dev_priv->drm; | ||
3622 | struct drm_connector *connector; | 3677 | struct drm_connector *connector; |
3623 | struct drm_connector_list_iter conn_iter; | 3678 | struct drm_connector_list_iter conn_iter; |
3624 | struct intel_dp *intel_dp; | 3679 | struct intel_dp *intel_dp; |
@@ -3657,26 +3712,12 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data) | |||
3657 | 3712 | ||
3658 | return 0; | 3713 | return 0; |
3659 | } | 3714 | } |
3660 | static int i915_displayport_test_data_open(struct inode *inode, | 3715 | DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data); |
3661 | struct file *file) | ||
3662 | { | ||
3663 | struct drm_i915_private *dev_priv = inode->i_private; | ||
3664 | |||
3665 | return single_open(file, i915_displayport_test_data_show, | ||
3666 | &dev_priv->drm); | ||
3667 | } | ||
3668 | |||
3669 | static const struct file_operations i915_displayport_test_data_fops = { | ||
3670 | .owner = THIS_MODULE, | ||
3671 | .open = i915_displayport_test_data_open, | ||
3672 | .read = seq_read, | ||
3673 | .llseek = seq_lseek, | ||
3674 | .release = single_release | ||
3675 | }; | ||
3676 | 3716 | ||
3677 | static int i915_displayport_test_type_show(struct seq_file *m, void *data) | 3717 | static int i915_displayport_test_type_show(struct seq_file *m, void *data) |
3678 | { | 3718 | { |
3679 | struct drm_device *dev = m->private; | 3719 | struct drm_i915_private *dev_priv = m->private; |
3720 | struct drm_device *dev = &dev_priv->drm; | ||
3680 | struct drm_connector *connector; | 3721 | struct drm_connector *connector; |
3681 | struct drm_connector_list_iter conn_iter; | 3722 | struct drm_connector_list_iter conn_iter; |
3682 | struct intel_dp *intel_dp; | 3723 | struct intel_dp *intel_dp; |
@@ -3703,23 +3744,7 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data) | |||
3703 | 3744 | ||
3704 | return 0; | 3745 | return 0; |
3705 | } | 3746 | } |
3706 | 3747 | DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type); | |
3707 | static int i915_displayport_test_type_open(struct inode *inode, | ||
3708 | struct file *file) | ||
3709 | { | ||
3710 | struct drm_i915_private *dev_priv = inode->i_private; | ||
3711 | |||
3712 | return single_open(file, i915_displayport_test_type_show, | ||
3713 | &dev_priv->drm); | ||
3714 | } | ||
3715 | |||
3716 | static const struct file_operations i915_displayport_test_type_fops = { | ||
3717 | .owner = THIS_MODULE, | ||
3718 | .open = i915_displayport_test_type_open, | ||
3719 | .read = seq_read, | ||
3720 | .llseek = seq_lseek, | ||
3721 | .release = single_release | ||
3722 | }; | ||
3723 | 3748 | ||
3724 | static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) | 3749 | static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) |
3725 | { | 3750 | { |
@@ -3987,8 +4012,8 @@ i915_wedged_set(void *data, u64 val) | |||
3987 | engine->hangcheck.stalled = true; | 4012 | engine->hangcheck.stalled = true; |
3988 | } | 4013 | } |
3989 | 4014 | ||
3990 | i915_handle_error(i915, val, "Manually set wedged engine mask = %llx", | 4015 | i915_handle_error(i915, val, I915_ERROR_CAPTURE, |
3991 | val); | 4016 | "Manually set wedged engine mask = %llx", val); |
3992 | 4017 | ||
3993 | wait_on_bit(&i915->gpu_error.flags, | 4018 | wait_on_bit(&i915->gpu_error.flags, |
3994 | I915_RESET_HANDOFF, | 4019 | I915_RESET_HANDOFF, |
@@ -4316,9 +4341,10 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, | |||
4316 | static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, | 4341 | static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, |
4317 | struct sseu_dev_info *sseu) | 4342 | struct sseu_dev_info *sseu) |
4318 | { | 4343 | { |
4319 | int ss_max = 2; | 4344 | #define SS_MAX 2 |
4345 | const int ss_max = SS_MAX; | ||
4346 | u32 sig1[SS_MAX], sig2[SS_MAX]; | ||
4320 | int ss; | 4347 | int ss; |
4321 | u32 sig1[ss_max], sig2[ss_max]; | ||
4322 | 4348 | ||
4323 | sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); | 4349 | sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); |
4324 | sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); | 4350 | sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); |
@@ -4342,15 +4368,16 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, | |||
4342 | sseu->eu_per_subslice = max_t(unsigned int, | 4368 | sseu->eu_per_subslice = max_t(unsigned int, |
4343 | sseu->eu_per_subslice, eu_cnt); | 4369 | sseu->eu_per_subslice, eu_cnt); |
4344 | } | 4370 | } |
4371 | #undef SS_MAX | ||
4345 | } | 4372 | } |
4346 | 4373 | ||
4347 | static void gen10_sseu_device_status(struct drm_i915_private *dev_priv, | 4374 | static void gen10_sseu_device_status(struct drm_i915_private *dev_priv, |
4348 | struct sseu_dev_info *sseu) | 4375 | struct sseu_dev_info *sseu) |
4349 | { | 4376 | { |
4377 | #define SS_MAX 6 | ||
4350 | const struct intel_device_info *info = INTEL_INFO(dev_priv); | 4378 | const struct intel_device_info *info = INTEL_INFO(dev_priv); |
4379 | u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2]; | ||
4351 | int s, ss; | 4380 | int s, ss; |
4352 | u32 s_reg[info->sseu.max_slices]; | ||
4353 | u32 eu_reg[2 * info->sseu.max_subslices], eu_mask[2]; | ||
4354 | 4381 | ||
4355 | for (s = 0; s < info->sseu.max_slices; s++) { | 4382 | for (s = 0; s < info->sseu.max_slices; s++) { |
4356 | /* | 4383 | /* |
@@ -4397,15 +4424,16 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv, | |||
4397 | eu_cnt); | 4424 | eu_cnt); |
4398 | } | 4425 | } |
4399 | } | 4426 | } |
4427 | #undef SS_MAX | ||
4400 | } | 4428 | } |
4401 | 4429 | ||
4402 | static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, | 4430 | static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, |
4403 | struct sseu_dev_info *sseu) | 4431 | struct sseu_dev_info *sseu) |
4404 | { | 4432 | { |
4433 | #define SS_MAX 3 | ||
4405 | const struct intel_device_info *info = INTEL_INFO(dev_priv); | 4434 | const struct intel_device_info *info = INTEL_INFO(dev_priv); |
4435 | u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2]; | ||
4406 | int s, ss; | 4436 | int s, ss; |
4407 | u32 s_reg[info->sseu.max_slices]; | ||
4408 | u32 eu_reg[2 * info->sseu.max_subslices], eu_mask[2]; | ||
4409 | 4437 | ||
4410 | for (s = 0; s < info->sseu.max_slices; s++) { | 4438 | for (s = 0; s < info->sseu.max_slices; s++) { |
4411 | s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s)); | 4439 | s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s)); |
@@ -4452,6 +4480,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, | |||
4452 | eu_cnt); | 4480 | eu_cnt); |
4453 | } | 4481 | } |
4454 | } | 4482 | } |
4483 | #undef SS_MAX | ||
4455 | } | 4484 | } |
4456 | 4485 | ||
4457 | static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, | 4486 | static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, |
@@ -4703,6 +4732,67 @@ static int i915_drrs_ctl_set(void *data, u64 val) | |||
4703 | 4732 | ||
4704 | DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n"); | 4733 | DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n"); |
4705 | 4734 | ||
4735 | static ssize_t | ||
4736 | i915_fifo_underrun_reset_write(struct file *filp, | ||
4737 | const char __user *ubuf, | ||
4738 | size_t cnt, loff_t *ppos) | ||
4739 | { | ||
4740 | struct drm_i915_private *dev_priv = filp->private_data; | ||
4741 | struct intel_crtc *intel_crtc; | ||
4742 | struct drm_device *dev = &dev_priv->drm; | ||
4743 | int ret; | ||
4744 | bool reset; | ||
4745 | |||
4746 | ret = kstrtobool_from_user(ubuf, cnt, &reset); | ||
4747 | if (ret) | ||
4748 | return ret; | ||
4749 | |||
4750 | if (!reset) | ||
4751 | return cnt; | ||
4752 | |||
4753 | for_each_intel_crtc(dev, intel_crtc) { | ||
4754 | struct drm_crtc_commit *commit; | ||
4755 | struct intel_crtc_state *crtc_state; | ||
4756 | |||
4757 | ret = drm_modeset_lock_single_interruptible(&intel_crtc->base.mutex); | ||
4758 | if (ret) | ||
4759 | return ret; | ||
4760 | |||
4761 | crtc_state = to_intel_crtc_state(intel_crtc->base.state); | ||
4762 | commit = crtc_state->base.commit; | ||
4763 | if (commit) { | ||
4764 | ret = wait_for_completion_interruptible(&commit->hw_done); | ||
4765 | if (!ret) | ||
4766 | ret = wait_for_completion_interruptible(&commit->flip_done); | ||
4767 | } | ||
4768 | |||
4769 | if (!ret && crtc_state->base.active) { | ||
4770 | DRM_DEBUG_KMS("Re-arming FIFO underruns on pipe %c\n", | ||
4771 | pipe_name(intel_crtc->pipe)); | ||
4772 | |||
4773 | intel_crtc_arm_fifo_underrun(intel_crtc, crtc_state); | ||
4774 | } | ||
4775 | |||
4776 | drm_modeset_unlock(&intel_crtc->base.mutex); | ||
4777 | |||
4778 | if (ret) | ||
4779 | return ret; | ||
4780 | } | ||
4781 | |||
4782 | ret = intel_fbc_reset_underrun(dev_priv); | ||
4783 | if (ret) | ||
4784 | return ret; | ||
4785 | |||
4786 | return cnt; | ||
4787 | } | ||
4788 | |||
4789 | static const struct file_operations i915_fifo_underrun_reset_ops = { | ||
4790 | .owner = THIS_MODULE, | ||
4791 | .open = simple_open, | ||
4792 | .write = i915_fifo_underrun_reset_write, | ||
4793 | .llseek = default_llseek, | ||
4794 | }; | ||
4795 | |||
4706 | static const struct drm_info_list i915_debugfs_list[] = { | 4796 | static const struct drm_info_list i915_debugfs_list[] = { |
4707 | {"i915_capabilities", i915_capabilities, 0}, | 4797 | {"i915_capabilities", i915_capabilities, 0}, |
4708 | {"i915_gem_objects", i915_gem_object_info, 0}, | 4798 | {"i915_gem_objects", i915_gem_object_info, 0}, |
@@ -4770,6 +4860,7 @@ static const struct i915_debugfs_files { | |||
4770 | {"i915_error_state", &i915_error_state_fops}, | 4860 | {"i915_error_state", &i915_error_state_fops}, |
4771 | {"i915_gpu_info", &i915_gpu_info_fops}, | 4861 | {"i915_gpu_info", &i915_gpu_info_fops}, |
4772 | #endif | 4862 | #endif |
4863 | {"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops}, | ||
4773 | {"i915_next_seqno", &i915_next_seqno_fops}, | 4864 | {"i915_next_seqno", &i915_next_seqno_fops}, |
4774 | {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, | 4865 | {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, |
4775 | {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, | 4866 | {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, |
@@ -4779,7 +4870,8 @@ static const struct i915_debugfs_files { | |||
4779 | {"i915_dp_test_data", &i915_displayport_test_data_fops}, | 4870 | {"i915_dp_test_data", &i915_displayport_test_data_fops}, |
4780 | {"i915_dp_test_type", &i915_displayport_test_type_fops}, | 4871 | {"i915_dp_test_type", &i915_displayport_test_type_fops}, |
4781 | {"i915_dp_test_active", &i915_displayport_test_active_fops}, | 4872 | {"i915_dp_test_active", &i915_displayport_test_active_fops}, |
4782 | {"i915_guc_log_control", &i915_guc_log_control_fops}, | 4873 | {"i915_guc_log_level", &i915_guc_log_level_fops}, |
4874 | {"i915_guc_log_relay", &i915_guc_log_relay_fops}, | ||
4783 | {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, | 4875 | {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, |
4784 | {"i915_ipc_status", &i915_ipc_status_fops}, | 4876 | {"i915_ipc_status", &i915_ipc_status_fops}, |
4785 | {"i915_drrs_ctl", &i915_drrs_ctl_fops} | 4877 | {"i915_drrs_ctl", &i915_drrs_ctl_fops} |
@@ -4876,19 +4968,7 @@ static int i915_dpcd_show(struct seq_file *m, void *data) | |||
4876 | 4968 | ||
4877 | return 0; | 4969 | return 0; |
4878 | } | 4970 | } |
4879 | 4971 | DEFINE_SHOW_ATTRIBUTE(i915_dpcd); | |
4880 | static int i915_dpcd_open(struct inode *inode, struct file *file) | ||
4881 | { | ||
4882 | return single_open(file, i915_dpcd_show, inode->i_private); | ||
4883 | } | ||
4884 | |||
4885 | static const struct file_operations i915_dpcd_fops = { | ||
4886 | .owner = THIS_MODULE, | ||
4887 | .open = i915_dpcd_open, | ||
4888 | .read = seq_read, | ||
4889 | .llseek = seq_lseek, | ||
4890 | .release = single_release, | ||
4891 | }; | ||
4892 | 4972 | ||
4893 | static int i915_panel_show(struct seq_file *m, void *data) | 4973 | static int i915_panel_show(struct seq_file *m, void *data) |
4894 | { | 4974 | { |
@@ -4910,19 +4990,7 @@ static int i915_panel_show(struct seq_file *m, void *data) | |||
4910 | 4990 | ||
4911 | return 0; | 4991 | return 0; |
4912 | } | 4992 | } |
4913 | 4993 | DEFINE_SHOW_ATTRIBUTE(i915_panel); | |
4914 | static int i915_panel_open(struct inode *inode, struct file *file) | ||
4915 | { | ||
4916 | return single_open(file, i915_panel_show, inode->i_private); | ||
4917 | } | ||
4918 | |||
4919 | static const struct file_operations i915_panel_fops = { | ||
4920 | .owner = THIS_MODULE, | ||
4921 | .open = i915_panel_open, | ||
4922 | .read = seq_read, | ||
4923 | .llseek = seq_lseek, | ||
4924 | .release = single_release, | ||
4925 | }; | ||
4926 | 4994 | ||
4927 | /** | 4995 | /** |
4928 | * i915_debugfs_connector_add - add i915 specific connector debugfs files | 4996 | * i915_debugfs_connector_add - add i915 specific connector debugfs files |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3b4daafebdcb..b7dbeba72dec 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -377,9 +377,9 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data, | |||
377 | value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; | 377 | value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; |
378 | break; | 378 | break; |
379 | case I915_PARAM_HUC_STATUS: | 379 | case I915_PARAM_HUC_STATUS: |
380 | intel_runtime_pm_get(dev_priv); | 380 | value = intel_huc_check_status(&dev_priv->huc); |
381 | value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; | 381 | if (value < 0) |
382 | intel_runtime_pm_put(dev_priv); | 382 | return value; |
383 | break; | 383 | break; |
384 | case I915_PARAM_MMAP_GTT_VERSION: | 384 | case I915_PARAM_MMAP_GTT_VERSION: |
385 | /* Though we've started our numbering from 1, and so class all | 385 | /* Though we've started our numbering from 1, and so class all |
@@ -695,11 +695,9 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
695 | if (ret) | 695 | if (ret) |
696 | goto cleanup_irq; | 696 | goto cleanup_irq; |
697 | 697 | ||
698 | intel_uc_init_fw(dev_priv); | ||
699 | |||
700 | ret = i915_gem_init(dev_priv); | 698 | ret = i915_gem_init(dev_priv); |
701 | if (ret) | 699 | if (ret) |
702 | goto cleanup_uc; | 700 | goto cleanup_irq; |
703 | 701 | ||
704 | intel_setup_overlay(dev_priv); | 702 | intel_setup_overlay(dev_priv); |
705 | 703 | ||
@@ -719,8 +717,6 @@ cleanup_gem: | |||
719 | if (i915_gem_suspend(dev_priv)) | 717 | if (i915_gem_suspend(dev_priv)) |
720 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); | 718 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); |
721 | i915_gem_fini(dev_priv); | 719 | i915_gem_fini(dev_priv); |
722 | cleanup_uc: | ||
723 | intel_uc_fini_fw(dev_priv); | ||
724 | cleanup_irq: | 720 | cleanup_irq: |
725 | drm_irq_uninstall(dev); | 721 | drm_irq_uninstall(dev); |
726 | intel_teardown_gmbus(dev_priv); | 722 | intel_teardown_gmbus(dev_priv); |
@@ -922,16 +918,21 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, | |||
922 | mutex_init(&dev_priv->wm.wm_mutex); | 918 | mutex_init(&dev_priv->wm.wm_mutex); |
923 | mutex_init(&dev_priv->pps_mutex); | 919 | mutex_init(&dev_priv->pps_mutex); |
924 | 920 | ||
925 | intel_uc_init_early(dev_priv); | ||
926 | i915_memcpy_init_early(dev_priv); | 921 | i915_memcpy_init_early(dev_priv); |
927 | 922 | ||
928 | ret = i915_workqueues_init(dev_priv); | 923 | ret = i915_workqueues_init(dev_priv); |
929 | if (ret < 0) | 924 | if (ret < 0) |
930 | goto err_engines; | 925 | goto err_engines; |
931 | 926 | ||
927 | ret = i915_gem_init_early(dev_priv); | ||
928 | if (ret < 0) | ||
929 | goto err_workqueues; | ||
930 | |||
932 | /* This must be called before any calls to HAS_PCH_* */ | 931 | /* This must be called before any calls to HAS_PCH_* */ |
933 | intel_detect_pch(dev_priv); | 932 | intel_detect_pch(dev_priv); |
934 | 933 | ||
934 | intel_wopcm_init_early(&dev_priv->wopcm); | ||
935 | intel_uc_init_early(dev_priv); | ||
935 | intel_pm_setup(dev_priv); | 936 | intel_pm_setup(dev_priv); |
936 | intel_init_dpio(dev_priv); | 937 | intel_init_dpio(dev_priv); |
937 | intel_power_domains_init(dev_priv); | 938 | intel_power_domains_init(dev_priv); |
@@ -940,18 +941,13 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, | |||
940 | intel_init_display_hooks(dev_priv); | 941 | intel_init_display_hooks(dev_priv); |
941 | intel_init_clock_gating_hooks(dev_priv); | 942 | intel_init_clock_gating_hooks(dev_priv); |
942 | intel_init_audio_hooks(dev_priv); | 943 | intel_init_audio_hooks(dev_priv); |
943 | ret = i915_gem_load_init(dev_priv); | ||
944 | if (ret < 0) | ||
945 | goto err_irq; | ||
946 | |||
947 | intel_display_crc_init(dev_priv); | 944 | intel_display_crc_init(dev_priv); |
948 | 945 | ||
949 | intel_detect_preproduction_hw(dev_priv); | 946 | intel_detect_preproduction_hw(dev_priv); |
950 | 947 | ||
951 | return 0; | 948 | return 0; |
952 | 949 | ||
953 | err_irq: | 950 | err_workqueues: |
954 | intel_irq_fini(dev_priv); | ||
955 | i915_workqueues_cleanup(dev_priv); | 951 | i915_workqueues_cleanup(dev_priv); |
956 | err_engines: | 952 | err_engines: |
957 | i915_engines_cleanup(dev_priv); | 953 | i915_engines_cleanup(dev_priv); |
@@ -964,8 +960,9 @@ err_engines: | |||
964 | */ | 960 | */ |
965 | static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) | 961 | static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) |
966 | { | 962 | { |
967 | i915_gem_load_cleanup(dev_priv); | ||
968 | intel_irq_fini(dev_priv); | 963 | intel_irq_fini(dev_priv); |
964 | intel_uc_cleanup_early(dev_priv); | ||
965 | i915_gem_cleanup_early(dev_priv); | ||
969 | i915_workqueues_cleanup(dev_priv); | 966 | i915_workqueues_cleanup(dev_priv); |
970 | i915_engines_cleanup(dev_priv); | 967 | i915_engines_cleanup(dev_priv); |
971 | } | 968 | } |
@@ -1035,6 +1032,10 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) | |||
1035 | 1032 | ||
1036 | intel_uncore_init(dev_priv); | 1033 | intel_uncore_init(dev_priv); |
1037 | 1034 | ||
1035 | intel_device_info_init_mmio(dev_priv); | ||
1036 | |||
1037 | intel_uncore_prune(dev_priv); | ||
1038 | |||
1038 | intel_uc_init_mmio(dev_priv); | 1039 | intel_uc_init_mmio(dev_priv); |
1039 | 1040 | ||
1040 | ret = intel_engines_init_mmio(dev_priv); | 1041 | ret = intel_engines_init_mmio(dev_priv); |
@@ -1077,8 +1078,6 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) | |||
1077 | i915_modparams.enable_ppgtt); | 1078 | i915_modparams.enable_ppgtt); |
1078 | DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); | 1079 | DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); |
1079 | 1080 | ||
1080 | intel_uc_sanitize_options(dev_priv); | ||
1081 | |||
1082 | intel_gvt_sanitize_options(dev_priv); | 1081 | intel_gvt_sanitize_options(dev_priv); |
1083 | } | 1082 | } |
1084 | 1083 | ||
@@ -1244,7 +1243,6 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) | |||
1244 | /* Reveal our presence to userspace */ | 1243 | /* Reveal our presence to userspace */ |
1245 | if (drm_dev_register(dev, 0) == 0) { | 1244 | if (drm_dev_register(dev, 0) == 0) { |
1246 | i915_debugfs_register(dev_priv); | 1245 | i915_debugfs_register(dev_priv); |
1247 | i915_guc_log_register(dev_priv); | ||
1248 | i915_setup_sysfs(dev_priv); | 1246 | i915_setup_sysfs(dev_priv); |
1249 | 1247 | ||
1250 | /* Depends on sysfs having been initialized */ | 1248 | /* Depends on sysfs having been initialized */ |
@@ -1304,7 +1302,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) | |||
1304 | i915_pmu_unregister(dev_priv); | 1302 | i915_pmu_unregister(dev_priv); |
1305 | 1303 | ||
1306 | i915_teardown_sysfs(dev_priv); | 1304 | i915_teardown_sysfs(dev_priv); |
1307 | i915_guc_log_unregister(dev_priv); | ||
1308 | drm_dev_unregister(&dev_priv->drm); | 1305 | drm_dev_unregister(&dev_priv->drm); |
1309 | 1306 | ||
1310 | i915_gem_shrinker_unregister(dev_priv); | 1307 | i915_gem_shrinker_unregister(dev_priv); |
@@ -1463,7 +1460,6 @@ void i915_driver_unload(struct drm_device *dev) | |||
1463 | i915_reset_error_state(dev_priv); | 1460 | i915_reset_error_state(dev_priv); |
1464 | 1461 | ||
1465 | i915_gem_fini(dev_priv); | 1462 | i915_gem_fini(dev_priv); |
1466 | intel_uc_fini_fw(dev_priv); | ||
1467 | intel_fbc_cleanup_cfb(dev_priv); | 1463 | intel_fbc_cleanup_cfb(dev_priv); |
1468 | 1464 | ||
1469 | intel_power_domains_fini(dev_priv); | 1465 | intel_power_domains_fini(dev_priv); |
@@ -1876,7 +1872,8 @@ static int i915_resume_switcheroo(struct drm_device *dev) | |||
1876 | /** | 1872 | /** |
1877 | * i915_reset - reset chip after a hang | 1873 | * i915_reset - reset chip after a hang |
1878 | * @i915: #drm_i915_private to reset | 1874 | * @i915: #drm_i915_private to reset |
1879 | * @flags: Instructions | 1875 | * @stalled_mask: mask of the stalled engines with the guilty requests |
1876 | * @reason: user error message for why we are resetting | ||
1880 | * | 1877 | * |
1881 | * Reset the chip. Useful if a hang is detected. Marks the device as wedged | 1878 | * Reset the chip. Useful if a hang is detected. Marks the device as wedged |
1882 | * on failure. | 1879 | * on failure. |
@@ -1891,12 +1888,16 @@ static int i915_resume_switcheroo(struct drm_device *dev) | |||
1891 | * - re-init interrupt state | 1888 | * - re-init interrupt state |
1892 | * - re-init display | 1889 | * - re-init display |
1893 | */ | 1890 | */ |
1894 | void i915_reset(struct drm_i915_private *i915, unsigned int flags) | 1891 | void i915_reset(struct drm_i915_private *i915, |
1892 | unsigned int stalled_mask, | ||
1893 | const char *reason) | ||
1895 | { | 1894 | { |
1896 | struct i915_gpu_error *error = &i915->gpu_error; | 1895 | struct i915_gpu_error *error = &i915->gpu_error; |
1897 | int ret; | 1896 | int ret; |
1898 | int i; | 1897 | int i; |
1899 | 1898 | ||
1899 | GEM_TRACE("flags=%lx\n", error->flags); | ||
1900 | |||
1900 | might_sleep(); | 1901 | might_sleep(); |
1901 | lockdep_assert_held(&i915->drm.struct_mutex); | 1902 | lockdep_assert_held(&i915->drm.struct_mutex); |
1902 | GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags)); | 1903 | GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags)); |
@@ -1908,8 +1909,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) | |||
1908 | if (!i915_gem_unset_wedged(i915)) | 1909 | if (!i915_gem_unset_wedged(i915)) |
1909 | goto wakeup; | 1910 | goto wakeup; |
1910 | 1911 | ||
1911 | if (!(flags & I915_RESET_QUIET)) | 1912 | if (reason) |
1912 | dev_notice(i915->drm.dev, "Resetting chip after gpu hang\n"); | 1913 | dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason); |
1913 | error->reset_count++; | 1914 | error->reset_count++; |
1914 | 1915 | ||
1915 | disable_irq(i915->drm.irq); | 1916 | disable_irq(i915->drm.irq); |
@@ -1952,7 +1953,7 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) | |||
1952 | goto error; | 1953 | goto error; |
1953 | } | 1954 | } |
1954 | 1955 | ||
1955 | i915_gem_reset(i915); | 1956 | i915_gem_reset(i915, stalled_mask); |
1956 | intel_overlay_reset(i915); | 1957 | intel_overlay_reset(i915); |
1957 | 1958 | ||
1958 | /* | 1959 | /* |
@@ -1998,7 +1999,6 @@ taint: | |||
1998 | error: | 1999 | error: |
1999 | i915_gem_set_wedged(i915); | 2000 | i915_gem_set_wedged(i915); |
2000 | i915_retire_requests(i915); | 2001 | i915_retire_requests(i915); |
2001 | intel_gpu_reset(i915, ALL_ENGINES); | ||
2002 | goto finish; | 2002 | goto finish; |
2003 | } | 2003 | } |
2004 | 2004 | ||
@@ -2011,7 +2011,7 @@ static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv, | |||
2011 | /** | 2011 | /** |
2012 | * i915_reset_engine - reset GPU engine to recover from a hang | 2012 | * i915_reset_engine - reset GPU engine to recover from a hang |
2013 | * @engine: engine to reset | 2013 | * @engine: engine to reset |
2014 | * @flags: options | 2014 | * @msg: reason for GPU reset; or NULL for no dev_notice() |
2015 | * | 2015 | * |
2016 | * Reset a specific GPU engine. Useful if a hang is detected. | 2016 | * Reset a specific GPU engine. Useful if a hang is detected. |
2017 | * Returns zero on successful reset or otherwise an error code. | 2017 | * Returns zero on successful reset or otherwise an error code. |
@@ -2021,12 +2021,13 @@ static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv, | |||
2021 | * - reset engine (which will force the engine to idle) | 2021 | * - reset engine (which will force the engine to idle) |
2022 | * - re-init/configure engine | 2022 | * - re-init/configure engine |
2023 | */ | 2023 | */ |
2024 | int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) | 2024 | int i915_reset_engine(struct intel_engine_cs *engine, const char *msg) |
2025 | { | 2025 | { |
2026 | struct i915_gpu_error *error = &engine->i915->gpu_error; | 2026 | struct i915_gpu_error *error = &engine->i915->gpu_error; |
2027 | struct i915_request *active_request; | 2027 | struct i915_request *active_request; |
2028 | int ret; | 2028 | int ret; |
2029 | 2029 | ||
2030 | GEM_TRACE("%s flags=%lx\n", engine->name, error->flags); | ||
2030 | GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); | 2031 | GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); |
2031 | 2032 | ||
2032 | active_request = i915_gem_reset_prepare_engine(engine); | 2033 | active_request = i915_gem_reset_prepare_engine(engine); |
@@ -2036,10 +2037,9 @@ int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) | |||
2036 | goto out; | 2037 | goto out; |
2037 | } | 2038 | } |
2038 | 2039 | ||
2039 | if (!(flags & I915_RESET_QUIET)) { | 2040 | if (msg) |
2040 | dev_notice(engine->i915->drm.dev, | 2041 | dev_notice(engine->i915->drm.dev, |
2041 | "Resetting %s after gpu hang\n", engine->name); | 2042 | "Resetting %s for %s\n", engine->name, msg); |
2042 | } | ||
2043 | error->reset_engine_count[engine->id]++; | 2043 | error->reset_engine_count[engine->id]++; |
2044 | 2044 | ||
2045 | if (!engine->i915->guc.execbuf_client) | 2045 | if (!engine->i915->guc.execbuf_client) |
@@ -2059,7 +2059,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) | |||
2059 | * active request and can drop it, adjust head to skip the offending | 2059 | * active request and can drop it, adjust head to skip the offending |
2060 | * request to resume executing remaining requests in the queue. | 2060 | * request to resume executing remaining requests in the queue. |
2061 | */ | 2061 | */ |
2062 | i915_gem_reset_engine(engine, active_request); | 2062 | i915_gem_reset_engine(engine, active_request, true); |
2063 | 2063 | ||
2064 | /* | 2064 | /* |
2065 | * The engine and its registers (and workarounds in case of render) | 2065 | * The engine and its registers (and workarounds in case of render) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ce18b6cf6e68..e50d9589d6e3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -64,6 +64,7 @@ | |||
64 | #include "intel_opregion.h" | 64 | #include "intel_opregion.h" |
65 | #include "intel_ringbuffer.h" | 65 | #include "intel_ringbuffer.h" |
66 | #include "intel_uncore.h" | 66 | #include "intel_uncore.h" |
67 | #include "intel_wopcm.h" | ||
67 | #include "intel_uc.h" | 68 | #include "intel_uc.h" |
68 | 69 | ||
69 | #include "i915_gem.h" | 70 | #include "i915_gem.h" |
@@ -72,7 +73,7 @@ | |||
72 | #include "i915_gem_object.h" | 73 | #include "i915_gem_object.h" |
73 | #include "i915_gem_gtt.h" | 74 | #include "i915_gem_gtt.h" |
74 | #include "i915_gem_timeline.h" | 75 | #include "i915_gem_timeline.h" |
75 | 76 | #include "i915_gpu_error.h" | |
76 | #include "i915_request.h" | 77 | #include "i915_request.h" |
77 | #include "i915_vma.h" | 78 | #include "i915_vma.h" |
78 | 79 | ||
@@ -83,8 +84,8 @@ | |||
83 | 84 | ||
84 | #define DRIVER_NAME "i915" | 85 | #define DRIVER_NAME "i915" |
85 | #define DRIVER_DESC "Intel Graphics" | 86 | #define DRIVER_DESC "Intel Graphics" |
86 | #define DRIVER_DATE "20180308" | 87 | #define DRIVER_DATE "20180413" |
87 | #define DRIVER_TIMESTAMP 1520513379 | 88 | #define DRIVER_TIMESTAMP 1523611258 |
88 | 89 | ||
89 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and | 90 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and |
90 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions | 91 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions |
@@ -261,6 +262,7 @@ enum hpd_pin { | |||
261 | HPD_PORT_C, | 262 | HPD_PORT_C, |
262 | HPD_PORT_D, | 263 | HPD_PORT_D, |
263 | HPD_PORT_E, | 264 | HPD_PORT_E, |
265 | HPD_PORT_F, | ||
264 | HPD_NUM_PINS | 266 | HPD_NUM_PINS |
265 | }; | 267 | }; |
266 | 268 | ||
@@ -453,172 +455,6 @@ struct intel_csr { | |||
453 | uint32_t allowed_dc_mask; | 455 | uint32_t allowed_dc_mask; |
454 | }; | 456 | }; |
455 | 457 | ||
456 | struct intel_display_error_state; | ||
457 | |||
458 | struct i915_gpu_state { | ||
459 | struct kref ref; | ||
460 | ktime_t time; | ||
461 | ktime_t boottime; | ||
462 | ktime_t uptime; | ||
463 | |||
464 | struct drm_i915_private *i915; | ||
465 | |||
466 | char error_msg[128]; | ||
467 | bool simulated; | ||
468 | bool awake; | ||
469 | bool wakelock; | ||
470 | bool suspended; | ||
471 | int iommu; | ||
472 | u32 reset_count; | ||
473 | u32 suspend_count; | ||
474 | struct intel_device_info device_info; | ||
475 | struct intel_driver_caps driver_caps; | ||
476 | struct i915_params params; | ||
477 | |||
478 | struct i915_error_uc { | ||
479 | struct intel_uc_fw guc_fw; | ||
480 | struct intel_uc_fw huc_fw; | ||
481 | struct drm_i915_error_object *guc_log; | ||
482 | } uc; | ||
483 | |||
484 | /* Generic register state */ | ||
485 | u32 eir; | ||
486 | u32 pgtbl_er; | ||
487 | u32 ier; | ||
488 | u32 gtier[4], ngtier; | ||
489 | u32 ccid; | ||
490 | u32 derrmr; | ||
491 | u32 forcewake; | ||
492 | u32 error; /* gen6+ */ | ||
493 | u32 err_int; /* gen7 */ | ||
494 | u32 fault_data0; /* gen8, gen9 */ | ||
495 | u32 fault_data1; /* gen8, gen9 */ | ||
496 | u32 done_reg; | ||
497 | u32 gac_eco; | ||
498 | u32 gam_ecochk; | ||
499 | u32 gab_ctl; | ||
500 | u32 gfx_mode; | ||
501 | |||
502 | u32 nfence; | ||
503 | u64 fence[I915_MAX_NUM_FENCES]; | ||
504 | struct intel_overlay_error_state *overlay; | ||
505 | struct intel_display_error_state *display; | ||
506 | |||
507 | struct drm_i915_error_engine { | ||
508 | int engine_id; | ||
509 | /* Software tracked state */ | ||
510 | bool idle; | ||
511 | bool waiting; | ||
512 | int num_waiters; | ||
513 | unsigned long hangcheck_timestamp; | ||
514 | bool hangcheck_stalled; | ||
515 | enum intel_engine_hangcheck_action hangcheck_action; | ||
516 | struct i915_address_space *vm; | ||
517 | int num_requests; | ||
518 | u32 reset_count; | ||
519 | |||
520 | /* position of active request inside the ring */ | ||
521 | u32 rq_head, rq_post, rq_tail; | ||
522 | |||
523 | /* our own tracking of ring head and tail */ | ||
524 | u32 cpu_ring_head; | ||
525 | u32 cpu_ring_tail; | ||
526 | |||
527 | u32 last_seqno; | ||
528 | |||
529 | /* Register state */ | ||
530 | u32 start; | ||
531 | u32 tail; | ||
532 | u32 head; | ||
533 | u32 ctl; | ||
534 | u32 mode; | ||
535 | u32 hws; | ||
536 | u32 ipeir; | ||
537 | u32 ipehr; | ||
538 | u32 bbstate; | ||
539 | u32 instpm; | ||
540 | u32 instps; | ||
541 | u32 seqno; | ||
542 | u64 bbaddr; | ||
543 | u64 acthd; | ||
544 | u32 fault_reg; | ||
545 | u64 faddr; | ||
546 | u32 rc_psmi; /* sleep state */ | ||
547 | u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; | ||
548 | struct intel_instdone instdone; | ||
549 | |||
550 | struct drm_i915_error_context { | ||
551 | char comm[TASK_COMM_LEN]; | ||
552 | pid_t pid; | ||
553 | u32 handle; | ||
554 | u32 hw_id; | ||
555 | int priority; | ||
556 | int ban_score; | ||
557 | int active; | ||
558 | int guilty; | ||
559 | bool bannable; | ||
560 | } context; | ||
561 | |||
562 | struct drm_i915_error_object { | ||
563 | u64 gtt_offset; | ||
564 | u64 gtt_size; | ||
565 | int page_count; | ||
566 | int unused; | ||
567 | u32 *pages[0]; | ||
568 | } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; | ||
569 | |||
570 | struct drm_i915_error_object **user_bo; | ||
571 | long user_bo_count; | ||
572 | |||
573 | struct drm_i915_error_object *wa_ctx; | ||
574 | struct drm_i915_error_object *default_state; | ||
575 | |||
576 | struct drm_i915_error_request { | ||
577 | long jiffies; | ||
578 | pid_t pid; | ||
579 | u32 context; | ||
580 | int priority; | ||
581 | int ban_score; | ||
582 | u32 seqno; | ||
583 | u32 head; | ||
584 | u32 tail; | ||
585 | } *requests, execlist[EXECLIST_MAX_PORTS]; | ||
586 | unsigned int num_ports; | ||
587 | |||
588 | struct drm_i915_error_waiter { | ||
589 | char comm[TASK_COMM_LEN]; | ||
590 | pid_t pid; | ||
591 | u32 seqno; | ||
592 | } *waiters; | ||
593 | |||
594 | struct { | ||
595 | u32 gfx_mode; | ||
596 | union { | ||
597 | u64 pdp[4]; | ||
598 | u32 pp_dir_base; | ||
599 | }; | ||
600 | } vm_info; | ||
601 | } engine[I915_NUM_ENGINES]; | ||
602 | |||
603 | struct drm_i915_error_buffer { | ||
604 | u32 size; | ||
605 | u32 name; | ||
606 | u32 rseqno[I915_NUM_ENGINES], wseqno; | ||
607 | u64 gtt_offset; | ||
608 | u32 read_domains; | ||
609 | u32 write_domain; | ||
610 | s32 fence_reg:I915_MAX_NUM_FENCE_BITS; | ||
611 | u32 tiling:2; | ||
612 | u32 dirty:1; | ||
613 | u32 purgeable:1; | ||
614 | u32 userptr:1; | ||
615 | s32 engine:4; | ||
616 | u32 cache_level:3; | ||
617 | } *active_bo[I915_NUM_ENGINES], *pinned_bo; | ||
618 | u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count; | ||
619 | struct i915_address_space *active_vm[I915_NUM_ENGINES]; | ||
620 | }; | ||
621 | |||
622 | enum i915_cache_level { | 458 | enum i915_cache_level { |
623 | I915_CACHE_NONE = 0, | 459 | I915_CACHE_NONE = 0, |
624 | I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */ | 460 | I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */ |
@@ -766,12 +602,13 @@ struct i915_psr { | |||
766 | bool active; | 602 | bool active; |
767 | struct delayed_work work; | 603 | struct delayed_work work; |
768 | unsigned busy_frontbuffer_bits; | 604 | unsigned busy_frontbuffer_bits; |
769 | bool psr2_support; | 605 | bool sink_psr2_support; |
770 | bool aux_frame_sync; | ||
771 | bool link_standby; | 606 | bool link_standby; |
772 | bool y_cord_support; | ||
773 | bool colorimetry_support; | 607 | bool colorimetry_support; |
774 | bool alpm; | 608 | bool alpm; |
609 | bool has_hw_tracking; | ||
610 | bool psr2_enabled; | ||
611 | u8 sink_sync_latency; | ||
775 | 612 | ||
776 | void (*enable_source)(struct intel_dp *, | 613 | void (*enable_source)(struct intel_dp *, |
777 | const struct intel_crtc_state *); | 614 | const struct intel_crtc_state *); |
@@ -1146,16 +983,6 @@ struct i915_gem_mm { | |||
1146 | u32 object_count; | 983 | u32 object_count; |
1147 | }; | 984 | }; |
1148 | 985 | ||
1149 | struct drm_i915_error_state_buf { | ||
1150 | struct drm_i915_private *i915; | ||
1151 | unsigned bytes; | ||
1152 | unsigned size; | ||
1153 | int err; | ||
1154 | u8 *buf; | ||
1155 | loff_t start; | ||
1156 | loff_t pos; | ||
1157 | }; | ||
1158 | |||
1159 | #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ | 986 | #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ |
1160 | 987 | ||
1161 | #define I915_RESET_TIMEOUT (10 * HZ) /* 10s */ | 988 | #define I915_RESET_TIMEOUT (10 * HZ) /* 10s */ |
@@ -1164,102 +991,6 @@ struct drm_i915_error_state_buf { | |||
1164 | #define I915_ENGINE_DEAD_TIMEOUT (4 * HZ) /* Seqno, head and subunits dead */ | 991 | #define I915_ENGINE_DEAD_TIMEOUT (4 * HZ) /* Seqno, head and subunits dead */ |
1165 | #define I915_SEQNO_DEAD_TIMEOUT (12 * HZ) /* Seqno dead with active head */ | 992 | #define I915_SEQNO_DEAD_TIMEOUT (12 * HZ) /* Seqno dead with active head */ |
1166 | 993 | ||
1167 | struct i915_gpu_error { | ||
1168 | /* For hangcheck timer */ | ||
1169 | #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ | ||
1170 | #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) | ||
1171 | |||
1172 | struct delayed_work hangcheck_work; | ||
1173 | |||
1174 | /* For reset and error_state handling. */ | ||
1175 | spinlock_t lock; | ||
1176 | /* Protected by the above dev->gpu_error.lock. */ | ||
1177 | struct i915_gpu_state *first_error; | ||
1178 | |||
1179 | atomic_t pending_fb_pin; | ||
1180 | |||
1181 | unsigned long missed_irq_rings; | ||
1182 | |||
1183 | /** | ||
1184 | * State variable controlling the reset flow and count | ||
1185 | * | ||
1186 | * This is a counter which gets incremented when reset is triggered, | ||
1187 | * | ||
1188 | * Before the reset commences, the I915_RESET_BACKOFF bit is set | ||
1189 | * meaning that any waiters holding onto the struct_mutex should | ||
1190 | * relinquish the lock immediately in order for the reset to start. | ||
1191 | * | ||
1192 | * If reset is not completed succesfully, the I915_WEDGE bit is | ||
1193 | * set meaning that hardware is terminally sour and there is no | ||
1194 | * recovery. All waiters on the reset_queue will be woken when | ||
1195 | * that happens. | ||
1196 | * | ||
1197 | * This counter is used by the wait_seqno code to notice that reset | ||
1198 | * event happened and it needs to restart the entire ioctl (since most | ||
1199 | * likely the seqno it waited for won't ever signal anytime soon). | ||
1200 | * | ||
1201 | * This is important for lock-free wait paths, where no contended lock | ||
1202 | * naturally enforces the correct ordering between the bail-out of the | ||
1203 | * waiter and the gpu reset work code. | ||
1204 | */ | ||
1205 | unsigned long reset_count; | ||
1206 | |||
1207 | /** | ||
1208 | * flags: Control various stages of the GPU reset | ||
1209 | * | ||
1210 | * #I915_RESET_BACKOFF - When we start a reset, we want to stop any | ||
1211 | * other users acquiring the struct_mutex. To do this we set the | ||
1212 | * #I915_RESET_BACKOFF bit in the error flags when we detect a reset | ||
1213 | * and then check for that bit before acquiring the struct_mutex (in | ||
1214 | * i915_mutex_lock_interruptible()?). I915_RESET_BACKOFF serves a | ||
1215 | * secondary role in preventing two concurrent global reset attempts. | ||
1216 | * | ||
1217 | * #I915_RESET_HANDOFF - To perform the actual GPU reset, we need the | ||
1218 | * struct_mutex. We try to acquire the struct_mutex in the reset worker, | ||
1219 | * but it may be held by some long running waiter (that we cannot | ||
1220 | * interrupt without causing trouble). Once we are ready to do the GPU | ||
1221 | * reset, we set the I915_RESET_HANDOFF bit and wakeup any waiters. If | ||
1222 | * they already hold the struct_mutex and want to participate they can | ||
1223 | * inspect the bit and do the reset directly, otherwise the worker | ||
1224 | * waits for the struct_mutex. | ||
1225 | * | ||
1226 | * #I915_RESET_ENGINE[num_engines] - Since the driver doesn't need to | ||
1227 | * acquire the struct_mutex to reset an engine, we need an explicit | ||
1228 | * flag to prevent two concurrent reset attempts in the same engine. | ||
1229 | * As the number of engines continues to grow, allocate the flags from | ||
1230 | * the most significant bits. | ||
1231 | * | ||
1232 | * #I915_WEDGED - If reset fails and we can no longer use the GPU, | ||
1233 | * we set the #I915_WEDGED bit. Prior to command submission, e.g. | ||
1234 | * i915_request_alloc(), this bit is checked and the sequence | ||
1235 | * aborted (with -EIO reported to userspace) if set. | ||
1236 | */ | ||
1237 | unsigned long flags; | ||
1238 | #define I915_RESET_BACKOFF 0 | ||
1239 | #define I915_RESET_HANDOFF 1 | ||
1240 | #define I915_RESET_MODESET 2 | ||
1241 | #define I915_WEDGED (BITS_PER_LONG - 1) | ||
1242 | #define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES) | ||
1243 | |||
1244 | /** Number of times an engine has been reset */ | ||
1245 | u32 reset_engine_count[I915_NUM_ENGINES]; | ||
1246 | |||
1247 | /** | ||
1248 | * Waitqueue to signal when a hang is detected. Used to for waiters | ||
1249 | * to release the struct_mutex for the reset to procede. | ||
1250 | */ | ||
1251 | wait_queue_head_t wait_queue; | ||
1252 | |||
1253 | /** | ||
1254 | * Waitqueue to signal when the reset has completed. Used by clients | ||
1255 | * that wait for dev_priv->mm.wedged to settle. | ||
1256 | */ | ||
1257 | wait_queue_head_t reset_queue; | ||
1258 | |||
1259 | /* For missed irq/seqno simulation. */ | ||
1260 | unsigned long test_irq_rings; | ||
1261 | }; | ||
1262 | |||
1263 | enum modeset_restore { | 994 | enum modeset_restore { |
1264 | MODESET_ON_LID_OPEN, | 995 | MODESET_ON_LID_OPEN, |
1265 | MODESET_DONE, | 996 | MODESET_DONE, |
@@ -1451,11 +1182,12 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, | |||
1451 | } | 1182 | } |
1452 | 1183 | ||
1453 | struct skl_ddb_allocation { | 1184 | struct skl_ddb_allocation { |
1454 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ | 1185 | /* packed/y */ |
1455 | struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; | 1186 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; |
1187 | struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES]; | ||
1456 | }; | 1188 | }; |
1457 | 1189 | ||
1458 | struct skl_wm_values { | 1190 | struct skl_ddb_values { |
1459 | unsigned dirty_pipes; | 1191 | unsigned dirty_pipes; |
1460 | struct skl_ddb_allocation ddb; | 1192 | struct skl_ddb_allocation ddb; |
1461 | }; | 1193 | }; |
@@ -1470,6 +1202,7 @@ struct skl_wm_level { | |||
1470 | struct skl_wm_params { | 1202 | struct skl_wm_params { |
1471 | bool x_tiled, y_tiled; | 1203 | bool x_tiled, y_tiled; |
1472 | bool rc_surface; | 1204 | bool rc_surface; |
1205 | bool is_planar; | ||
1473 | uint32_t width; | 1206 | uint32_t width; |
1474 | uint8_t cpp; | 1207 | uint8_t cpp; |
1475 | uint32_t plane_pixel_rate; | 1208 | uint32_t plane_pixel_rate; |
@@ -1860,6 +1593,8 @@ struct drm_i915_private { | |||
1860 | 1593 | ||
1861 | struct intel_gvt *gvt; | 1594 | struct intel_gvt *gvt; |
1862 | 1595 | ||
1596 | struct intel_wopcm wopcm; | ||
1597 | |||
1863 | struct intel_huc huc; | 1598 | struct intel_huc huc; |
1864 | struct intel_guc guc; | 1599 | struct intel_guc guc; |
1865 | 1600 | ||
@@ -2152,7 +1887,7 @@ struct drm_i915_private { | |||
2152 | /* current hardware state */ | 1887 | /* current hardware state */ |
2153 | union { | 1888 | union { |
2154 | struct ilk_wm_values hw; | 1889 | struct ilk_wm_values hw; |
2155 | struct skl_wm_values skl_hw; | 1890 | struct skl_ddb_values skl_hw; |
2156 | struct vlv_wm_values vlv; | 1891 | struct vlv_wm_values vlv; |
2157 | struct g4x_wm_values g4x; | 1892 | struct g4x_wm_values g4x; |
2158 | }; | 1893 | }; |
@@ -2392,6 +2127,11 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev) | |||
2392 | return to_i915(dev_get_drvdata(kdev)); | 2127 | return to_i915(dev_get_drvdata(kdev)); |
2393 | } | 2128 | } |
2394 | 2129 | ||
2130 | static inline struct drm_i915_private *wopcm_to_i915(struct intel_wopcm *wopcm) | ||
2131 | { | ||
2132 | return container_of(wopcm, struct drm_i915_private, wopcm); | ||
2133 | } | ||
2134 | |||
2395 | static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) | 2135 | static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) |
2396 | { | 2136 | { |
2397 | return container_of(guc, struct drm_i915_private, guc); | 2137 | return container_of(guc, struct drm_i915_private, guc); |
@@ -2411,8 +2151,10 @@ static inline struct drm_i915_private *huc_to_i915(struct intel_huc *huc) | |||
2411 | 2151 | ||
2412 | /* Iterator over subset of engines selected by mask */ | 2152 | /* Iterator over subset of engines selected by mask */ |
2413 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ | 2153 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ |
2414 | for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ | 2154 | for ((tmp__) = (mask__) & INTEL_INFO(dev_priv__)->ring_mask; \ |
2415 | tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) | 2155 | (tmp__) ? \ |
2156 | ((engine__) = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : \ | ||
2157 | 0;) | ||
2416 | 2158 | ||
2417 | enum hdmi_force_audio { | 2159 | enum hdmi_force_audio { |
2418 | HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ | 2160 | HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ |
@@ -2963,10 +2705,11 @@ extern void i915_driver_unload(struct drm_device *dev); | |||
2963 | extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); | 2705 | extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); |
2964 | extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); | 2706 | extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); |
2965 | 2707 | ||
2966 | #define I915_RESET_QUIET BIT(0) | 2708 | extern void i915_reset(struct drm_i915_private *i915, |
2967 | extern void i915_reset(struct drm_i915_private *i915, unsigned int flags); | 2709 | unsigned int stalled_mask, |
2710 | const char *reason); | ||
2968 | extern int i915_reset_engine(struct intel_engine_cs *engine, | 2711 | extern int i915_reset_engine(struct intel_engine_cs *engine, |
2969 | unsigned int flags); | 2712 | const char *reason); |
2970 | 2713 | ||
2971 | extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv); | 2714 | extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv); |
2972 | extern int intel_reset_guc(struct drm_i915_private *dev_priv); | 2715 | extern int intel_reset_guc(struct drm_i915_private *dev_priv); |
@@ -3014,10 +2757,12 @@ static inline void i915_queue_hangcheck(struct drm_i915_private *dev_priv) | |||
3014 | &dev_priv->gpu_error.hangcheck_work, delay); | 2757 | &dev_priv->gpu_error.hangcheck_work, delay); |
3015 | } | 2758 | } |
3016 | 2759 | ||
3017 | __printf(3, 4) | 2760 | __printf(4, 5) |
3018 | void i915_handle_error(struct drm_i915_private *dev_priv, | 2761 | void i915_handle_error(struct drm_i915_private *dev_priv, |
3019 | u32 engine_mask, | 2762 | u32 engine_mask, |
2763 | unsigned long flags, | ||
3020 | const char *fmt, ...); | 2764 | const char *fmt, ...); |
2765 | #define I915_ERROR_CAPTURE BIT(0) | ||
3021 | 2766 | ||
3022 | extern void intel_irq_init(struct drm_i915_private *dev_priv); | 2767 | extern void intel_irq_init(struct drm_i915_private *dev_priv); |
3023 | extern void intel_irq_fini(struct drm_i915_private *dev_priv); | 2768 | extern void intel_irq_fini(struct drm_i915_private *dev_priv); |
@@ -3132,8 +2877,8 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | |||
3132 | int i915_gem_wait_ioctl(struct drm_device *dev, void *data, | 2877 | int i915_gem_wait_ioctl(struct drm_device *dev, void *data, |
3133 | struct drm_file *file_priv); | 2878 | struct drm_file *file_priv); |
3134 | void i915_gem_sanitize(struct drm_i915_private *i915); | 2879 | void i915_gem_sanitize(struct drm_i915_private *i915); |
3135 | int i915_gem_load_init(struct drm_i915_private *dev_priv); | 2880 | int i915_gem_init_early(struct drm_i915_private *dev_priv); |
3136 | void i915_gem_load_cleanup(struct drm_i915_private *dev_priv); | 2881 | void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); |
3137 | void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); | 2882 | void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); |
3138 | int i915_gem_freeze(struct drm_i915_private *dev_priv); | 2883 | int i915_gem_freeze(struct drm_i915_private *dev_priv); |
3139 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv); | 2884 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv); |
@@ -3388,13 +3133,15 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, | |||
3388 | struct i915_request * | 3133 | struct i915_request * |
3389 | i915_gem_reset_prepare_engine(struct intel_engine_cs *engine); | 3134 | i915_gem_reset_prepare_engine(struct intel_engine_cs *engine); |
3390 | int i915_gem_reset_prepare(struct drm_i915_private *dev_priv); | 3135 | int i915_gem_reset_prepare(struct drm_i915_private *dev_priv); |
3391 | void i915_gem_reset(struct drm_i915_private *dev_priv); | 3136 | void i915_gem_reset(struct drm_i915_private *dev_priv, |
3137 | unsigned int stalled_mask); | ||
3392 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine); | 3138 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine); |
3393 | void i915_gem_reset_finish(struct drm_i915_private *dev_priv); | 3139 | void i915_gem_reset_finish(struct drm_i915_private *dev_priv); |
3394 | void i915_gem_set_wedged(struct drm_i915_private *dev_priv); | 3140 | void i915_gem_set_wedged(struct drm_i915_private *dev_priv); |
3395 | bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv); | 3141 | bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv); |
3396 | void i915_gem_reset_engine(struct intel_engine_cs *engine, | 3142 | void i915_gem_reset_engine(struct intel_engine_cs *engine, |
3397 | struct i915_request *request); | 3143 | struct i915_request *request, |
3144 | bool stalled); | ||
3398 | 3145 | ||
3399 | void i915_gem_init_mmio(struct drm_i915_private *i915); | 3146 | void i915_gem_init_mmio(struct drm_i915_private *i915); |
3400 | int __must_check i915_gem_init(struct drm_i915_private *dev_priv); | 3147 | int __must_check i915_gem_init(struct drm_i915_private *dev_priv); |
@@ -3589,64 +3336,6 @@ static inline int i915_debugfs_connector_add(struct drm_connector *connector) | |||
3589 | static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {} | 3336 | static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {} |
3590 | #endif | 3337 | #endif |
3591 | 3338 | ||
3592 | /* i915_gpu_error.c */ | ||
3593 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
3594 | |||
3595 | __printf(2, 3) | ||
3596 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); | ||
3597 | int i915_error_state_to_str(struct drm_i915_error_state_buf *estr, | ||
3598 | const struct i915_gpu_state *gpu); | ||
3599 | int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb, | ||
3600 | struct drm_i915_private *i915, | ||
3601 | size_t count, loff_t pos); | ||
3602 | static inline void i915_error_state_buf_release( | ||
3603 | struct drm_i915_error_state_buf *eb) | ||
3604 | { | ||
3605 | kfree(eb->buf); | ||
3606 | } | ||
3607 | |||
3608 | struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915); | ||
3609 | void i915_capture_error_state(struct drm_i915_private *dev_priv, | ||
3610 | u32 engine_mask, | ||
3611 | const char *error_msg); | ||
3612 | |||
3613 | static inline struct i915_gpu_state * | ||
3614 | i915_gpu_state_get(struct i915_gpu_state *gpu) | ||
3615 | { | ||
3616 | kref_get(&gpu->ref); | ||
3617 | return gpu; | ||
3618 | } | ||
3619 | |||
3620 | void __i915_gpu_state_free(struct kref *kref); | ||
3621 | static inline void i915_gpu_state_put(struct i915_gpu_state *gpu) | ||
3622 | { | ||
3623 | if (gpu) | ||
3624 | kref_put(&gpu->ref, __i915_gpu_state_free); | ||
3625 | } | ||
3626 | |||
3627 | struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915); | ||
3628 | void i915_reset_error_state(struct drm_i915_private *i915); | ||
3629 | |||
3630 | #else | ||
3631 | |||
3632 | static inline void i915_capture_error_state(struct drm_i915_private *dev_priv, | ||
3633 | u32 engine_mask, | ||
3634 | const char *error_msg) | ||
3635 | { | ||
3636 | } | ||
3637 | |||
3638 | static inline struct i915_gpu_state * | ||
3639 | i915_first_error_state(struct drm_i915_private *i915) | ||
3640 | { | ||
3641 | return NULL; | ||
3642 | } | ||
3643 | |||
3644 | static inline void i915_reset_error_state(struct drm_i915_private *i915) | ||
3645 | { | ||
3646 | } | ||
3647 | |||
3648 | #endif | ||
3649 | |||
3650 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type); | 3339 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type); |
3651 | 3340 | ||
3652 | /* i915_cmd_parser.c */ | 3341 | /* i915_cmd_parser.c */ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7b5a9d7c9593..4c9d2a6f7d28 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
36 | #include "intel_frontbuffer.h" | 36 | #include "intel_frontbuffer.h" |
37 | #include "intel_mocs.h" | 37 | #include "intel_mocs.h" |
38 | #include "intel_workarounds.h" | ||
38 | #include "i915_gemfs.h" | 39 | #include "i915_gemfs.h" |
39 | #include <linux/dma-fence-array.h> | 40 | #include <linux/dma-fence-array.h> |
40 | #include <linux/kthread.h> | 41 | #include <linux/kthread.h> |
@@ -136,6 +137,100 @@ int i915_mutex_lock_interruptible(struct drm_device *dev) | |||
136 | return 0; | 137 | return 0; |
137 | } | 138 | } |
138 | 139 | ||
140 | static u32 __i915_gem_park(struct drm_i915_private *i915) | ||
141 | { | ||
142 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
143 | GEM_BUG_ON(i915->gt.active_requests); | ||
144 | |||
145 | if (!i915->gt.awake) | ||
146 | return I915_EPOCH_INVALID; | ||
147 | |||
148 | GEM_BUG_ON(i915->gt.epoch == I915_EPOCH_INVALID); | ||
149 | |||
150 | /* | ||
151 | * Be paranoid and flush a concurrent interrupt to make sure | ||
152 | * we don't reactivate any irq tasklets after parking. | ||
153 | * | ||
154 | * FIXME: Note that even though we have waited for execlists to be idle, | ||
155 | * there may still be an in-flight interrupt even though the CSB | ||
156 | * is now empty. synchronize_irq() makes sure that a residual interrupt | ||
157 | * is completed before we continue, but it doesn't prevent the HW from | ||
158 | * raising a spurious interrupt later. To complete the shield we should | ||
159 | * coordinate disabling the CS irq with flushing the interrupts. | ||
160 | */ | ||
161 | synchronize_irq(i915->drm.irq); | ||
162 | |||
163 | intel_engines_park(i915); | ||
164 | i915_gem_timelines_park(i915); | ||
165 | |||
166 | i915_pmu_gt_parked(i915); | ||
167 | |||
168 | i915->gt.awake = false; | ||
169 | |||
170 | if (INTEL_GEN(i915) >= 6) | ||
171 | gen6_rps_idle(i915); | ||
172 | |||
173 | intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ); | ||
174 | |||
175 | intel_runtime_pm_put(i915); | ||
176 | |||
177 | return i915->gt.epoch; | ||
178 | } | ||
179 | |||
180 | void i915_gem_park(struct drm_i915_private *i915) | ||
181 | { | ||
182 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
183 | GEM_BUG_ON(i915->gt.active_requests); | ||
184 | |||
185 | if (!i915->gt.awake) | ||
186 | return; | ||
187 | |||
188 | /* Defer the actual call to __i915_gem_park() to prevent ping-pongs */ | ||
189 | mod_delayed_work(i915->wq, &i915->gt.idle_work, msecs_to_jiffies(100)); | ||
190 | } | ||
191 | |||
192 | void i915_gem_unpark(struct drm_i915_private *i915) | ||
193 | { | ||
194 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
195 | GEM_BUG_ON(!i915->gt.active_requests); | ||
196 | |||
197 | if (i915->gt.awake) | ||
198 | return; | ||
199 | |||
200 | intel_runtime_pm_get_noresume(i915); | ||
201 | |||
202 | /* | ||
203 | * It seems that the DMC likes to transition between the DC states a lot | ||
204 | * when there are no connected displays (no active power domains) during | ||
205 | * command submission. | ||
206 | * | ||
207 | * This activity has negative impact on the performance of the chip with | ||
208 | * huge latencies observed in the interrupt handler and elsewhere. | ||
209 | * | ||
210 | * Work around it by grabbing a GT IRQ power domain whilst there is any | ||
211 | * GT activity, preventing any DC state transitions. | ||
212 | */ | ||
213 | intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ); | ||
214 | |||
215 | i915->gt.awake = true; | ||
216 | if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */ | ||
217 | i915->gt.epoch = 1; | ||
218 | |||
219 | intel_enable_gt_powersave(i915); | ||
220 | i915_update_gfx_val(i915); | ||
221 | if (INTEL_GEN(i915) >= 6) | ||
222 | gen6_rps_busy(i915); | ||
223 | i915_pmu_gt_unparked(i915); | ||
224 | |||
225 | intel_engines_unpark(i915); | ||
226 | |||
227 | i915_queue_hangcheck(i915); | ||
228 | |||
229 | queue_delayed_work(i915->wq, | ||
230 | &i915->gt.retire_work, | ||
231 | round_jiffies_up_relative(HZ)); | ||
232 | } | ||
233 | |||
139 | int | 234 | int |
140 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | 235 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
141 | struct drm_file *file) | 236 | struct drm_file *file) |
@@ -2896,20 +2991,6 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) | |||
2896 | return active; | 2991 | return active; |
2897 | } | 2992 | } |
2898 | 2993 | ||
2899 | static bool engine_stalled(struct intel_engine_cs *engine) | ||
2900 | { | ||
2901 | if (!engine->hangcheck.stalled) | ||
2902 | return false; | ||
2903 | |||
2904 | /* Check for possible seqno movement after hang declaration */ | ||
2905 | if (engine->hangcheck.seqno != intel_engine_get_seqno(engine)) { | ||
2906 | DRM_DEBUG_DRIVER("%s pardoned\n", engine->name); | ||
2907 | return false; | ||
2908 | } | ||
2909 | |||
2910 | return true; | ||
2911 | } | ||
2912 | |||
2913 | /* | 2994 | /* |
2914 | * Ensure irq handler finishes, and not run again. | 2995 | * Ensure irq handler finishes, and not run again. |
2915 | * Also return the active request so that we only search for it once. | 2996 | * Also return the active request so that we only search for it once. |
@@ -2998,6 +3079,7 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv) | |||
2998 | } | 3079 | } |
2999 | 3080 | ||
3000 | i915_gem_revoke_fences(dev_priv); | 3081 | i915_gem_revoke_fences(dev_priv); |
3082 | intel_uc_sanitize(dev_priv); | ||
3001 | 3083 | ||
3002 | return err; | 3084 | return err; |
3003 | } | 3085 | } |
@@ -3047,7 +3129,8 @@ static void engine_skip_context(struct i915_request *request) | |||
3047 | /* Returns the request if it was guilty of the hang */ | 3129 | /* Returns the request if it was guilty of the hang */ |
3048 | static struct i915_request * | 3130 | static struct i915_request * |
3049 | i915_gem_reset_request(struct intel_engine_cs *engine, | 3131 | i915_gem_reset_request(struct intel_engine_cs *engine, |
3050 | struct i915_request *request) | 3132 | struct i915_request *request, |
3133 | bool stalled) | ||
3051 | { | 3134 | { |
3052 | /* The guilty request will get skipped on a hung engine. | 3135 | /* The guilty request will get skipped on a hung engine. |
3053 | * | 3136 | * |
@@ -3070,7 +3153,15 @@ i915_gem_reset_request(struct intel_engine_cs *engine, | |||
3070 | * subsequent hangs. | 3153 | * subsequent hangs. |
3071 | */ | 3154 | */ |
3072 | 3155 | ||
3073 | if (engine_stalled(engine)) { | 3156 | if (i915_request_completed(request)) { |
3157 | GEM_TRACE("%s pardoned global=%d (fence %llx:%d), current %d\n", | ||
3158 | engine->name, request->global_seqno, | ||
3159 | request->fence.context, request->fence.seqno, | ||
3160 | intel_engine_get_seqno(engine)); | ||
3161 | stalled = false; | ||
3162 | } | ||
3163 | |||
3164 | if (stalled) { | ||
3074 | i915_gem_context_mark_guilty(request->ctx); | 3165 | i915_gem_context_mark_guilty(request->ctx); |
3075 | skip_request(request); | 3166 | skip_request(request); |
3076 | 3167 | ||
@@ -3101,7 +3192,8 @@ i915_gem_reset_request(struct intel_engine_cs *engine, | |||
3101 | } | 3192 | } |
3102 | 3193 | ||
3103 | void i915_gem_reset_engine(struct intel_engine_cs *engine, | 3194 | void i915_gem_reset_engine(struct intel_engine_cs *engine, |
3104 | struct i915_request *request) | 3195 | struct i915_request *request, |
3196 | bool stalled) | ||
3105 | { | 3197 | { |
3106 | /* | 3198 | /* |
3107 | * Make sure this write is visible before we re-enable the interrupt | 3199 | * Make sure this write is visible before we re-enable the interrupt |
@@ -3111,7 +3203,7 @@ void i915_gem_reset_engine(struct intel_engine_cs *engine, | |||
3111 | smp_store_mb(engine->irq_posted, 0); | 3203 | smp_store_mb(engine->irq_posted, 0); |
3112 | 3204 | ||
3113 | if (request) | 3205 | if (request) |
3114 | request = i915_gem_reset_request(engine, request); | 3206 | request = i915_gem_reset_request(engine, request, stalled); |
3115 | 3207 | ||
3116 | if (request) { | 3208 | if (request) { |
3117 | DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", | 3209 | DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", |
@@ -3122,7 +3214,8 @@ void i915_gem_reset_engine(struct intel_engine_cs *engine, | |||
3122 | engine->reset_hw(engine, request); | 3214 | engine->reset_hw(engine, request); |
3123 | } | 3215 | } |
3124 | 3216 | ||
3125 | void i915_gem_reset(struct drm_i915_private *dev_priv) | 3217 | void i915_gem_reset(struct drm_i915_private *dev_priv, |
3218 | unsigned int stalled_mask) | ||
3126 | { | 3219 | { |
3127 | struct intel_engine_cs *engine; | 3220 | struct intel_engine_cs *engine; |
3128 | enum intel_engine_id id; | 3221 | enum intel_engine_id id; |
@@ -3134,7 +3227,9 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) | |||
3134 | for_each_engine(engine, dev_priv, id) { | 3227 | for_each_engine(engine, dev_priv, id) { |
3135 | struct i915_gem_context *ctx; | 3228 | struct i915_gem_context *ctx; |
3136 | 3229 | ||
3137 | i915_gem_reset_engine(engine, engine->hangcheck.active_request); | 3230 | i915_gem_reset_engine(engine, |
3231 | engine->hangcheck.active_request, | ||
3232 | stalled_mask & ENGINE_MASK(id)); | ||
3138 | ctx = fetch_and_zero(&engine->last_retired_context); | 3233 | ctx = fetch_and_zero(&engine->last_retired_context); |
3139 | if (ctx) | 3234 | if (ctx) |
3140 | engine->context_unpin(engine, ctx); | 3235 | engine->context_unpin(engine, ctx); |
@@ -3160,13 +3255,6 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) | |||
3160 | } | 3255 | } |
3161 | 3256 | ||
3162 | i915_gem_restore_fences(dev_priv); | 3257 | i915_gem_restore_fences(dev_priv); |
3163 | |||
3164 | if (dev_priv->gt.awake) { | ||
3165 | intel_sanitize_gt_powersave(dev_priv); | ||
3166 | intel_enable_gt_powersave(dev_priv); | ||
3167 | if (INTEL_GEN(dev_priv) >= 6) | ||
3168 | gen6_rps_busy(dev_priv); | ||
3169 | } | ||
3170 | } | 3258 | } |
3171 | 3259 | ||
3172 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) | 3260 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) |
@@ -3192,6 +3280,9 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv) | |||
3192 | 3280 | ||
3193 | static void nop_submit_request(struct i915_request *request) | 3281 | static void nop_submit_request(struct i915_request *request) |
3194 | { | 3282 | { |
3283 | GEM_TRACE("%s fence %llx:%d -> -EIO\n", | ||
3284 | request->engine->name, | ||
3285 | request->fence.context, request->fence.seqno); | ||
3195 | dma_fence_set_error(&request->fence, -EIO); | 3286 | dma_fence_set_error(&request->fence, -EIO); |
3196 | 3287 | ||
3197 | i915_request_submit(request); | 3288 | i915_request_submit(request); |
@@ -3201,6 +3292,9 @@ static void nop_complete_submit_request(struct i915_request *request) | |||
3201 | { | 3292 | { |
3202 | unsigned long flags; | 3293 | unsigned long flags; |
3203 | 3294 | ||
3295 | GEM_TRACE("%s fence %llx:%d -> -EIO\n", | ||
3296 | request->engine->name, | ||
3297 | request->fence.context, request->fence.seqno); | ||
3204 | dma_fence_set_error(&request->fence, -EIO); | 3298 | dma_fence_set_error(&request->fence, -EIO); |
3205 | 3299 | ||
3206 | spin_lock_irqsave(&request->engine->timeline->lock, flags); | 3300 | spin_lock_irqsave(&request->engine->timeline->lock, flags); |
@@ -3214,6 +3308,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3214 | struct intel_engine_cs *engine; | 3308 | struct intel_engine_cs *engine; |
3215 | enum intel_engine_id id; | 3309 | enum intel_engine_id id; |
3216 | 3310 | ||
3311 | GEM_TRACE("start\n"); | ||
3312 | |||
3217 | if (drm_debug & DRM_UT_DRIVER) { | 3313 | if (drm_debug & DRM_UT_DRIVER) { |
3218 | struct drm_printer p = drm_debug_printer(__func__); | 3314 | struct drm_printer p = drm_debug_printer(__func__); |
3219 | 3315 | ||
@@ -3237,6 +3333,9 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3237 | } | 3333 | } |
3238 | i915->caps.scheduler = 0; | 3334 | i915->caps.scheduler = 0; |
3239 | 3335 | ||
3336 | /* Even if the GPU reset fails, it should still stop the engines */ | ||
3337 | intel_gpu_reset(i915, ALL_ENGINES); | ||
3338 | |||
3240 | /* | 3339 | /* |
3241 | * Make sure no one is running the old callback before we proceed with | 3340 | * Make sure no one is running the old callback before we proceed with |
3242 | * cancelling requests and resetting the completion tracking. Otherwise | 3341 | * cancelling requests and resetting the completion tracking. Otherwise |
@@ -3278,6 +3377,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3278 | i915_gem_reset_finish_engine(engine); | 3377 | i915_gem_reset_finish_engine(engine); |
3279 | } | 3378 | } |
3280 | 3379 | ||
3380 | GEM_TRACE("end\n"); | ||
3381 | |||
3281 | wake_up_all(&i915->gpu_error.reset_queue); | 3382 | wake_up_all(&i915->gpu_error.reset_queue); |
3282 | } | 3383 | } |
3283 | 3384 | ||
@@ -3290,7 +3391,10 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) | |||
3290 | if (!test_bit(I915_WEDGED, &i915->gpu_error.flags)) | 3391 | if (!test_bit(I915_WEDGED, &i915->gpu_error.flags)) |
3291 | return true; | 3392 | return true; |
3292 | 3393 | ||
3293 | /* Before unwedging, make sure that all pending operations | 3394 | GEM_TRACE("start\n"); |
3395 | |||
3396 | /* | ||
3397 | * Before unwedging, make sure that all pending operations | ||
3294 | * are flushed and errored out - we may have requests waiting upon | 3398 | * are flushed and errored out - we may have requests waiting upon |
3295 | * third party fences. We marked all inflight requests as EIO, and | 3399 | * third party fences. We marked all inflight requests as EIO, and |
3296 | * every execbuf since returned EIO, for consistency we want all | 3400 | * every execbuf since returned EIO, for consistency we want all |
@@ -3308,7 +3412,8 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) | |||
3308 | if (!rq) | 3412 | if (!rq) |
3309 | continue; | 3413 | continue; |
3310 | 3414 | ||
3311 | /* We can't use our normal waiter as we want to | 3415 | /* |
3416 | * We can't use our normal waiter as we want to | ||
3312 | * avoid recursively trying to handle the current | 3417 | * avoid recursively trying to handle the current |
3313 | * reset. The basic dma_fence_default_wait() installs | 3418 | * reset. The basic dma_fence_default_wait() installs |
3314 | * a callback for dma_fence_signal(), which is | 3419 | * a callback for dma_fence_signal(), which is |
@@ -3323,8 +3428,11 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) | |||
3323 | return false; | 3428 | return false; |
3324 | } | 3429 | } |
3325 | } | 3430 | } |
3431 | i915_retire_requests(i915); | ||
3432 | GEM_BUG_ON(i915->gt.active_requests); | ||
3326 | 3433 | ||
3327 | /* Undo nop_submit_request. We prevent all new i915 requests from | 3434 | /* |
3435 | * Undo nop_submit_request. We prevent all new i915 requests from | ||
3328 | * being queued (by disallowing execbuf whilst wedged) so having | 3436 | * being queued (by disallowing execbuf whilst wedged) so having |
3329 | * waited for all active requests above, we know the system is idle | 3437 | * waited for all active requests above, we know the system is idle |
3330 | * and do not have to worry about a thread being inside | 3438 | * and do not have to worry about a thread being inside |
@@ -3335,6 +3443,8 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) | |||
3335 | intel_engines_reset_default_submission(i915); | 3443 | intel_engines_reset_default_submission(i915); |
3336 | i915_gem_contexts_lost(i915); | 3444 | i915_gem_contexts_lost(i915); |
3337 | 3445 | ||
3446 | GEM_TRACE("end\n"); | ||
3447 | |||
3338 | smp_mb__before_atomic(); /* complete takeover before enabling execbuf */ | 3448 | smp_mb__before_atomic(); /* complete takeover before enabling execbuf */ |
3339 | clear_bit(I915_WEDGED, &i915->gpu_error.flags); | 3449 | clear_bit(I915_WEDGED, &i915->gpu_error.flags); |
3340 | 3450 | ||
@@ -3473,36 +3583,9 @@ i915_gem_idle_work_handler(struct work_struct *work) | |||
3473 | if (new_requests_since_last_retire(dev_priv)) | 3583 | if (new_requests_since_last_retire(dev_priv)) |
3474 | goto out_unlock; | 3584 | goto out_unlock; |
3475 | 3585 | ||
3476 | /* | 3586 | epoch = __i915_gem_park(dev_priv); |
3477 | * Be paranoid and flush a concurrent interrupt to make sure | ||
3478 | * we don't reactivate any irq tasklets after parking. | ||
3479 | * | ||
3480 | * FIXME: Note that even though we have waited for execlists to be idle, | ||
3481 | * there may still be an in-flight interrupt even though the CSB | ||
3482 | * is now empty. synchronize_irq() makes sure that a residual interrupt | ||
3483 | * is completed before we continue, but it doesn't prevent the HW from | ||
3484 | * raising a spurious interrupt later. To complete the shield we should | ||
3485 | * coordinate disabling the CS irq with flushing the interrupts. | ||
3486 | */ | ||
3487 | synchronize_irq(dev_priv->drm.irq); | ||
3488 | |||
3489 | intel_engines_park(dev_priv); | ||
3490 | i915_gem_timelines_park(dev_priv); | ||
3491 | |||
3492 | i915_pmu_gt_parked(dev_priv); | ||
3493 | 3587 | ||
3494 | GEM_BUG_ON(!dev_priv->gt.awake); | ||
3495 | dev_priv->gt.awake = false; | ||
3496 | epoch = dev_priv->gt.epoch; | ||
3497 | GEM_BUG_ON(epoch == I915_EPOCH_INVALID); | ||
3498 | rearm_hangcheck = false; | 3588 | rearm_hangcheck = false; |
3499 | |||
3500 | if (INTEL_GEN(dev_priv) >= 6) | ||
3501 | gen6_rps_idle(dev_priv); | ||
3502 | |||
3503 | intel_display_power_put(dev_priv, POWER_DOMAIN_GT_IRQ); | ||
3504 | |||
3505 | intel_runtime_pm_put(dev_priv); | ||
3506 | out_unlock: | 3589 | out_unlock: |
3507 | mutex_unlock(&dev_priv->drm.struct_mutex); | 3590 | mutex_unlock(&dev_priv->drm.struct_mutex); |
3508 | 3591 | ||
@@ -3666,16 +3749,7 @@ static int wait_for_engines(struct drm_i915_private *i915) | |||
3666 | if (wait_for(intel_engines_are_idle(i915), I915_IDLE_ENGINES_TIMEOUT)) { | 3749 | if (wait_for(intel_engines_are_idle(i915), I915_IDLE_ENGINES_TIMEOUT)) { |
3667 | dev_err(i915->drm.dev, | 3750 | dev_err(i915->drm.dev, |
3668 | "Failed to idle engines, declaring wedged!\n"); | 3751 | "Failed to idle engines, declaring wedged!\n"); |
3669 | if (drm_debug & DRM_UT_DRIVER) { | 3752 | GEM_TRACE_DUMP(); |
3670 | struct drm_printer p = drm_debug_printer(__func__); | ||
3671 | struct intel_engine_cs *engine; | ||
3672 | enum intel_engine_id id; | ||
3673 | |||
3674 | for_each_engine(engine, i915, id) | ||
3675 | intel_engine_dump(engine, &p, | ||
3676 | "%s\n", engine->name); | ||
3677 | } | ||
3678 | |||
3679 | i915_gem_set_wedged(i915); | 3753 | i915_gem_set_wedged(i915); |
3680 | return -EIO; | 3754 | return -EIO; |
3681 | } | 3755 | } |
@@ -4088,9 +4162,10 @@ out: | |||
4088 | } | 4162 | } |
4089 | 4163 | ||
4090 | /* | 4164 | /* |
4091 | * Prepare buffer for display plane (scanout, cursors, etc). | 4165 | * Prepare buffer for display plane (scanout, cursors, etc). Can be called from |
4092 | * Can be called from an uninterruptible phase (modesetting) and allows | 4166 | * an uninterruptible phase (modesetting) and allows any flushes to be pipelined |
4093 | * any flushes to be pipelined (for pageflips). | 4167 | * (for pageflips). We only flush the caches while preparing the buffer for |
4168 | * display, the callers are responsible for frontbuffer flush. | ||
4094 | */ | 4169 | */ |
4095 | struct i915_vma * | 4170 | struct i915_vma * |
4096 | i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, | 4171 | i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, |
@@ -4146,9 +4221,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, | |||
4146 | 4221 | ||
4147 | vma->display_alignment = max_t(u64, vma->display_alignment, alignment); | 4222 | vma->display_alignment = max_t(u64, vma->display_alignment, alignment); |
4148 | 4223 | ||
4149 | /* Treat this as an end-of-frame, like intel_user_framebuffer_dirty() */ | ||
4150 | __i915_gem_object_flush_for_display(obj); | 4224 | __i915_gem_object_flush_for_display(obj); |
4151 | intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | ||
4152 | 4225 | ||
4153 | /* It should now be out of any other write domains, and we can update | 4226 | /* It should now be out of any other write domains, and we can update |
4154 | * the domain values for our changes. | 4227 | * the domain values for our changes. |
@@ -4973,6 +5046,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) | |||
4973 | * machines is a good idea, we don't - just in case it leaves the | 5046 | * machines is a good idea, we don't - just in case it leaves the |
4974 | * machine in an unusable condition. | 5047 | * machine in an unusable condition. |
4975 | */ | 5048 | */ |
5049 | intel_uc_sanitize(dev_priv); | ||
4976 | i915_gem_sanitize(dev_priv); | 5050 | i915_gem_sanitize(dev_priv); |
4977 | 5051 | ||
4978 | intel_runtime_pm_put(dev_priv); | 5052 | intel_runtime_pm_put(dev_priv); |
@@ -5118,6 +5192,8 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) | |||
5118 | } | 5192 | } |
5119 | } | 5193 | } |
5120 | 5194 | ||
5195 | intel_gt_workarounds_apply(dev_priv); | ||
5196 | |||
5121 | i915_gem_init_swizzling(dev_priv); | 5197 | i915_gem_init_swizzling(dev_priv); |
5122 | 5198 | ||
5123 | /* | 5199 | /* |
@@ -5140,6 +5216,12 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) | |||
5140 | goto out; | 5216 | goto out; |
5141 | } | 5217 | } |
5142 | 5218 | ||
5219 | ret = intel_wopcm_init_hw(&dev_priv->wopcm); | ||
5220 | if (ret) { | ||
5221 | DRM_ERROR("Enabling WOPCM failed (%d)\n", ret); | ||
5222 | goto out; | ||
5223 | } | ||
5224 | |||
5143 | /* We can't enable contexts until all firmware is loaded */ | 5225 | /* We can't enable contexts until all firmware is loaded */ |
5144 | ret = intel_uc_init_hw(dev_priv); | 5226 | ret = intel_uc_init_hw(dev_priv); |
5145 | if (ret) { | 5227 | if (ret) { |
@@ -5297,6 +5379,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) | |||
5297 | if (ret) | 5379 | if (ret) |
5298 | return ret; | 5380 | return ret; |
5299 | 5381 | ||
5382 | ret = intel_wopcm_init(&dev_priv->wopcm); | ||
5383 | if (ret) | ||
5384 | return ret; | ||
5385 | |||
5300 | ret = intel_uc_init_misc(dev_priv); | 5386 | ret = intel_uc_init_misc(dev_priv); |
5301 | if (ret) | 5387 | if (ret) |
5302 | return ret; | 5388 | return ret; |
@@ -5478,8 +5564,7 @@ static void i915_gem_init__mm(struct drm_i915_private *i915) | |||
5478 | INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); | 5564 | INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); |
5479 | } | 5565 | } |
5480 | 5566 | ||
5481 | int | 5567 | int i915_gem_init_early(struct drm_i915_private *dev_priv) |
5482 | i915_gem_load_init(struct drm_i915_private *dev_priv) | ||
5483 | { | 5568 | { |
5484 | int err = -ENOMEM; | 5569 | int err = -ENOMEM; |
5485 | 5570 | ||
@@ -5554,7 +5639,7 @@ err_out: | |||
5554 | return err; | 5639 | return err; |
5555 | } | 5640 | } |
5556 | 5641 | ||
5557 | void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) | 5642 | void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) |
5558 | { | 5643 | { |
5559 | i915_gem_drain_freed_objects(dev_priv); | 5644 | i915_gem_drain_freed_objects(dev_priv); |
5560 | GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); | 5645 | GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); |
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index f54c4ff74ded..deaf78d2ae8b 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #include <linux/bug.h> | 28 | #include <linux/bug.h> |
29 | 29 | ||
30 | struct drm_i915_private; | ||
31 | |||
30 | #ifdef CONFIG_DRM_I915_DEBUG_GEM | 32 | #ifdef CONFIG_DRM_I915_DEBUG_GEM |
31 | #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ | 33 | #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ |
32 | pr_err("%s:%d GEM_BUG_ON(%s)\n", \ | 34 | pr_err("%s:%d GEM_BUG_ON(%s)\n", \ |
@@ -53,10 +55,15 @@ | |||
53 | 55 | ||
54 | #if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM) | 56 | #if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM) |
55 | #define GEM_TRACE(...) trace_printk(__VA_ARGS__) | 57 | #define GEM_TRACE(...) trace_printk(__VA_ARGS__) |
58 | #define GEM_TRACE_DUMP() ftrace_dump(DUMP_ALL) | ||
56 | #else | 59 | #else |
57 | #define GEM_TRACE(...) do { } while (0) | 60 | #define GEM_TRACE(...) do { } while (0) |
61 | #define GEM_TRACE_DUMP() do { } while (0) | ||
58 | #endif | 62 | #endif |
59 | 63 | ||
60 | #define I915_NUM_ENGINES 8 | 64 | #define I915_NUM_ENGINES 8 |
61 | 65 | ||
66 | void i915_gem_park(struct drm_i915_private *i915); | ||
67 | void i915_gem_unpark(struct drm_i915_private *i915); | ||
68 | |||
62 | #endif /* __I915_GEM_H__ */ | 69 | #endif /* __I915_GEM_H__ */ |
diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index d3cbe8432f48..f3890b664e3f 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c | |||
@@ -1,29 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2014 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2014-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
25 | #include "i915_drv.h" | ||
26 | #include "i915_gem_batch_pool.h" | 7 | #include "i915_gem_batch_pool.h" |
8 | #include "i915_drv.h" | ||
27 | 9 | ||
28 | /** | 10 | /** |
29 | * DOC: batch pool | 11 | * DOC: batch pool |
@@ -41,11 +23,11 @@ | |||
41 | 23 | ||
42 | /** | 24 | /** |
43 | * i915_gem_batch_pool_init() - initialize a batch buffer pool | 25 | * i915_gem_batch_pool_init() - initialize a batch buffer pool |
44 | * @engine: the associated request submission engine | ||
45 | * @pool: the batch buffer pool | 26 | * @pool: the batch buffer pool |
27 | * @engine: the associated request submission engine | ||
46 | */ | 28 | */ |
47 | void i915_gem_batch_pool_init(struct intel_engine_cs *engine, | 29 | void i915_gem_batch_pool_init(struct i915_gem_batch_pool *pool, |
48 | struct i915_gem_batch_pool *pool) | 30 | struct intel_engine_cs *engine) |
49 | { | 31 | { |
50 | int n; | 32 | int n; |
51 | 33 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.h b/drivers/gpu/drm/i915/i915_gem_batch_pool.h index 10d5ac4c00d3..56947daaaf65 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.h +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.h | |||
@@ -1,31 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2014 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2014-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
25 | #ifndef I915_GEM_BATCH_POOL_H | 7 | #ifndef I915_GEM_BATCH_POOL_H |
26 | #define I915_GEM_BATCH_POOL_H | 8 | #define I915_GEM_BATCH_POOL_H |
27 | 9 | ||
28 | #include "i915_drv.h" | 10 | #include <linux/types.h> |
29 | 11 | ||
30 | struct intel_engine_cs; | 12 | struct intel_engine_cs; |
31 | 13 | ||
@@ -34,9 +16,8 @@ struct i915_gem_batch_pool { | |||
34 | struct list_head cache_list[4]; | 16 | struct list_head cache_list[4]; |
35 | }; | 17 | }; |
36 | 18 | ||
37 | /* i915_gem_batch_pool.c */ | 19 | void i915_gem_batch_pool_init(struct i915_gem_batch_pool *pool, |
38 | void i915_gem_batch_pool_init(struct intel_engine_cs *engine, | 20 | struct intel_engine_cs *engine); |
39 | struct i915_gem_batch_pool *pool); | ||
40 | void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); | 21 | void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); |
41 | struct drm_i915_gem_object* | 22 | struct drm_i915_gem_object* |
42 | i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); | 23 | i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f2cbea7cf940..9b3834a846e8 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <drm/i915_drm.h> | 90 | #include <drm/i915_drm.h> |
91 | #include "i915_drv.h" | 91 | #include "i915_drv.h" |
92 | #include "i915_trace.h" | 92 | #include "i915_trace.h" |
93 | #include "intel_workarounds.h" | ||
93 | 94 | ||
94 | #define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1 | 95 | #define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1 |
95 | 96 | ||
@@ -318,12 +319,13 @@ __create_hw_context(struct drm_i915_private *dev_priv, | |||
318 | ctx->desc_template = | 319 | ctx->desc_template = |
319 | default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt); | 320 | default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt); |
320 | 321 | ||
321 | /* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not | 322 | /* |
323 | * GuC requires the ring to be placed in Non-WOPCM memory. If GuC is not | ||
322 | * present or not in use we still need a small bias as ring wraparound | 324 | * present or not in use we still need a small bias as ring wraparound |
323 | * at offset 0 sometimes hangs. No idea why. | 325 | * at offset 0 sometimes hangs. No idea why. |
324 | */ | 326 | */ |
325 | if (USES_GUC(dev_priv)) | 327 | if (USES_GUC(dev_priv)) |
326 | ctx->ggtt_offset_bias = GUC_WOPCM_TOP; | 328 | ctx->ggtt_offset_bias = dev_priv->guc.ggtt_pin_bias; |
327 | else | 329 | else |
328 | ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; | 330 | ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; |
329 | 331 | ||
@@ -458,11 +460,16 @@ static bool needs_preempt_context(struct drm_i915_private *i915) | |||
458 | int i915_gem_contexts_init(struct drm_i915_private *dev_priv) | 460 | int i915_gem_contexts_init(struct drm_i915_private *dev_priv) |
459 | { | 461 | { |
460 | struct i915_gem_context *ctx; | 462 | struct i915_gem_context *ctx; |
463 | int ret; | ||
461 | 464 | ||
462 | /* Reassure ourselves we are only called once */ | 465 | /* Reassure ourselves we are only called once */ |
463 | GEM_BUG_ON(dev_priv->kernel_context); | 466 | GEM_BUG_ON(dev_priv->kernel_context); |
464 | GEM_BUG_ON(dev_priv->preempt_context); | 467 | GEM_BUG_ON(dev_priv->preempt_context); |
465 | 468 | ||
469 | ret = intel_ctx_workarounds_init(dev_priv); | ||
470 | if (ret) | ||
471 | return ret; | ||
472 | |||
466 | INIT_LIST_HEAD(&dev_priv->contexts.list); | 473 | INIT_LIST_HEAD(&dev_priv->contexts.list); |
467 | INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); | 474 | INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); |
468 | init_llist_head(&dev_priv->contexts.free_list); | 475 | init_llist_head(&dev_priv->contexts.free_list); |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 0414228cd2b5..c74f5df3fb5a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -81,6 +81,35 @@ enum { | |||
81 | * but this remains just a hint as the kernel may choose a new location for | 81 | * but this remains just a hint as the kernel may choose a new location for |
82 | * any object in the future. | 82 | * any object in the future. |
83 | * | 83 | * |
84 | * At the level of talking to the hardware, submitting a batchbuffer for the | ||
85 | * GPU to execute is to add content to a buffer from which the HW | ||
86 | * command streamer is reading. | ||
87 | * | ||
88 | * 1. Add a command to load the HW context. For Logical Ring Contexts, i.e. | ||
89 | * Execlists, this command is not placed on the same buffer as the | ||
90 | * remaining items. | ||
91 | * | ||
92 | * 2. Add a command to invalidate caches to the buffer. | ||
93 | * | ||
94 | * 3. Add a batchbuffer start command to the buffer; the start command is | ||
95 | * essentially a token together with the GPU address of the batchbuffer | ||
96 | * to be executed. | ||
97 | * | ||
98 | * 4. Add a pipeline flush to the buffer. | ||
99 | * | ||
100 | * 5. Add a memory write command to the buffer to record when the GPU | ||
101 | * is done executing the batchbuffer. The memory write writes the | ||
102 | * global sequence number of the request, ``i915_request::global_seqno``; | ||
103 | * the i915 driver uses the current value in the register to determine | ||
104 | * if the GPU has completed the batchbuffer. | ||
105 | * | ||
106 | * 6. Add a user interrupt command to the buffer. This command instructs | ||
107 | * the GPU to issue an interrupt when the command, pipeline flush and | ||
108 | * memory write are completed. | ||
109 | * | ||
110 | * 7. Inform the hardware of the additional commands added to the buffer | ||
111 | * (by updating the tail pointer). | ||
112 | * | ||
84 | * Processing an execbuf ioctl is conceptually split up into a few phases. | 113 | * Processing an execbuf ioctl is conceptually split up into a few phases. |
85 | * | 114 | * |
86 | * 1. Validation - Ensure all the pointers, handles and flags are valid. | 115 | * 1. Validation - Ensure all the pointers, handles and flags are valid. |
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 62aa67960bf4..af915d041281 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c | |||
@@ -121,8 +121,8 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, | |||
121 | 121 | ||
122 | if (stolen[0].start != stolen[1].start || | 122 | if (stolen[0].start != stolen[1].start || |
123 | stolen[0].end != stolen[1].end) { | 123 | stolen[0].end != stolen[1].end) { |
124 | DRM_DEBUG_KMS("GTT within stolen memory at %pR\n", &ggtt_res); | 124 | DRM_DEBUG_DRIVER("GTT within stolen memory at %pR\n", &ggtt_res); |
125 | DRM_DEBUG_KMS("Stolen memory adjusted to %pR\n", dsm); | 125 | DRM_DEBUG_DRIVER("Stolen memory adjusted to %pR\n", dsm); |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
@@ -174,18 +174,19 @@ void i915_gem_cleanup_stolen(struct drm_device *dev) | |||
174 | } | 174 | } |
175 | 175 | ||
176 | static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, | 176 | static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, |
177 | resource_size_t *base, resource_size_t *size) | 177 | resource_size_t *base, |
178 | resource_size_t *size) | ||
178 | { | 179 | { |
179 | uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ? | 180 | u32 reg_val = I915_READ(IS_GM45(dev_priv) ? |
180 | CTG_STOLEN_RESERVED : | 181 | CTG_STOLEN_RESERVED : |
181 | ELK_STOLEN_RESERVED); | 182 | ELK_STOLEN_RESERVED); |
182 | resource_size_t stolen_top = dev_priv->dsm.end + 1; | 183 | resource_size_t stolen_top = dev_priv->dsm.end + 1; |
183 | 184 | ||
184 | if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) { | 185 | DRM_DEBUG_DRIVER("%s_STOLEN_RESERVED = %08x\n", |
185 | *base = 0; | 186 | IS_GM45(dev_priv) ? "CTG" : "ELK", reg_val); |
186 | *size = 0; | 187 | |
188 | if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) | ||
187 | return; | 189 | return; |
188 | } | ||
189 | 190 | ||
190 | /* | 191 | /* |
191 | * Whether ILK really reuses the ELK register for this is unclear. | 192 | * Whether ILK really reuses the ELK register for this is unclear. |
@@ -193,30 +194,25 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, | |||
193 | */ | 194 | */ |
194 | WARN(IS_GEN5(dev_priv), "ILK stolen reserved found? 0x%08x\n", reg_val); | 195 | WARN(IS_GEN5(dev_priv), "ILK stolen reserved found? 0x%08x\n", reg_val); |
195 | 196 | ||
196 | *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; | 197 | if (!(reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK)) |
198 | return; | ||
197 | 199 | ||
200 | *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; | ||
198 | WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); | 201 | WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); |
199 | 202 | ||
200 | /* On these platforms, the register doesn't have a size field, so the | 203 | *size = stolen_top - *base; |
201 | * size is the distance between the base and the top of the stolen | ||
202 | * memory. We also have the genuine case where base is zero and there's | ||
203 | * nothing reserved. */ | ||
204 | if (*base == 0) | ||
205 | *size = 0; | ||
206 | else | ||
207 | *size = stolen_top - *base; | ||
208 | } | 204 | } |
209 | 205 | ||
210 | static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, | 206 | static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, |
211 | resource_size_t *base, resource_size_t *size) | 207 | resource_size_t *base, |
208 | resource_size_t *size) | ||
212 | { | 209 | { |
213 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); | 210 | u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
211 | |||
212 | DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); | ||
214 | 213 | ||
215 | if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | 214 | if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) |
216 | *base = 0; | ||
217 | *size = 0; | ||
218 | return; | 215 | return; |
219 | } | ||
220 | 216 | ||
221 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; | 217 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
222 | 218 | ||
@@ -239,17 +235,44 @@ static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, | |||
239 | } | 235 | } |
240 | } | 236 | } |
241 | 237 | ||
242 | static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, | 238 | static void vlv_get_stolen_reserved(struct drm_i915_private *dev_priv, |
243 | resource_size_t *base, resource_size_t *size) | 239 | resource_size_t *base, |
240 | resource_size_t *size) | ||
244 | { | 241 | { |
245 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); | 242 | u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
243 | resource_size_t stolen_top = dev_priv->dsm.end + 1; | ||
246 | 244 | ||
247 | if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | 245 | DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); |
248 | *base = 0; | 246 | |
249 | *size = 0; | 247 | if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) |
250 | return; | 248 | return; |
249 | |||
250 | switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) { | ||
251 | default: | ||
252 | MISSING_CASE(reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK); | ||
253 | case GEN7_STOLEN_RESERVED_1M: | ||
254 | *size = 1024 * 1024; | ||
255 | break; | ||
251 | } | 256 | } |
252 | 257 | ||
258 | /* | ||
259 | * On vlv, the ADDR_MASK portion is left as 0 and HW deduces the | ||
260 | * reserved location as (top - size). | ||
261 | */ | ||
262 | *base = stolen_top - *size; | ||
263 | } | ||
264 | |||
265 | static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, | ||
266 | resource_size_t *base, | ||
267 | resource_size_t *size) | ||
268 | { | ||
269 | u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); | ||
270 | |||
271 | DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); | ||
272 | |||
273 | if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) | ||
274 | return; | ||
275 | |||
253 | *base = reg_val & GEN7_STOLEN_RESERVED_ADDR_MASK; | 276 | *base = reg_val & GEN7_STOLEN_RESERVED_ADDR_MASK; |
254 | 277 | ||
255 | switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) { | 278 | switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) { |
@@ -266,15 +289,15 @@ static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, | |||
266 | } | 289 | } |
267 | 290 | ||
268 | static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, | 291 | static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, |
269 | resource_size_t *base, resource_size_t *size) | 292 | resource_size_t *base, |
293 | resource_size_t *size) | ||
270 | { | 294 | { |
271 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); | 295 | u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
272 | 296 | ||
273 | if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | 297 | DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); |
274 | *base = 0; | 298 | |
275 | *size = 0; | 299 | if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) |
276 | return; | 300 | return; |
277 | } | ||
278 | 301 | ||
279 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; | 302 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
280 | 303 | ||
@@ -298,29 +321,22 @@ static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, | |||
298 | } | 321 | } |
299 | 322 | ||
300 | static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, | 323 | static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, |
301 | resource_size_t *base, resource_size_t *size) | 324 | resource_size_t *base, |
325 | resource_size_t *size) | ||
302 | { | 326 | { |
303 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); | 327 | u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
304 | resource_size_t stolen_top; | 328 | resource_size_t stolen_top = dev_priv->dsm.end + 1; |
305 | 329 | ||
306 | if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | 330 | DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); |
307 | *base = 0; | 331 | |
308 | *size = 0; | 332 | if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) |
309 | return; | 333 | return; |
310 | } | ||
311 | 334 | ||
312 | stolen_top = dev_priv->dsm.end + 1; | 335 | if (!(reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK)) |
336 | return; | ||
313 | 337 | ||
314 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; | 338 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
315 | 339 | *size = stolen_top - *base; | |
316 | /* On these platforms, the register doesn't have a size field, so the | ||
317 | * size is the distance between the base and the top of the stolen | ||
318 | * memory. We also have the genuine case where base is zero and there's | ||
319 | * nothing reserved. */ | ||
320 | if (*base == 0) | ||
321 | *size = 0; | ||
322 | else | ||
323 | *size = stolen_top - *base; | ||
324 | } | 340 | } |
325 | 341 | ||
326 | int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | 342 | int i915_gem_init_stolen(struct drm_i915_private *dev_priv) |
@@ -353,7 +369,7 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
353 | GEM_BUG_ON(dev_priv->dsm.end <= dev_priv->dsm.start); | 369 | GEM_BUG_ON(dev_priv->dsm.end <= dev_priv->dsm.start); |
354 | 370 | ||
355 | stolen_top = dev_priv->dsm.end + 1; | 371 | stolen_top = dev_priv->dsm.end + 1; |
356 | reserved_base = 0; | 372 | reserved_base = stolen_top; |
357 | reserved_size = 0; | 373 | reserved_size = 0; |
358 | 374 | ||
359 | switch (INTEL_GEN(dev_priv)) { | 375 | switch (INTEL_GEN(dev_priv)) { |
@@ -373,8 +389,12 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
373 | &reserved_base, &reserved_size); | 389 | &reserved_base, &reserved_size); |
374 | break; | 390 | break; |
375 | case 7: | 391 | case 7: |
376 | gen7_get_stolen_reserved(dev_priv, | 392 | if (IS_VALLEYVIEW(dev_priv)) |
377 | &reserved_base, &reserved_size); | 393 | vlv_get_stolen_reserved(dev_priv, |
394 | &reserved_base, &reserved_size); | ||
395 | else | ||
396 | gen7_get_stolen_reserved(dev_priv, | ||
397 | &reserved_base, &reserved_size); | ||
378 | break; | 398 | break; |
379 | default: | 399 | default: |
380 | if (IS_LP(dev_priv)) | 400 | if (IS_LP(dev_priv)) |
@@ -386,11 +406,16 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
386 | break; | 406 | break; |
387 | } | 407 | } |
388 | 408 | ||
389 | /* It is possible for the reserved base to be zero, but the register | 409 | /* |
390 | * field for size doesn't have a zero option. */ | 410 | * Our expectation is that the reserved space is at the top of the |
391 | if (reserved_base == 0) { | 411 | * stolen region and *never* at the bottom. If we see !reserved_base, |
392 | reserved_size = 0; | 412 | * it likely means we failed to read the registers correctly. |
413 | */ | ||
414 | if (!reserved_base) { | ||
415 | DRM_ERROR("inconsistent reservation %pa + %pa; ignoring\n", | ||
416 | &reserved_base, &reserved_size); | ||
393 | reserved_base = stolen_top; | 417 | reserved_base = stolen_top; |
418 | reserved_size = 0; | ||
394 | } | 419 | } |
395 | 420 | ||
396 | dev_priv->dsm_reserved = | 421 | dev_priv->dsm_reserved = |
@@ -406,9 +431,9 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
406 | * memory, so just consider the start. */ | 431 | * memory, so just consider the start. */ |
407 | reserved_total = stolen_top - reserved_base; | 432 | reserved_total = stolen_top - reserved_base; |
408 | 433 | ||
409 | DRM_DEBUG_KMS("Memory reserved for graphics device: %lluK, usable: %lluK\n", | 434 | DRM_DEBUG_DRIVER("Memory reserved for graphics device: %lluK, usable: %lluK\n", |
410 | (u64)resource_size(&dev_priv->dsm) >> 10, | 435 | (u64)resource_size(&dev_priv->dsm) >> 10, |
411 | ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); | 436 | ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); |
412 | 437 | ||
413 | stolen_usable_start = 0; | 438 | stolen_usable_start = 0; |
414 | /* WaSkipStolenMemoryFirstPage:bdw+ */ | 439 | /* WaSkipStolenMemoryFirstPage:bdw+ */ |
@@ -580,8 +605,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv | |||
580 | 605 | ||
581 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 606 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
582 | 607 | ||
583 | DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", | 608 | DRM_DEBUG_DRIVER("creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", |
584 | &stolen_offset, >t_offset, &size); | 609 | &stolen_offset, >t_offset, &size); |
585 | 610 | ||
586 | /* KISS and expect everything to be page-aligned */ | 611 | /* KISS and expect everything to be page-aligned */ |
587 | if (WARN_ON(size == 0) || | 612 | if (WARN_ON(size == 0) || |
@@ -599,14 +624,14 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv | |||
599 | ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen); | 624 | ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen); |
600 | mutex_unlock(&dev_priv->mm.stolen_lock); | 625 | mutex_unlock(&dev_priv->mm.stolen_lock); |
601 | if (ret) { | 626 | if (ret) { |
602 | DRM_DEBUG_KMS("failed to allocate stolen space\n"); | 627 | DRM_DEBUG_DRIVER("failed to allocate stolen space\n"); |
603 | kfree(stolen); | 628 | kfree(stolen); |
604 | return NULL; | 629 | return NULL; |
605 | } | 630 | } |
606 | 631 | ||
607 | obj = _i915_gem_object_create_stolen(dev_priv, stolen); | 632 | obj = _i915_gem_object_create_stolen(dev_priv, stolen); |
608 | if (obj == NULL) { | 633 | if (obj == NULL) { |
609 | DRM_DEBUG_KMS("failed to allocate stolen object\n"); | 634 | DRM_DEBUG_DRIVER("failed to allocate stolen object\n"); |
610 | i915_gem_stolen_remove_node(dev_priv, stolen); | 635 | i915_gem_stolen_remove_node(dev_priv, stolen); |
611 | kfree(stolen); | 636 | kfree(stolen); |
612 | return NULL; | 637 | return NULL; |
@@ -635,7 +660,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv | |||
635 | size, gtt_offset, obj->cache_level, | 660 | size, gtt_offset, obj->cache_level, |
636 | 0); | 661 | 0); |
637 | if (ret) { | 662 | if (ret) { |
638 | DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); | 663 | DRM_DEBUG_DRIVER("failed to allocate stolen GTT space\n"); |
639 | goto err_pages; | 664 | goto err_pages; |
640 | } | 665 | } |
641 | 666 | ||
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index f89ac7a8f95f..effaf982b19b 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/zlib.h> | 32 | #include <linux/zlib.h> |
33 | #include <drm/drm_print.h> | 33 | #include <drm/drm_print.h> |
34 | 34 | ||
35 | #include "i915_gpu_error.h" | ||
35 | #include "i915_drv.h" | 36 | #include "i915_drv.h" |
36 | 37 | ||
37 | static inline const struct intel_engine_cs * | 38 | static inline const struct intel_engine_cs * |
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h new file mode 100644 index 000000000000..c05b6034d718 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gpu_error.h | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright � 2008-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef _I915_GPU_ERROR_H_ | ||
8 | #define _I915_GPU_ERROR_H_ | ||
9 | |||
10 | #include <linux/kref.h> | ||
11 | #include <linux/ktime.h> | ||
12 | #include <linux/sched.h> | ||
13 | |||
14 | #include <drm/drm_mm.h> | ||
15 | |||
16 | #include "intel_device_info.h" | ||
17 | #include "intel_ringbuffer.h" | ||
18 | #include "intel_uc_fw.h" | ||
19 | |||
20 | #include "i915_gem.h" | ||
21 | #include "i915_gem_gtt.h" | ||
22 | #include "i915_params.h" | ||
23 | |||
24 | struct drm_i915_private; | ||
25 | struct intel_overlay_error_state; | ||
26 | struct intel_display_error_state; | ||
27 | |||
28 | struct i915_gpu_state { | ||
29 | struct kref ref; | ||
30 | ktime_t time; | ||
31 | ktime_t boottime; | ||
32 | ktime_t uptime; | ||
33 | |||
34 | struct drm_i915_private *i915; | ||
35 | |||
36 | char error_msg[128]; | ||
37 | bool simulated; | ||
38 | bool awake; | ||
39 | bool wakelock; | ||
40 | bool suspended; | ||
41 | int iommu; | ||
42 | u32 reset_count; | ||
43 | u32 suspend_count; | ||
44 | struct intel_device_info device_info; | ||
45 | struct intel_driver_caps driver_caps; | ||
46 | struct i915_params params; | ||
47 | |||
48 | struct i915_error_uc { | ||
49 | struct intel_uc_fw guc_fw; | ||
50 | struct intel_uc_fw huc_fw; | ||
51 | struct drm_i915_error_object *guc_log; | ||
52 | } uc; | ||
53 | |||
54 | /* Generic register state */ | ||
55 | u32 eir; | ||
56 | u32 pgtbl_er; | ||
57 | u32 ier; | ||
58 | u32 gtier[4], ngtier; | ||
59 | u32 ccid; | ||
60 | u32 derrmr; | ||
61 | u32 forcewake; | ||
62 | u32 error; /* gen6+ */ | ||
63 | u32 err_int; /* gen7 */ | ||
64 | u32 fault_data0; /* gen8, gen9 */ | ||
65 | u32 fault_data1; /* gen8, gen9 */ | ||
66 | u32 done_reg; | ||
67 | u32 gac_eco; | ||
68 | u32 gam_ecochk; | ||
69 | u32 gab_ctl; | ||
70 | u32 gfx_mode; | ||
71 | |||
72 | u32 nfence; | ||
73 | u64 fence[I915_MAX_NUM_FENCES]; | ||
74 | struct intel_overlay_error_state *overlay; | ||
75 | struct intel_display_error_state *display; | ||
76 | |||
77 | struct drm_i915_error_engine { | ||
78 | int engine_id; | ||
79 | /* Software tracked state */ | ||
80 | bool idle; | ||
81 | bool waiting; | ||
82 | int num_waiters; | ||
83 | unsigned long hangcheck_timestamp; | ||
84 | bool hangcheck_stalled; | ||
85 | enum intel_engine_hangcheck_action hangcheck_action; | ||
86 | struct i915_address_space *vm; | ||
87 | int num_requests; | ||
88 | u32 reset_count; | ||
89 | |||
90 | /* position of active request inside the ring */ | ||
91 | u32 rq_head, rq_post, rq_tail; | ||
92 | |||
93 | /* our own tracking of ring head and tail */ | ||
94 | u32 cpu_ring_head; | ||
95 | u32 cpu_ring_tail; | ||
96 | |||
97 | u32 last_seqno; | ||
98 | |||
99 | /* Register state */ | ||
100 | u32 start; | ||
101 | u32 tail; | ||
102 | u32 head; | ||
103 | u32 ctl; | ||
104 | u32 mode; | ||
105 | u32 hws; | ||
106 | u32 ipeir; | ||
107 | u32 ipehr; | ||
108 | u32 bbstate; | ||
109 | u32 instpm; | ||
110 | u32 instps; | ||
111 | u32 seqno; | ||
112 | u64 bbaddr; | ||
113 | u64 acthd; | ||
114 | u32 fault_reg; | ||
115 | u64 faddr; | ||
116 | u32 rc_psmi; /* sleep state */ | ||
117 | u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; | ||
118 | struct intel_instdone instdone; | ||
119 | |||
120 | struct drm_i915_error_context { | ||
121 | char comm[TASK_COMM_LEN]; | ||
122 | pid_t pid; | ||
123 | u32 handle; | ||
124 | u32 hw_id; | ||
125 | int priority; | ||
126 | int ban_score; | ||
127 | int active; | ||
128 | int guilty; | ||
129 | bool bannable; | ||
130 | } context; | ||
131 | |||
132 | struct drm_i915_error_object { | ||
133 | u64 gtt_offset; | ||
134 | u64 gtt_size; | ||
135 | int page_count; | ||
136 | int unused; | ||
137 | u32 *pages[0]; | ||
138 | } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; | ||
139 | |||
140 | struct drm_i915_error_object **user_bo; | ||
141 | long user_bo_count; | ||
142 | |||
143 | struct drm_i915_error_object *wa_ctx; | ||
144 | struct drm_i915_error_object *default_state; | ||
145 | |||
146 | struct drm_i915_error_request { | ||
147 | long jiffies; | ||
148 | pid_t pid; | ||
149 | u32 context; | ||
150 | int priority; | ||
151 | int ban_score; | ||
152 | u32 seqno; | ||
153 | u32 head; | ||
154 | u32 tail; | ||
155 | } *requests, execlist[EXECLIST_MAX_PORTS]; | ||
156 | unsigned int num_ports; | ||
157 | |||
158 | struct drm_i915_error_waiter { | ||
159 | char comm[TASK_COMM_LEN]; | ||
160 | pid_t pid; | ||
161 | u32 seqno; | ||
162 | } *waiters; | ||
163 | |||
164 | struct { | ||
165 | u32 gfx_mode; | ||
166 | union { | ||
167 | u64 pdp[4]; | ||
168 | u32 pp_dir_base; | ||
169 | }; | ||
170 | } vm_info; | ||
171 | } engine[I915_NUM_ENGINES]; | ||
172 | |||
173 | struct drm_i915_error_buffer { | ||
174 | u32 size; | ||
175 | u32 name; | ||
176 | u32 rseqno[I915_NUM_ENGINES], wseqno; | ||
177 | u64 gtt_offset; | ||
178 | u32 read_domains; | ||
179 | u32 write_domain; | ||
180 | s32 fence_reg:I915_MAX_NUM_FENCE_BITS; | ||
181 | u32 tiling:2; | ||
182 | u32 dirty:1; | ||
183 | u32 purgeable:1; | ||
184 | u32 userptr:1; | ||
185 | s32 engine:4; | ||
186 | u32 cache_level:3; | ||
187 | } *active_bo[I915_NUM_ENGINES], *pinned_bo; | ||
188 | u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count; | ||
189 | struct i915_address_space *active_vm[I915_NUM_ENGINES]; | ||
190 | }; | ||
191 | |||
192 | struct i915_gpu_error { | ||
193 | /* For hangcheck timer */ | ||
194 | #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ | ||
195 | #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) | ||
196 | |||
197 | struct delayed_work hangcheck_work; | ||
198 | |||
199 | /* For reset and error_state handling. */ | ||
200 | spinlock_t lock; | ||
201 | /* Protected by the above dev->gpu_error.lock. */ | ||
202 | struct i915_gpu_state *first_error; | ||
203 | |||
204 | atomic_t pending_fb_pin; | ||
205 | |||
206 | unsigned long missed_irq_rings; | ||
207 | |||
208 | /** | ||
209 | * State variable controlling the reset flow and count | ||
210 | * | ||
211 | * This is a counter which gets incremented when reset is triggered, | ||
212 | * | ||
213 | * Before the reset commences, the I915_RESET_BACKOFF bit is set | ||
214 | * meaning that any waiters holding onto the struct_mutex should | ||
215 | * relinquish the lock immediately in order for the reset to start. | ||
216 | * | ||
217 | * If reset is not completed successfully, the I915_WEDGE bit is | ||
218 | * set meaning that hardware is terminally sour and there is no | ||
219 | * recovery. All waiters on the reset_queue will be woken when | ||
220 | * that happens. | ||
221 | * | ||
222 | * This counter is used by the wait_seqno code to notice that reset | ||
223 | * event happened and it needs to restart the entire ioctl (since most | ||
224 | * likely the seqno it waited for won't ever signal anytime soon). | ||
225 | * | ||
226 | * This is important for lock-free wait paths, where no contended lock | ||
227 | * naturally enforces the correct ordering between the bail-out of the | ||
228 | * waiter and the gpu reset work code. | ||
229 | */ | ||
230 | unsigned long reset_count; | ||
231 | |||
232 | /** | ||
233 | * flags: Control various stages of the GPU reset | ||
234 | * | ||
235 | * #I915_RESET_BACKOFF - When we start a reset, we want to stop any | ||
236 | * other users acquiring the struct_mutex. To do this we set the | ||
237 | * #I915_RESET_BACKOFF bit in the error flags when we detect a reset | ||
238 | * and then check for that bit before acquiring the struct_mutex (in | ||
239 | * i915_mutex_lock_interruptible()?). I915_RESET_BACKOFF serves a | ||
240 | * secondary role in preventing two concurrent global reset attempts. | ||
241 | * | ||
242 | * #I915_RESET_HANDOFF - To perform the actual GPU reset, we need the | ||
243 | * struct_mutex. We try to acquire the struct_mutex in the reset worker, | ||
244 | * but it may be held by some long running waiter (that we cannot | ||
245 | * interrupt without causing trouble). Once we are ready to do the GPU | ||
246 | * reset, we set the I915_RESET_HANDOFF bit and wakeup any waiters. If | ||
247 | * they already hold the struct_mutex and want to participate they can | ||
248 | * inspect the bit and do the reset directly, otherwise the worker | ||
249 | * waits for the struct_mutex. | ||
250 | * | ||
251 | * #I915_RESET_ENGINE[num_engines] - Since the driver doesn't need to | ||
252 | * acquire the struct_mutex to reset an engine, we need an explicit | ||
253 | * flag to prevent two concurrent reset attempts in the same engine. | ||
254 | * As the number of engines continues to grow, allocate the flags from | ||
255 | * the most significant bits. | ||
256 | * | ||
257 | * #I915_WEDGED - If reset fails and we can no longer use the GPU, | ||
258 | * we set the #I915_WEDGED bit. Prior to command submission, e.g. | ||
259 | * i915_request_alloc(), this bit is checked and the sequence | ||
260 | * aborted (with -EIO reported to userspace) if set. | ||
261 | */ | ||
262 | unsigned long flags; | ||
263 | #define I915_RESET_BACKOFF 0 | ||
264 | #define I915_RESET_HANDOFF 1 | ||
265 | #define I915_RESET_MODESET 2 | ||
266 | #define I915_WEDGED (BITS_PER_LONG - 1) | ||
267 | #define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES) | ||
268 | |||
269 | /** Number of times an engine has been reset */ | ||
270 | u32 reset_engine_count[I915_NUM_ENGINES]; | ||
271 | |||
272 | /** Set of stalled engines with guilty requests, in the current reset */ | ||
273 | u32 stalled_mask; | ||
274 | |||
275 | /** Reason for the current *global* reset */ | ||
276 | const char *reason; | ||
277 | |||
278 | /** | ||
279 | * Waitqueue to signal when a hang is detected. Used to for waiters | ||
280 | * to release the struct_mutex for the reset to procede. | ||
281 | */ | ||
282 | wait_queue_head_t wait_queue; | ||
283 | |||
284 | /** | ||
285 | * Waitqueue to signal when the reset has completed. Used by clients | ||
286 | * that wait for dev_priv->mm.wedged to settle. | ||
287 | */ | ||
288 | wait_queue_head_t reset_queue; | ||
289 | |||
290 | /* For missed irq/seqno simulation. */ | ||
291 | unsigned long test_irq_rings; | ||
292 | }; | ||
293 | |||
294 | struct drm_i915_error_state_buf { | ||
295 | struct drm_i915_private *i915; | ||
296 | unsigned int bytes; | ||
297 | unsigned int size; | ||
298 | int err; | ||
299 | u8 *buf; | ||
300 | loff_t start; | ||
301 | loff_t pos; | ||
302 | }; | ||
303 | |||
304 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
305 | |||
306 | __printf(2, 3) | ||
307 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); | ||
308 | int i915_error_state_to_str(struct drm_i915_error_state_buf *estr, | ||
309 | const struct i915_gpu_state *gpu); | ||
310 | int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb, | ||
311 | struct drm_i915_private *i915, | ||
312 | size_t count, loff_t pos); | ||
313 | |||
314 | static inline void | ||
315 | i915_error_state_buf_release(struct drm_i915_error_state_buf *eb) | ||
316 | { | ||
317 | kfree(eb->buf); | ||
318 | } | ||
319 | |||
320 | struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915); | ||
321 | void i915_capture_error_state(struct drm_i915_private *dev_priv, | ||
322 | u32 engine_mask, | ||
323 | const char *error_msg); | ||
324 | |||
325 | static inline struct i915_gpu_state * | ||
326 | i915_gpu_state_get(struct i915_gpu_state *gpu) | ||
327 | { | ||
328 | kref_get(&gpu->ref); | ||
329 | return gpu; | ||
330 | } | ||
331 | |||
332 | void __i915_gpu_state_free(struct kref *kref); | ||
333 | static inline void i915_gpu_state_put(struct i915_gpu_state *gpu) | ||
334 | { | ||
335 | if (gpu) | ||
336 | kref_put(&gpu->ref, __i915_gpu_state_free); | ||
337 | } | ||
338 | |||
339 | struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915); | ||
340 | void i915_reset_error_state(struct drm_i915_private *i915); | ||
341 | |||
342 | #else | ||
343 | |||
344 | static inline void i915_capture_error_state(struct drm_i915_private *dev_priv, | ||
345 | u32 engine_mask, | ||
346 | const char *error_msg) | ||
347 | { | ||
348 | } | ||
349 | |||
350 | static inline struct i915_gpu_state * | ||
351 | i915_first_error_state(struct drm_i915_private *i915) | ||
352 | { | ||
353 | return NULL; | ||
354 | } | ||
355 | |||
356 | static inline void i915_reset_error_state(struct drm_i915_private *i915) | ||
357 | { | ||
358 | } | ||
359 | |||
360 | #endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */ | ||
361 | |||
362 | #endif /* _I915_GPU_ERROR_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 633c18785c1e..b03d18561b55 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -243,6 +243,41 @@ void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, | |||
243 | spin_unlock_irq(&dev_priv->irq_lock); | 243 | spin_unlock_irq(&dev_priv->irq_lock); |
244 | } | 244 | } |
245 | 245 | ||
246 | static u32 | ||
247 | gen11_gt_engine_identity(struct drm_i915_private * const i915, | ||
248 | const unsigned int bank, const unsigned int bit); | ||
249 | |||
250 | static bool gen11_reset_one_iir(struct drm_i915_private * const i915, | ||
251 | const unsigned int bank, | ||
252 | const unsigned int bit) | ||
253 | { | ||
254 | void __iomem * const regs = i915->regs; | ||
255 | u32 dw; | ||
256 | |||
257 | lockdep_assert_held(&i915->irq_lock); | ||
258 | |||
259 | dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); | ||
260 | if (dw & BIT(bit)) { | ||
261 | /* | ||
262 | * According to the BSpec, DW_IIR bits cannot be cleared without | ||
263 | * first servicing the Selector & Shared IIR registers. | ||
264 | */ | ||
265 | gen11_gt_engine_identity(i915, bank, bit); | ||
266 | |||
267 | /* | ||
268 | * We locked GT INT DW by reading it. If we want to (try | ||
269 | * to) recover from this succesfully, we need to clear | ||
270 | * our bit, otherwise we are locking the register for | ||
271 | * everybody. | ||
272 | */ | ||
273 | raw_reg_write(regs, GEN11_GT_INTR_DW(bank), BIT(bit)); | ||
274 | |||
275 | return true; | ||
276 | } | ||
277 | |||
278 | return false; | ||
279 | } | ||
280 | |||
246 | /** | 281 | /** |
247 | * ilk_update_display_irq - update DEIMR | 282 | * ilk_update_display_irq - update DEIMR |
248 | * @dev_priv: driver private | 283 | * @dev_priv: driver private |
@@ -308,17 +343,29 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) | |||
308 | 343 | ||
309 | static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) | 344 | static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) |
310 | { | 345 | { |
346 | WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11); | ||
347 | |||
311 | return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; | 348 | return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; |
312 | } | 349 | } |
313 | 350 | ||
314 | static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) | 351 | static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) |
315 | { | 352 | { |
316 | return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IMR(2) : GEN6_PMIMR; | 353 | if (INTEL_GEN(dev_priv) >= 11) |
354 | return GEN11_GPM_WGBOXPERF_INTR_MASK; | ||
355 | else if (INTEL_GEN(dev_priv) >= 8) | ||
356 | return GEN8_GT_IMR(2); | ||
357 | else | ||
358 | return GEN6_PMIMR; | ||
317 | } | 359 | } |
318 | 360 | ||
319 | static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) | 361 | static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) |
320 | { | 362 | { |
321 | return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IER(2) : GEN6_PMIER; | 363 | if (INTEL_GEN(dev_priv) >= 11) |
364 | return GEN11_GPM_WGBOXPERF_INTR_ENABLE; | ||
365 | else if (INTEL_GEN(dev_priv) >= 8) | ||
366 | return GEN8_GT_IER(2); | ||
367 | else | ||
368 | return GEN6_PMIER; | ||
322 | } | 369 | } |
323 | 370 | ||
324 | /** | 371 | /** |
@@ -400,6 +447,18 @@ static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_m | |||
400 | /* though a barrier is missing here, but don't really need a one */ | 447 | /* though a barrier is missing here, but don't really need a one */ |
401 | } | 448 | } |
402 | 449 | ||
450 | void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv) | ||
451 | { | ||
452 | spin_lock_irq(&dev_priv->irq_lock); | ||
453 | |||
454 | while (gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)) | ||
455 | ; | ||
456 | |||
457 | dev_priv->gt_pm.rps.pm_iir = 0; | ||
458 | |||
459 | spin_unlock_irq(&dev_priv->irq_lock); | ||
460 | } | ||
461 | |||
403 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) | 462 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) |
404 | { | 463 | { |
405 | spin_lock_irq(&dev_priv->irq_lock); | 464 | spin_lock_irq(&dev_priv->irq_lock); |
@@ -415,12 +474,14 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) | |||
415 | if (READ_ONCE(rps->interrupts_enabled)) | 474 | if (READ_ONCE(rps->interrupts_enabled)) |
416 | return; | 475 | return; |
417 | 476 | ||
418 | if (WARN_ON_ONCE(IS_GEN11(dev_priv))) | ||
419 | return; | ||
420 | |||
421 | spin_lock_irq(&dev_priv->irq_lock); | 477 | spin_lock_irq(&dev_priv->irq_lock); |
422 | WARN_ON_ONCE(rps->pm_iir); | 478 | WARN_ON_ONCE(rps->pm_iir); |
423 | WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | 479 | |
480 | if (INTEL_GEN(dev_priv) >= 11) | ||
481 | WARN_ON_ONCE(gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)); | ||
482 | else | ||
483 | WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | ||
484 | |||
424 | rps->interrupts_enabled = true; | 485 | rps->interrupts_enabled = true; |
425 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 486 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
426 | 487 | ||
@@ -434,9 +495,6 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) | |||
434 | if (!READ_ONCE(rps->interrupts_enabled)) | 495 | if (!READ_ONCE(rps->interrupts_enabled)) |
435 | return; | 496 | return; |
436 | 497 | ||
437 | if (WARN_ON_ONCE(IS_GEN11(dev_priv))) | ||
438 | return; | ||
439 | |||
440 | spin_lock_irq(&dev_priv->irq_lock); | 498 | spin_lock_irq(&dev_priv->irq_lock); |
441 | rps->interrupts_enabled = false; | 499 | rps->interrupts_enabled = false; |
442 | 500 | ||
@@ -453,7 +511,10 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) | |||
453 | * state of the worker can be discarded. | 511 | * state of the worker can be discarded. |
454 | */ | 512 | */ |
455 | cancel_work_sync(&rps->work); | 513 | cancel_work_sync(&rps->work); |
456 | gen6_reset_rps_interrupts(dev_priv); | 514 | if (INTEL_GEN(dev_priv) >= 11) |
515 | gen11_reset_rps_interrupts(dev_priv); | ||
516 | else | ||
517 | gen6_reset_rps_interrupts(dev_priv); | ||
457 | } | 518 | } |
458 | 519 | ||
459 | void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv) | 520 | void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv) |
@@ -1399,19 +1460,18 @@ static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, | |||
1399 | } | 1460 | } |
1400 | 1461 | ||
1401 | static void | 1462 | static void |
1402 | gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) | 1463 | gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) |
1403 | { | 1464 | { |
1404 | struct intel_engine_execlists * const execlists = &engine->execlists; | 1465 | struct intel_engine_execlists * const execlists = &engine->execlists; |
1405 | bool tasklet = false; | 1466 | bool tasklet = false; |
1406 | 1467 | ||
1407 | if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { | 1468 | if (iir & GT_CONTEXT_SWITCH_INTERRUPT) { |
1408 | if (READ_ONCE(engine->execlists.active)) { | 1469 | if (READ_ONCE(engine->execlists.active)) |
1409 | __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 1470 | tasklet = !test_and_set_bit(ENGINE_IRQ_EXECLIST, |
1410 | tasklet = true; | 1471 | &engine->irq_posted); |
1411 | } | ||
1412 | } | 1472 | } |
1413 | 1473 | ||
1414 | if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { | 1474 | if (iir & GT_RENDER_USER_INTERRUPT) { |
1415 | notify_ring(engine); | 1475 | notify_ring(engine); |
1416 | tasklet |= USES_GUC_SUBMISSION(engine->i915); | 1476 | tasklet |= USES_GUC_SUBMISSION(engine->i915); |
1417 | } | 1477 | } |
@@ -1466,21 +1526,21 @@ static void gen8_gt_irq_handler(struct drm_i915_private *i915, | |||
1466 | { | 1526 | { |
1467 | if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { | 1527 | if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { |
1468 | gen8_cs_irq_handler(i915->engine[RCS], | 1528 | gen8_cs_irq_handler(i915->engine[RCS], |
1469 | gt_iir[0], GEN8_RCS_IRQ_SHIFT); | 1529 | gt_iir[0] >> GEN8_RCS_IRQ_SHIFT); |
1470 | gen8_cs_irq_handler(i915->engine[BCS], | 1530 | gen8_cs_irq_handler(i915->engine[BCS], |
1471 | gt_iir[0], GEN8_BCS_IRQ_SHIFT); | 1531 | gt_iir[0] >> GEN8_BCS_IRQ_SHIFT); |
1472 | } | 1532 | } |
1473 | 1533 | ||
1474 | if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { | 1534 | if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { |
1475 | gen8_cs_irq_handler(i915->engine[VCS], | 1535 | gen8_cs_irq_handler(i915->engine[VCS], |
1476 | gt_iir[1], GEN8_VCS1_IRQ_SHIFT); | 1536 | gt_iir[1] >> GEN8_VCS1_IRQ_SHIFT); |
1477 | gen8_cs_irq_handler(i915->engine[VCS2], | 1537 | gen8_cs_irq_handler(i915->engine[VCS2], |
1478 | gt_iir[1], GEN8_VCS2_IRQ_SHIFT); | 1538 | gt_iir[1] >> GEN8_VCS2_IRQ_SHIFT); |
1479 | } | 1539 | } |
1480 | 1540 | ||
1481 | if (master_ctl & GEN8_GT_VECS_IRQ) { | 1541 | if (master_ctl & GEN8_GT_VECS_IRQ) { |
1482 | gen8_cs_irq_handler(i915->engine[VECS], | 1542 | gen8_cs_irq_handler(i915->engine[VECS], |
1483 | gt_iir[3], GEN8_VECS_IRQ_SHIFT); | 1543 | gt_iir[3] >> GEN8_VECS_IRQ_SHIFT); |
1484 | } | 1544 | } |
1485 | 1545 | ||
1486 | if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { | 1546 | if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { |
@@ -1627,7 +1687,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, | |||
1627 | int head, tail; | 1687 | int head, tail; |
1628 | 1688 | ||
1629 | spin_lock(&pipe_crc->lock); | 1689 | spin_lock(&pipe_crc->lock); |
1630 | if (pipe_crc->source) { | 1690 | if (pipe_crc->source && !crtc->base.crc.opened) { |
1631 | if (!pipe_crc->entries) { | 1691 | if (!pipe_crc->entries) { |
1632 | spin_unlock(&pipe_crc->lock); | 1692 | spin_unlock(&pipe_crc->lock); |
1633 | DRM_DEBUG_KMS("spurious interrupt\n"); | 1693 | DRM_DEBUG_KMS("spurious interrupt\n"); |
@@ -1667,7 +1727,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, | |||
1667 | * On GEN8+ sometimes the second CRC is bonkers as well, so | 1727 | * On GEN8+ sometimes the second CRC is bonkers as well, so |
1668 | * don't trust that one either. | 1728 | * don't trust that one either. |
1669 | */ | 1729 | */ |
1670 | if (pipe_crc->skipped == 0 || | 1730 | if (pipe_crc->skipped <= 0 || |
1671 | (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { | 1731 | (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { |
1672 | pipe_crc->skipped++; | 1732 | pipe_crc->skipped++; |
1673 | spin_unlock(&pipe_crc->lock); | 1733 | spin_unlock(&pipe_crc->lock); |
@@ -1766,37 +1826,8 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) | |||
1766 | 1826 | ||
1767 | static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) | 1827 | static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) |
1768 | { | 1828 | { |
1769 | if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) { | 1829 | if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) |
1770 | /* Sample the log buffer flush related bits & clear them out now | 1830 | intel_guc_to_host_event_handler(&dev_priv->guc); |
1771 | * itself from the message identity register to minimize the | ||
1772 | * probability of losing a flush interrupt, when there are back | ||
1773 | * to back flush interrupts. | ||
1774 | * There can be a new flush interrupt, for different log buffer | ||
1775 | * type (like for ISR), whilst Host is handling one (for DPC). | ||
1776 | * Since same bit is used in message register for ISR & DPC, it | ||
1777 | * could happen that GuC sets the bit for 2nd interrupt but Host | ||
1778 | * clears out the bit on handling the 1st interrupt. | ||
1779 | */ | ||
1780 | u32 msg, flush; | ||
1781 | |||
1782 | msg = I915_READ(SOFT_SCRATCH(15)); | ||
1783 | flush = msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED | | ||
1784 | INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER); | ||
1785 | if (flush) { | ||
1786 | /* Clear the message bits that are handled */ | ||
1787 | I915_WRITE(SOFT_SCRATCH(15), msg & ~flush); | ||
1788 | |||
1789 | /* Handle flush interrupt in bottom half */ | ||
1790 | queue_work(dev_priv->guc.log.runtime.flush_wq, | ||
1791 | &dev_priv->guc.log.runtime.flush_work); | ||
1792 | |||
1793 | dev_priv->guc.log.flush_interrupt_count++; | ||
1794 | } else { | ||
1795 | /* Not clearing of unhandled event bits won't result in | ||
1796 | * re-triggering of the interrupt. | ||
1797 | */ | ||
1798 | } | ||
1799 | } | ||
1800 | } | 1831 | } |
1801 | 1832 | ||
1802 | static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) | 1833 | static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) |
@@ -2762,58 +2793,16 @@ static void __fini_wedge(struct wedge_me *w) | |||
2762 | (W)->i915; \ | 2793 | (W)->i915; \ |
2763 | __fini_wedge((W))) | 2794 | __fini_wedge((W))) |
2764 | 2795 | ||
2765 | static __always_inline void | ||
2766 | gen11_cs_irq_handler(struct intel_engine_cs * const engine, const u32 iir) | ||
2767 | { | ||
2768 | gen8_cs_irq_handler(engine, iir, 0); | ||
2769 | } | ||
2770 | |||
2771 | static void | ||
2772 | gen11_gt_engine_irq_handler(struct drm_i915_private * const i915, | ||
2773 | const unsigned int bank, | ||
2774 | const unsigned int engine_n, | ||
2775 | const u16 iir) | ||
2776 | { | ||
2777 | struct intel_engine_cs ** const engine = i915->engine; | ||
2778 | |||
2779 | switch (bank) { | ||
2780 | case 0: | ||
2781 | switch (engine_n) { | ||
2782 | |||
2783 | case GEN11_RCS0: | ||
2784 | return gen11_cs_irq_handler(engine[RCS], iir); | ||
2785 | |||
2786 | case GEN11_BCS: | ||
2787 | return gen11_cs_irq_handler(engine[BCS], iir); | ||
2788 | } | ||
2789 | case 1: | ||
2790 | switch (engine_n) { | ||
2791 | |||
2792 | case GEN11_VCS(0): | ||
2793 | return gen11_cs_irq_handler(engine[_VCS(0)], iir); | ||
2794 | case GEN11_VCS(1): | ||
2795 | return gen11_cs_irq_handler(engine[_VCS(1)], iir); | ||
2796 | case GEN11_VCS(2): | ||
2797 | return gen11_cs_irq_handler(engine[_VCS(2)], iir); | ||
2798 | case GEN11_VCS(3): | ||
2799 | return gen11_cs_irq_handler(engine[_VCS(3)], iir); | ||
2800 | |||
2801 | case GEN11_VECS(0): | ||
2802 | return gen11_cs_irq_handler(engine[_VECS(0)], iir); | ||
2803 | case GEN11_VECS(1): | ||
2804 | return gen11_cs_irq_handler(engine[_VECS(1)], iir); | ||
2805 | } | ||
2806 | } | ||
2807 | } | ||
2808 | |||
2809 | static u32 | 2796 | static u32 |
2810 | gen11_gt_engine_intr(struct drm_i915_private * const i915, | 2797 | gen11_gt_engine_identity(struct drm_i915_private * const i915, |
2811 | const unsigned int bank, const unsigned int bit) | 2798 | const unsigned int bank, const unsigned int bit) |
2812 | { | 2799 | { |
2813 | void __iomem * const regs = i915->regs; | 2800 | void __iomem * const regs = i915->regs; |
2814 | u32 timeout_ts; | 2801 | u32 timeout_ts; |
2815 | u32 ident; | 2802 | u32 ident; |
2816 | 2803 | ||
2804 | lockdep_assert_held(&i915->irq_lock); | ||
2805 | |||
2817 | raw_reg_write(regs, GEN11_IIR_REG_SELECTOR(bank), BIT(bit)); | 2806 | raw_reg_write(regs, GEN11_IIR_REG_SELECTOR(bank), BIT(bit)); |
2818 | 2807 | ||
2819 | /* | 2808 | /* |
@@ -2835,42 +2824,101 @@ gen11_gt_engine_intr(struct drm_i915_private * const i915, | |||
2835 | raw_reg_write(regs, GEN11_INTR_IDENTITY_REG(bank), | 2824 | raw_reg_write(regs, GEN11_INTR_IDENTITY_REG(bank), |
2836 | GEN11_INTR_DATA_VALID); | 2825 | GEN11_INTR_DATA_VALID); |
2837 | 2826 | ||
2838 | return ident & GEN11_INTR_ENGINE_MASK; | 2827 | return ident; |
2839 | } | 2828 | } |
2840 | 2829 | ||
2841 | static void | 2830 | static void |
2842 | gen11_gt_irq_handler(struct drm_i915_private * const i915, | 2831 | gen11_other_irq_handler(struct drm_i915_private * const i915, |
2843 | const u32 master_ctl) | 2832 | const u8 instance, const u16 iir) |
2833 | { | ||
2834 | if (instance == OTHER_GTPM_INSTANCE) | ||
2835 | return gen6_rps_irq_handler(i915, iir); | ||
2836 | |||
2837 | WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", | ||
2838 | instance, iir); | ||
2839 | } | ||
2840 | |||
2841 | static void | ||
2842 | gen11_engine_irq_handler(struct drm_i915_private * const i915, | ||
2843 | const u8 class, const u8 instance, const u16 iir) | ||
2844 | { | ||
2845 | struct intel_engine_cs *engine; | ||
2846 | |||
2847 | if (instance <= MAX_ENGINE_INSTANCE) | ||
2848 | engine = i915->engine_class[class][instance]; | ||
2849 | else | ||
2850 | engine = NULL; | ||
2851 | |||
2852 | if (likely(engine)) | ||
2853 | return gen8_cs_irq_handler(engine, iir); | ||
2854 | |||
2855 | WARN_ONCE(1, "unhandled engine interrupt class=0x%x, instance=0x%x\n", | ||
2856 | class, instance); | ||
2857 | } | ||
2858 | |||
2859 | static void | ||
2860 | gen11_gt_identity_handler(struct drm_i915_private * const i915, | ||
2861 | const u32 identity) | ||
2862 | { | ||
2863 | const u8 class = GEN11_INTR_ENGINE_CLASS(identity); | ||
2864 | const u8 instance = GEN11_INTR_ENGINE_INSTANCE(identity); | ||
2865 | const u16 intr = GEN11_INTR_ENGINE_INTR(identity); | ||
2866 | |||
2867 | if (unlikely(!intr)) | ||
2868 | return; | ||
2869 | |||
2870 | if (class <= COPY_ENGINE_CLASS) | ||
2871 | return gen11_engine_irq_handler(i915, class, instance, intr); | ||
2872 | |||
2873 | if (class == OTHER_CLASS) | ||
2874 | return gen11_other_irq_handler(i915, instance, intr); | ||
2875 | |||
2876 | WARN_ONCE(1, "unknown interrupt class=0x%x, instance=0x%x, intr=0x%x\n", | ||
2877 | class, instance, intr); | ||
2878 | } | ||
2879 | |||
2880 | static void | ||
2881 | gen11_gt_bank_handler(struct drm_i915_private * const i915, | ||
2882 | const unsigned int bank) | ||
2844 | { | 2883 | { |
2845 | void __iomem * const regs = i915->regs; | 2884 | void __iomem * const regs = i915->regs; |
2846 | unsigned int bank; | 2885 | unsigned long intr_dw; |
2886 | unsigned int bit; | ||
2847 | 2887 | ||
2848 | for (bank = 0; bank < 2; bank++) { | 2888 | lockdep_assert_held(&i915->irq_lock); |
2849 | unsigned long intr_dw; | ||
2850 | unsigned int bit; | ||
2851 | 2889 | ||
2852 | if (!(master_ctl & GEN11_GT_DW_IRQ(bank))) | 2890 | intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); |
2853 | continue; | ||
2854 | 2891 | ||
2855 | intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); | 2892 | if (unlikely(!intr_dw)) { |
2893 | DRM_ERROR("GT_INTR_DW%u blank!\n", bank); | ||
2894 | return; | ||
2895 | } | ||
2856 | 2896 | ||
2857 | if (unlikely(!intr_dw)) { | 2897 | for_each_set_bit(bit, &intr_dw, 32) { |
2858 | DRM_ERROR("GT_INTR_DW%u blank!\n", bank); | 2898 | const u32 ident = gen11_gt_engine_identity(i915, |
2859 | continue; | 2899 | bank, bit); |
2860 | } | ||
2861 | 2900 | ||
2862 | for_each_set_bit(bit, &intr_dw, 32) { | 2901 | gen11_gt_identity_handler(i915, ident); |
2863 | const u16 iir = gen11_gt_engine_intr(i915, bank, bit); | 2902 | } |
2864 | 2903 | ||
2865 | if (unlikely(!iir)) | 2904 | /* Clear must be after shared has been served for engine */ |
2866 | continue; | 2905 | raw_reg_write(regs, GEN11_GT_INTR_DW(bank), intr_dw); |
2906 | } | ||
2867 | 2907 | ||
2868 | gen11_gt_engine_irq_handler(i915, bank, bit, iir); | 2908 | static void |
2869 | } | 2909 | gen11_gt_irq_handler(struct drm_i915_private * const i915, |
2910 | const u32 master_ctl) | ||
2911 | { | ||
2912 | unsigned int bank; | ||
2870 | 2913 | ||
2871 | /* Clear must be after shared has been served for engine */ | 2914 | spin_lock(&i915->irq_lock); |
2872 | raw_reg_write(regs, GEN11_GT_INTR_DW(bank), intr_dw); | 2915 | |
2916 | for (bank = 0; bank < 2; bank++) { | ||
2917 | if (master_ctl & GEN11_GT_DW_IRQ(bank)) | ||
2918 | gen11_gt_bank_handler(i915, bank); | ||
2873 | } | 2919 | } |
2920 | |||
2921 | spin_unlock(&i915->irq_lock); | ||
2874 | } | 2922 | } |
2875 | 2923 | ||
2876 | static irqreturn_t gen11_irq_handler(int irq, void *arg) | 2924 | static irqreturn_t gen11_irq_handler(int irq, void *arg) |
@@ -2912,15 +2960,11 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) | |||
2912 | return IRQ_HANDLED; | 2960 | return IRQ_HANDLED; |
2913 | } | 2961 | } |
2914 | 2962 | ||
2915 | /** | 2963 | static void i915_reset_device(struct drm_i915_private *dev_priv, |
2916 | * i915_reset_device - do process context error handling work | 2964 | u32 engine_mask, |
2917 | * @dev_priv: i915 device private | 2965 | const char *reason) |
2918 | * | ||
2919 | * Fire an error uevent so userspace can see that a hang or error | ||
2920 | * was detected. | ||
2921 | */ | ||
2922 | static void i915_reset_device(struct drm_i915_private *dev_priv) | ||
2923 | { | 2966 | { |
2967 | struct i915_gpu_error *error = &dev_priv->gpu_error; | ||
2924 | struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; | 2968 | struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; |
2925 | char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; | 2969 | char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; |
2926 | char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; | 2970 | char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; |
@@ -2936,29 +2980,35 @@ static void i915_reset_device(struct drm_i915_private *dev_priv) | |||
2936 | i915_wedge_on_timeout(&w, dev_priv, 5*HZ) { | 2980 | i915_wedge_on_timeout(&w, dev_priv, 5*HZ) { |
2937 | intel_prepare_reset(dev_priv); | 2981 | intel_prepare_reset(dev_priv); |
2938 | 2982 | ||
2983 | error->reason = reason; | ||
2984 | error->stalled_mask = engine_mask; | ||
2985 | |||
2939 | /* Signal that locked waiters should reset the GPU */ | 2986 | /* Signal that locked waiters should reset the GPU */ |
2940 | set_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags); | 2987 | smp_mb__before_atomic(); |
2941 | wake_up_all(&dev_priv->gpu_error.wait_queue); | 2988 | set_bit(I915_RESET_HANDOFF, &error->flags); |
2989 | wake_up_all(&error->wait_queue); | ||
2942 | 2990 | ||
2943 | /* Wait for anyone holding the lock to wakeup, without | 2991 | /* Wait for anyone holding the lock to wakeup, without |
2944 | * blocking indefinitely on struct_mutex. | 2992 | * blocking indefinitely on struct_mutex. |
2945 | */ | 2993 | */ |
2946 | do { | 2994 | do { |
2947 | if (mutex_trylock(&dev_priv->drm.struct_mutex)) { | 2995 | if (mutex_trylock(&dev_priv->drm.struct_mutex)) { |
2948 | i915_reset(dev_priv, 0); | 2996 | i915_reset(dev_priv, engine_mask, reason); |
2949 | mutex_unlock(&dev_priv->drm.struct_mutex); | 2997 | mutex_unlock(&dev_priv->drm.struct_mutex); |
2950 | } | 2998 | } |
2951 | } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags, | 2999 | } while (wait_on_bit_timeout(&error->flags, |
2952 | I915_RESET_HANDOFF, | 3000 | I915_RESET_HANDOFF, |
2953 | TASK_UNINTERRUPTIBLE, | 3001 | TASK_UNINTERRUPTIBLE, |
2954 | 1)); | 3002 | 1)); |
2955 | 3003 | ||
3004 | error->stalled_mask = 0; | ||
3005 | error->reason = NULL; | ||
3006 | |||
2956 | intel_finish_reset(dev_priv); | 3007 | intel_finish_reset(dev_priv); |
2957 | } | 3008 | } |
2958 | 3009 | ||
2959 | if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) | 3010 | if (!test_bit(I915_WEDGED, &error->flags)) |
2960 | kobject_uevent_env(kobj, | 3011 | kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); |
2961 | KOBJ_CHANGE, reset_done_event); | ||
2962 | } | 3012 | } |
2963 | 3013 | ||
2964 | static void i915_clear_error_registers(struct drm_i915_private *dev_priv) | 3014 | static void i915_clear_error_registers(struct drm_i915_private *dev_priv) |
@@ -2990,6 +3040,7 @@ static void i915_clear_error_registers(struct drm_i915_private *dev_priv) | |||
2990 | * i915_handle_error - handle a gpu error | 3040 | * i915_handle_error - handle a gpu error |
2991 | * @dev_priv: i915 device private | 3041 | * @dev_priv: i915 device private |
2992 | * @engine_mask: mask representing engines that are hung | 3042 | * @engine_mask: mask representing engines that are hung |
3043 | * @flags: control flags | ||
2993 | * @fmt: Error message format string | 3044 | * @fmt: Error message format string |
2994 | * | 3045 | * |
2995 | * Do some basic checking of register state at error time and | 3046 | * Do some basic checking of register state at error time and |
@@ -3000,16 +3051,23 @@ static void i915_clear_error_registers(struct drm_i915_private *dev_priv) | |||
3000 | */ | 3051 | */ |
3001 | void i915_handle_error(struct drm_i915_private *dev_priv, | 3052 | void i915_handle_error(struct drm_i915_private *dev_priv, |
3002 | u32 engine_mask, | 3053 | u32 engine_mask, |
3054 | unsigned long flags, | ||
3003 | const char *fmt, ...) | 3055 | const char *fmt, ...) |
3004 | { | 3056 | { |
3005 | struct intel_engine_cs *engine; | 3057 | struct intel_engine_cs *engine; |
3006 | unsigned int tmp; | 3058 | unsigned int tmp; |
3007 | va_list args; | ||
3008 | char error_msg[80]; | 3059 | char error_msg[80]; |
3060 | char *msg = NULL; | ||
3009 | 3061 | ||
3010 | va_start(args, fmt); | 3062 | if (fmt) { |
3011 | vscnprintf(error_msg, sizeof(error_msg), fmt, args); | 3063 | va_list args; |
3012 | va_end(args); | 3064 | |
3065 | va_start(args, fmt); | ||
3066 | vscnprintf(error_msg, sizeof(error_msg), fmt, args); | ||
3067 | va_end(args); | ||
3068 | |||
3069 | msg = error_msg; | ||
3070 | } | ||
3013 | 3071 | ||
3014 | /* | 3072 | /* |
3015 | * In most cases it's guaranteed that we get here with an RPM | 3073 | * In most cases it's guaranteed that we get here with an RPM |
@@ -3020,8 +3078,12 @@ void i915_handle_error(struct drm_i915_private *dev_priv, | |||
3020 | */ | 3078 | */ |
3021 | intel_runtime_pm_get(dev_priv); | 3079 | intel_runtime_pm_get(dev_priv); |
3022 | 3080 | ||
3023 | i915_capture_error_state(dev_priv, engine_mask, error_msg); | 3081 | engine_mask &= INTEL_INFO(dev_priv)->ring_mask; |
3024 | i915_clear_error_registers(dev_priv); | 3082 | |
3083 | if (flags & I915_ERROR_CAPTURE) { | ||
3084 | i915_capture_error_state(dev_priv, engine_mask, msg); | ||
3085 | i915_clear_error_registers(dev_priv); | ||
3086 | } | ||
3025 | 3087 | ||
3026 | /* | 3088 | /* |
3027 | * Try engine reset when available. We fall back to full reset if | 3089 | * Try engine reset when available. We fall back to full reset if |
@@ -3034,7 +3096,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv, | |||
3034 | &dev_priv->gpu_error.flags)) | 3096 | &dev_priv->gpu_error.flags)) |
3035 | continue; | 3097 | continue; |
3036 | 3098 | ||
3037 | if (i915_reset_engine(engine, 0) == 0) | 3099 | if (i915_reset_engine(engine, msg) == 0) |
3038 | engine_mask &= ~intel_engine_flag(engine); | 3100 | engine_mask &= ~intel_engine_flag(engine); |
3039 | 3101 | ||
3040 | clear_bit(I915_RESET_ENGINE + engine->id, | 3102 | clear_bit(I915_RESET_ENGINE + engine->id, |
@@ -3064,7 +3126,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv, | |||
3064 | TASK_UNINTERRUPTIBLE); | 3126 | TASK_UNINTERRUPTIBLE); |
3065 | } | 3127 | } |
3066 | 3128 | ||
3067 | i915_reset_device(dev_priv); | 3129 | i915_reset_device(dev_priv, engine_mask, msg); |
3068 | 3130 | ||
3069 | for_each_engine(engine, dev_priv, tmp) { | 3131 | for_each_engine(engine, dev_priv, tmp) { |
3070 | clear_bit(I915_RESET_ENGINE + engine->id, | 3132 | clear_bit(I915_RESET_ENGINE + engine->id, |
@@ -3349,6 +3411,9 @@ static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv) | |||
3349 | I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~0); | 3411 | I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~0); |
3350 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~0); | 3412 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~0); |
3351 | I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~0); | 3413 | I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~0); |
3414 | |||
3415 | I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); | ||
3416 | I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); | ||
3352 | } | 3417 | } |
3353 | 3418 | ||
3354 | static void gen11_irq_reset(struct drm_device *dev) | 3419 | static void gen11_irq_reset(struct drm_device *dev) |
@@ -3887,7 +3952,14 @@ static void gen11_gt_irq_postinstall(struct drm_i915_private *dev_priv) | |||
3887 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~(irqs | irqs << 16)); | 3952 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~(irqs | irqs << 16)); |
3888 | I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~(irqs | irqs << 16)); | 3953 | I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~(irqs | irqs << 16)); |
3889 | 3954 | ||
3890 | dev_priv->pm_imr = 0xffffffff; /* TODO */ | 3955 | /* |
3956 | * RPS interrupts will get enabled/disabled on demand when RPS itself | ||
3957 | * is enabled/disabled. | ||
3958 | */ | ||
3959 | dev_priv->pm_ier = 0x0; | ||
3960 | dev_priv->pm_imr = ~dev_priv->pm_ier; | ||
3961 | I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); | ||
3962 | I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); | ||
3891 | } | 3963 | } |
3892 | 3964 | ||
3893 | static int gen11_irq_postinstall(struct drm_device *dev) | 3965 | static int gen11_irq_postinstall(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/i915_oa_icl.c b/drivers/gpu/drm/i915/i915_oa_icl.c new file mode 100644 index 000000000000..a5667926e3de --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_icl.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Autogenerated file by GPU Top : https://github.com/rib/gputop | ||
3 | * DO NOT EDIT manually! | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 2015 Intel Corporation | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
25 | * IN THE SOFTWARE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/sysfs.h> | ||
30 | |||
31 | #include "i915_drv.h" | ||
32 | #include "i915_oa_icl.h" | ||
33 | |||
34 | static const struct i915_oa_reg b_counter_config_test_oa[] = { | ||
35 | { _MMIO(0x2740), 0x00000000 }, | ||
36 | { _MMIO(0x2710), 0x00000000 }, | ||
37 | { _MMIO(0x2714), 0xf0800000 }, | ||
38 | { _MMIO(0x2720), 0x00000000 }, | ||
39 | { _MMIO(0x2724), 0xf0800000 }, | ||
40 | { _MMIO(0x2770), 0x00000004 }, | ||
41 | { _MMIO(0x2774), 0x0000ffff }, | ||
42 | { _MMIO(0x2778), 0x00000003 }, | ||
43 | { _MMIO(0x277c), 0x0000ffff }, | ||
44 | { _MMIO(0x2780), 0x00000007 }, | ||
45 | { _MMIO(0x2784), 0x0000ffff }, | ||
46 | { _MMIO(0x2788), 0x00100002 }, | ||
47 | { _MMIO(0x278c), 0x0000fff7 }, | ||
48 | { _MMIO(0x2790), 0x00100002 }, | ||
49 | { _MMIO(0x2794), 0x0000ffcf }, | ||
50 | { _MMIO(0x2798), 0x00100082 }, | ||
51 | { _MMIO(0x279c), 0x0000ffef }, | ||
52 | { _MMIO(0x27a0), 0x001000c2 }, | ||
53 | { _MMIO(0x27a4), 0x0000ffe7 }, | ||
54 | { _MMIO(0x27a8), 0x00100001 }, | ||
55 | { _MMIO(0x27ac), 0x0000ffe7 }, | ||
56 | }; | ||
57 | |||
58 | static const struct i915_oa_reg flex_eu_config_test_oa[] = { | ||
59 | }; | ||
60 | |||
61 | static const struct i915_oa_reg mux_config_test_oa[] = { | ||
62 | { _MMIO(0xd04), 0x00000200 }, | ||
63 | { _MMIO(0x9840), 0x00000000 }, | ||
64 | { _MMIO(0x9884), 0x00000000 }, | ||
65 | { _MMIO(0x9888), 0x10060000 }, | ||
66 | { _MMIO(0x9888), 0x22060000 }, | ||
67 | { _MMIO(0x9888), 0x16060000 }, | ||
68 | { _MMIO(0x9888), 0x24060000 }, | ||
69 | { _MMIO(0x9888), 0x18060000 }, | ||
70 | { _MMIO(0x9888), 0x1a060000 }, | ||
71 | { _MMIO(0x9888), 0x12060000 }, | ||
72 | { _MMIO(0x9888), 0x14060000 }, | ||
73 | { _MMIO(0x9888), 0x10060000 }, | ||
74 | { _MMIO(0x9888), 0x22060000 }, | ||
75 | { _MMIO(0x9884), 0x00000003 }, | ||
76 | { _MMIO(0x9888), 0x16130000 }, | ||
77 | { _MMIO(0x9888), 0x24000001 }, | ||
78 | { _MMIO(0x9888), 0x0e130056 }, | ||
79 | { _MMIO(0x9888), 0x10130000 }, | ||
80 | { _MMIO(0x9888), 0x1a130000 }, | ||
81 | { _MMIO(0x9888), 0x541f0001 }, | ||
82 | { _MMIO(0x9888), 0x181f0000 }, | ||
83 | { _MMIO(0x9888), 0x4c1f0000 }, | ||
84 | { _MMIO(0x9888), 0x301f0000 }, | ||
85 | }; | ||
86 | |||
87 | static ssize_t | ||
88 | show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) | ||
89 | { | ||
90 | return sprintf(buf, "1\n"); | ||
91 | } | ||
92 | |||
93 | void | ||
94 | i915_perf_load_test_config_icl(struct drm_i915_private *dev_priv) | ||
95 | { | ||
96 | strlcpy(dev_priv->perf.oa.test_config.uuid, | ||
97 | "a291665e-244b-4b76-9b9a-01de9d3c8068", | ||
98 | sizeof(dev_priv->perf.oa.test_config.uuid)); | ||
99 | dev_priv->perf.oa.test_config.id = 1; | ||
100 | |||
101 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; | ||
102 | dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa); | ||
103 | |||
104 | dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa; | ||
105 | dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa); | ||
106 | |||
107 | dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa; | ||
108 | dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa); | ||
109 | |||
110 | dev_priv->perf.oa.test_config.sysfs_metric.name = "a291665e-244b-4b76-9b9a-01de9d3c8068"; | ||
111 | dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs; | ||
112 | |||
113 | dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr; | ||
114 | |||
115 | dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id"; | ||
116 | dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444; | ||
117 | dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id; | ||
118 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_oa_icl.h b/drivers/gpu/drm/i915/i915_oa_icl.h new file mode 100644 index 000000000000..ae1c24aafe4f --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_icl.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Autogenerated file by GPU Top : https://github.com/rib/gputop | ||
3 | * DO NOT EDIT manually! | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 2015 Intel Corporation | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
25 | * IN THE SOFTWARE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef __I915_OA_ICL_H__ | ||
30 | #define __I915_OA_ICL_H__ | ||
31 | |||
32 | extern void i915_perf_load_test_config_icl(struct drm_i915_private *dev_priv); | ||
33 | |||
34 | #endif | ||
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 430f5f9d0ff4..c96360398072 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h | |||
@@ -48,7 +48,7 @@ struct drm_printer; | |||
48 | param(int, enable_ips, 1) \ | 48 | param(int, enable_ips, 1) \ |
49 | param(int, invert_brightness, 0) \ | 49 | param(int, invert_brightness, 0) \ |
50 | param(int, enable_guc, 0) \ | 50 | param(int, enable_guc, 0) \ |
51 | param(int, guc_log_level, 0) \ | 51 | param(int, guc_log_level, -1) \ |
52 | param(char *, guc_firmware_path, NULL) \ | 52 | param(char *, guc_firmware_path, NULL) \ |
53 | param(char *, huc_firmware_path, NULL) \ | 53 | param(char *, huc_firmware_path, NULL) \ |
54 | param(int, mmio_debug, 0) \ | 54 | param(int, mmio_debug, 0) \ |
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 062e91b39085..4364922e935d 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c | |||
@@ -602,6 +602,7 @@ static const struct intel_device_info intel_icelake_11_info = { | |||
602 | PLATFORM(INTEL_ICELAKE), | 602 | PLATFORM(INTEL_ICELAKE), |
603 | .is_alpha_support = 1, | 603 | .is_alpha_support = 1, |
604 | .has_resource_streamer = 0, | 604 | .has_resource_streamer = 0, |
605 | .ring_mask = RENDER_RING | BLT_RING | VEBOX_RING | BSD_RING | BSD3_RING, | ||
605 | }; | 606 | }; |
606 | 607 | ||
607 | #undef GEN | 608 | #undef GEN |
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index abaca6edeb71..bfc906cd4e5e 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c | |||
@@ -209,6 +209,7 @@ | |||
209 | #include "i915_oa_cflgt2.h" | 209 | #include "i915_oa_cflgt2.h" |
210 | #include "i915_oa_cflgt3.h" | 210 | #include "i915_oa_cflgt3.h" |
211 | #include "i915_oa_cnl.h" | 211 | #include "i915_oa_cnl.h" |
212 | #include "i915_oa_icl.h" | ||
212 | 213 | ||
213 | /* HW requires this to be a power of two, between 128k and 16M, though driver | 214 | /* HW requires this to be a power of two, between 128k and 16M, though driver |
214 | * is currently generally designed assuming the largest 16M size is used such | 215 | * is currently generally designed assuming the largest 16M size is used such |
@@ -1042,7 +1043,7 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream, | |||
1042 | 1043 | ||
1043 | I915_WRITE(GEN7_OASTATUS2, | 1044 | I915_WRITE(GEN7_OASTATUS2, |
1044 | ((head & GEN7_OASTATUS2_HEAD_MASK) | | 1045 | ((head & GEN7_OASTATUS2_HEAD_MASK) | |
1045 | OA_MEM_SELECT_GGTT)); | 1046 | GEN7_OASTATUS2_MEM_SELECT_GGTT)); |
1046 | dev_priv->perf.oa.oa_buffer.head = head; | 1047 | dev_priv->perf.oa.oa_buffer.head = head; |
1047 | 1048 | ||
1048 | spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags); | 1049 | spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags); |
@@ -1332,7 +1333,8 @@ static void gen7_init_oa_buffer(struct drm_i915_private *dev_priv) | |||
1332 | /* Pre-DevBDW: OABUFFER must be set with counters off, | 1333 | /* Pre-DevBDW: OABUFFER must be set with counters off, |
1333 | * before OASTATUS1, but after OASTATUS2 | 1334 | * before OASTATUS1, but after OASTATUS2 |
1334 | */ | 1335 | */ |
1335 | I915_WRITE(GEN7_OASTATUS2, gtt_offset | OA_MEM_SELECT_GGTT); /* head */ | 1336 | I915_WRITE(GEN7_OASTATUS2, |
1337 | gtt_offset | GEN7_OASTATUS2_MEM_SELECT_GGTT); /* head */ | ||
1336 | dev_priv->perf.oa.oa_buffer.head = gtt_offset; | 1338 | dev_priv->perf.oa.oa_buffer.head = gtt_offset; |
1337 | 1339 | ||
1338 | I915_WRITE(GEN7_OABUFFER, gtt_offset); | 1340 | I915_WRITE(GEN7_OABUFFER, gtt_offset); |
@@ -1392,7 +1394,7 @@ static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv) | |||
1392 | * bit." | 1394 | * bit." |
1393 | */ | 1395 | */ |
1394 | I915_WRITE(GEN8_OABUFFER, gtt_offset | | 1396 | I915_WRITE(GEN8_OABUFFER, gtt_offset | |
1395 | OABUFFER_SIZE_16M | OA_MEM_SELECT_GGTT); | 1397 | OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT); |
1396 | I915_WRITE(GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK); | 1398 | I915_WRITE(GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK); |
1397 | 1399 | ||
1398 | /* Mark that we need updated tail pointers to read from... */ | 1400 | /* Mark that we need updated tail pointers to read from... */ |
@@ -1840,7 +1842,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, | |||
1840 | * be read back from automatically triggered reports, as part of the | 1842 | * be read back from automatically triggered reports, as part of the |
1841 | * RPT_ID field. | 1843 | * RPT_ID field. |
1842 | */ | 1844 | */ |
1843 | if (IS_GEN9(dev_priv) || IS_GEN10(dev_priv)) { | 1845 | if (IS_GEN(dev_priv, 9, 11)) { |
1844 | I915_WRITE(GEN8_OA_DEBUG, | 1846 | I915_WRITE(GEN8_OA_DEBUG, |
1845 | _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | | 1847 | _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | |
1846 | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); | 1848 | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); |
@@ -1870,7 +1872,6 @@ static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) | |||
1870 | 1872 | ||
1871 | I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & | 1873 | I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & |
1872 | ~GT_NOA_ENABLE)); | 1874 | ~GT_NOA_ENABLE)); |
1873 | |||
1874 | } | 1875 | } |
1875 | 1876 | ||
1876 | static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) | 1877 | static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) |
@@ -1885,6 +1886,13 @@ static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) | |||
1885 | 1886 | ||
1886 | static void gen7_oa_enable(struct drm_i915_private *dev_priv) | 1887 | static void gen7_oa_enable(struct drm_i915_private *dev_priv) |
1887 | { | 1888 | { |
1889 | struct i915_gem_context *ctx = | ||
1890 | dev_priv->perf.oa.exclusive_stream->ctx; | ||
1891 | u32 ctx_id = dev_priv->perf.oa.specific_ctx_id; | ||
1892 | bool periodic = dev_priv->perf.oa.periodic; | ||
1893 | u32 period_exponent = dev_priv->perf.oa.period_exponent; | ||
1894 | u32 report_format = dev_priv->perf.oa.oa_buffer.format; | ||
1895 | |||
1888 | /* | 1896 | /* |
1889 | * Reset buf pointers so we don't forward reports from before now. | 1897 | * Reset buf pointers so we don't forward reports from before now. |
1890 | * | 1898 | * |
@@ -1896,25 +1904,14 @@ static void gen7_oa_enable(struct drm_i915_private *dev_priv) | |||
1896 | */ | 1904 | */ |
1897 | gen7_init_oa_buffer(dev_priv); | 1905 | gen7_init_oa_buffer(dev_priv); |
1898 | 1906 | ||
1899 | if (dev_priv->perf.oa.exclusive_stream->enabled) { | 1907 | I915_WRITE(GEN7_OACONTROL, |
1900 | struct i915_gem_context *ctx = | 1908 | (ctx_id & GEN7_OACONTROL_CTX_MASK) | |
1901 | dev_priv->perf.oa.exclusive_stream->ctx; | 1909 | (period_exponent << |
1902 | u32 ctx_id = dev_priv->perf.oa.specific_ctx_id; | 1910 | GEN7_OACONTROL_TIMER_PERIOD_SHIFT) | |
1903 | 1911 | (periodic ? GEN7_OACONTROL_TIMER_ENABLE : 0) | | |
1904 | bool periodic = dev_priv->perf.oa.periodic; | 1912 | (report_format << GEN7_OACONTROL_FORMAT_SHIFT) | |
1905 | u32 period_exponent = dev_priv->perf.oa.period_exponent; | 1913 | (ctx ? GEN7_OACONTROL_PER_CTX_ENABLE : 0) | |
1906 | u32 report_format = dev_priv->perf.oa.oa_buffer.format; | 1914 | GEN7_OACONTROL_ENABLE); |
1907 | |||
1908 | I915_WRITE(GEN7_OACONTROL, | ||
1909 | (ctx_id & GEN7_OACONTROL_CTX_MASK) | | ||
1910 | (period_exponent << | ||
1911 | GEN7_OACONTROL_TIMER_PERIOD_SHIFT) | | ||
1912 | (periodic ? GEN7_OACONTROL_TIMER_ENABLE : 0) | | ||
1913 | (report_format << GEN7_OACONTROL_FORMAT_SHIFT) | | ||
1914 | (ctx ? GEN7_OACONTROL_PER_CTX_ENABLE : 0) | | ||
1915 | GEN7_OACONTROL_ENABLE); | ||
1916 | } else | ||
1917 | I915_WRITE(GEN7_OACONTROL, 0); | ||
1918 | } | 1915 | } |
1919 | 1916 | ||
1920 | static void gen8_oa_enable(struct drm_i915_private *dev_priv) | 1917 | static void gen8_oa_enable(struct drm_i915_private *dev_priv) |
@@ -2099,13 +2096,17 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, | |||
2099 | 2096 | ||
2100 | if (stream->ctx) { | 2097 | if (stream->ctx) { |
2101 | ret = oa_get_render_ctx_id(stream); | 2098 | ret = oa_get_render_ctx_id(stream); |
2102 | if (ret) | 2099 | if (ret) { |
2100 | DRM_DEBUG("Invalid context id to filter with\n"); | ||
2103 | return ret; | 2101 | return ret; |
2102 | } | ||
2104 | } | 2103 | } |
2105 | 2104 | ||
2106 | ret = get_oa_config(dev_priv, props->metrics_set, &stream->oa_config); | 2105 | ret = get_oa_config(dev_priv, props->metrics_set, &stream->oa_config); |
2107 | if (ret) | 2106 | if (ret) { |
2107 | DRM_DEBUG("Invalid OA config id=%i\n", props->metrics_set); | ||
2108 | goto err_config; | 2108 | goto err_config; |
2109 | } | ||
2109 | 2110 | ||
2110 | /* PRM - observability performance counters: | 2111 | /* PRM - observability performance counters: |
2111 | * | 2112 | * |
@@ -2132,8 +2133,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, | |||
2132 | 2133 | ||
2133 | ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv, | 2134 | ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv, |
2134 | stream->oa_config); | 2135 | stream->oa_config); |
2135 | if (ret) | 2136 | if (ret) { |
2137 | DRM_DEBUG("Unable to enable metric set\n"); | ||
2136 | goto err_enable; | 2138 | goto err_enable; |
2139 | } | ||
2137 | 2140 | ||
2138 | stream->ops = &i915_oa_stream_ops; | 2141 | stream->ops = &i915_oa_stream_ops; |
2139 | 2142 | ||
@@ -2745,7 +2748,8 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv, | |||
2745 | props->ctx_handle = value; | 2748 | props->ctx_handle = value; |
2746 | break; | 2749 | break; |
2747 | case DRM_I915_PERF_PROP_SAMPLE_OA: | 2750 | case DRM_I915_PERF_PROP_SAMPLE_OA: |
2748 | props->sample_flags |= SAMPLE_OA_REPORT; | 2751 | if (value) |
2752 | props->sample_flags |= SAMPLE_OA_REPORT; | ||
2749 | break; | 2753 | break; |
2750 | case DRM_I915_PERF_PROP_OA_METRICS_SET: | 2754 | case DRM_I915_PERF_PROP_OA_METRICS_SET: |
2751 | if (value == 0) { | 2755 | if (value == 0) { |
@@ -2935,6 +2939,8 @@ void i915_perf_register(struct drm_i915_private *dev_priv) | |||
2935 | i915_perf_load_test_config_cflgt3(dev_priv); | 2939 | i915_perf_load_test_config_cflgt3(dev_priv); |
2936 | } else if (IS_CANNONLAKE(dev_priv)) { | 2940 | } else if (IS_CANNONLAKE(dev_priv)) { |
2937 | i915_perf_load_test_config_cnl(dev_priv); | 2941 | i915_perf_load_test_config_cnl(dev_priv); |
2942 | } else if (IS_ICELAKE(dev_priv)) { | ||
2943 | i915_perf_load_test_config_icl(dev_priv); | ||
2938 | } | 2944 | } |
2939 | 2945 | ||
2940 | if (dev_priv->perf.oa.test_config.id == 0) | 2946 | if (dev_priv->perf.oa.test_config.id == 0) |
@@ -3292,6 +3298,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, | |||
3292 | 3298 | ||
3293 | mutex_unlock(&dev_priv->perf.metrics_lock); | 3299 | mutex_unlock(&dev_priv->perf.metrics_lock); |
3294 | 3300 | ||
3301 | DRM_DEBUG("Added config %s id=%i\n", oa_config->uuid, oa_config->id); | ||
3302 | |||
3295 | return oa_config->id; | 3303 | return oa_config->id; |
3296 | 3304 | ||
3297 | sysfs_err: | 3305 | sysfs_err: |
@@ -3348,6 +3356,9 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, | |||
3348 | &oa_config->sysfs_metric); | 3356 | &oa_config->sysfs_metric); |
3349 | 3357 | ||
3350 | idr_remove(&dev_priv->perf.metrics_idr, *arg); | 3358 | idr_remove(&dev_priv->perf.metrics_idr, *arg); |
3359 | |||
3360 | DRM_DEBUG("Removed config %s id=%i\n", oa_config->uuid, oa_config->id); | ||
3361 | |||
3351 | put_oa_config(dev_priv, oa_config); | 3362 | put_oa_config(dev_priv, oa_config); |
3352 | 3363 | ||
3353 | config_err: | 3364 | config_err: |
@@ -3467,7 +3478,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) | |||
3467 | 3478 | ||
3468 | dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); | 3479 | dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); |
3469 | } | 3480 | } |
3470 | } else if (IS_GEN10(dev_priv)) { | 3481 | } else if (IS_GEN(dev_priv, 10, 11)) { |
3471 | dev_priv->perf.oa.ops.is_valid_b_counter_reg = | 3482 | dev_priv->perf.oa.ops.is_valid_b_counter_reg = |
3472 | gen7_is_valid_b_counter_addr; | 3483 | gen7_is_valid_b_counter_addr; |
3473 | dev_priv->perf.oa.ops.is_valid_mux_reg = | 3484 | dev_priv->perf.oa.ops.is_valid_mux_reg = |
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index f0519e31543a..dc87797db500 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c | |||
@@ -1,33 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2017 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2017-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
25 | #include <linux/perf_event.h> | ||
26 | #include <linux/pm_runtime.h> | ||
27 | |||
28 | #include "i915_drv.h" | ||
29 | #include "i915_pmu.h" | 7 | #include "i915_pmu.h" |
30 | #include "intel_ringbuffer.h" | 8 | #include "intel_ringbuffer.h" |
9 | #include "i915_drv.h" | ||
31 | 10 | ||
32 | /* Frequency for the sampling timer for events which need it. */ | 11 | /* Frequency for the sampling timer for events which need it. */ |
33 | #define FREQUENCY 200 | 12 | #define FREQUENCY 200 |
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index aa1b1a987ea1..2ba735299f7c 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h | |||
@@ -1,29 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2017 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2017-2018 Intel Corporation | ||
23 | */ | 5 | */ |
6 | |||
24 | #ifndef __I915_PMU_H__ | 7 | #ifndef __I915_PMU_H__ |
25 | #define __I915_PMU_H__ | 8 | #define __I915_PMU_H__ |
26 | 9 | ||
10 | #include <linux/hrtimer.h> | ||
11 | #include <linux/perf_event.h> | ||
12 | #include <linux/spinlock_types.h> | ||
13 | #include <drm/i915_drm.h> | ||
14 | |||
15 | struct drm_i915_private; | ||
16 | |||
27 | enum { | 17 | enum { |
28 | __I915_SAMPLE_FREQ_ACT = 0, | 18 | __I915_SAMPLE_FREQ_ACT = 0, |
29 | __I915_SAMPLE_FREQ_REQ, | 19 | __I915_SAMPLE_FREQ_REQ, |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e6a8c0ee7df1..fb106026a1f4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -153,9 +153,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
153 | #define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) | 153 | #define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) |
154 | #define _PLL(pll, a, b) ((a) + (pll)*((b)-(a))) | 154 | #define _PLL(pll, a, b) ((a) + (pll)*((b)-(a))) |
155 | #define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b)) | 155 | #define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b)) |
156 | #define _MMIO_PORT6(port, a, b, c, d, e, f) _MMIO(_PICK(port, a, b, c, d, e, f)) | ||
157 | #define _MMIO_PORT6_LN(port, ln, a0, a1, b, c, d, e, f) \ | ||
158 | _MMIO(_PICK(port, a0, b, c, d, e, f) + (ln * (a1 - a0))) | ||
159 | #define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) | 156 | #define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) |
160 | #define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c)) | 157 | #define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c)) |
161 | 158 | ||
@@ -191,6 +188,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
191 | #define OTHER_CLASS 4 | 188 | #define OTHER_CLASS 4 |
192 | #define MAX_ENGINE_CLASS 4 | 189 | #define MAX_ENGINE_CLASS 4 |
193 | 190 | ||
191 | #define OTHER_GTPM_INSTANCE 1 | ||
194 | #define MAX_ENGINE_INSTANCE 3 | 192 | #define MAX_ENGINE_INSTANCE 3 |
195 | 193 | ||
196 | /* PCI config space */ | 194 | /* PCI config space */ |
@@ -304,6 +302,17 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
304 | #define GEN6_GRDOM_VECS (1 << 4) | 302 | #define GEN6_GRDOM_VECS (1 << 4) |
305 | #define GEN9_GRDOM_GUC (1 << 5) | 303 | #define GEN9_GRDOM_GUC (1 << 5) |
306 | #define GEN8_GRDOM_MEDIA2 (1 << 7) | 304 | #define GEN8_GRDOM_MEDIA2 (1 << 7) |
305 | /* GEN11 changed all bit defs except for FULL & RENDER */ | ||
306 | #define GEN11_GRDOM_FULL GEN6_GRDOM_FULL | ||
307 | #define GEN11_GRDOM_RENDER GEN6_GRDOM_RENDER | ||
308 | #define GEN11_GRDOM_BLT (1 << 2) | ||
309 | #define GEN11_GRDOM_GUC (1 << 3) | ||
310 | #define GEN11_GRDOM_MEDIA (1 << 5) | ||
311 | #define GEN11_GRDOM_MEDIA2 (1 << 6) | ||
312 | #define GEN11_GRDOM_MEDIA3 (1 << 7) | ||
313 | #define GEN11_GRDOM_MEDIA4 (1 << 8) | ||
314 | #define GEN11_GRDOM_VECS (1 << 13) | ||
315 | #define GEN11_GRDOM_VECS2 (1 << 14) | ||
307 | 316 | ||
308 | #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base+0x228) | 317 | #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base+0x228) |
309 | #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base+0x518) | 318 | #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base+0x518) |
@@ -430,145 +439,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
430 | #define VGA_CR_INDEX_CGA 0x3d4 | 439 | #define VGA_CR_INDEX_CGA 0x3d4 |
431 | #define VGA_CR_DATA_CGA 0x3d5 | 440 | #define VGA_CR_DATA_CGA 0x3d5 |
432 | 441 | ||
433 | /* | ||
434 | * Instruction field definitions used by the command parser | ||
435 | */ | ||
436 | #define INSTR_CLIENT_SHIFT 29 | ||
437 | #define INSTR_MI_CLIENT 0x0 | ||
438 | #define INSTR_BC_CLIENT 0x2 | ||
439 | #define INSTR_RC_CLIENT 0x3 | ||
440 | #define INSTR_SUBCLIENT_SHIFT 27 | ||
441 | #define INSTR_SUBCLIENT_MASK 0x18000000 | ||
442 | #define INSTR_MEDIA_SUBCLIENT 0x2 | ||
443 | #define INSTR_26_TO_24_MASK 0x7000000 | ||
444 | #define INSTR_26_TO_24_SHIFT 24 | ||
445 | |||
446 | /* | ||
447 | * Memory interface instructions used by the kernel | ||
448 | */ | ||
449 | #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags)) | ||
450 | /* Many MI commands use bit 22 of the header dword for GGTT vs PPGTT */ | ||
451 | #define MI_GLOBAL_GTT (1<<22) | ||
452 | |||
453 | #define MI_NOOP MI_INSTR(0, 0) | ||
454 | #define MI_USER_INTERRUPT MI_INSTR(0x02, 0) | ||
455 | #define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) | ||
456 | #define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) | ||
457 | #define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) | ||
458 | #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) | ||
459 | #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) | ||
460 | #define MI_FLUSH MI_INSTR(0x04, 0) | ||
461 | #define MI_READ_FLUSH (1 << 0) | ||
462 | #define MI_EXE_FLUSH (1 << 1) | ||
463 | #define MI_NO_WRITE_FLUSH (1 << 2) | ||
464 | #define MI_SCENE_COUNT (1 << 3) /* just increment scene count */ | ||
465 | #define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ | ||
466 | #define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */ | ||
467 | #define MI_REPORT_HEAD MI_INSTR(0x07, 0) | ||
468 | #define MI_ARB_ON_OFF MI_INSTR(0x08, 0) | ||
469 | #define MI_ARB_ENABLE (1<<0) | ||
470 | #define MI_ARB_DISABLE (0<<0) | ||
471 | #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) | ||
472 | #define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) | ||
473 | #define MI_SUSPEND_FLUSH_EN (1<<0) | ||
474 | #define MI_SET_APPID MI_INSTR(0x0e, 0) | ||
475 | #define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) | ||
476 | #define MI_OVERLAY_CONTINUE (0x0<<21) | ||
477 | #define MI_OVERLAY_ON (0x1<<21) | ||
478 | #define MI_OVERLAY_OFF (0x2<<21) | ||
479 | #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) | ||
480 | #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) | ||
481 | #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) | ||
482 | #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) | ||
483 | /* IVB has funny definitions for which plane to flip. */ | ||
484 | #define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) | ||
485 | #define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) | ||
486 | #define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) | ||
487 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) | ||
488 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) | ||
489 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) | ||
490 | /* SKL ones */ | ||
491 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_A (0 << 8) | ||
492 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_B (1 << 8) | ||
493 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_C (2 << 8) | ||
494 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_A (4 << 8) | ||
495 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_B (5 << 8) | ||
496 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_C (6 << 8) | ||
497 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_A (7 << 8) | ||
498 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_B (8 << 8) | ||
499 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_C (9 << 8) | ||
500 | #define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6, gen7 */ | ||
501 | #define MI_SEMAPHORE_GLOBAL_GTT (1<<22) | ||
502 | #define MI_SEMAPHORE_UPDATE (1<<21) | ||
503 | #define MI_SEMAPHORE_COMPARE (1<<20) | ||
504 | #define MI_SEMAPHORE_REGISTER (1<<18) | ||
505 | #define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ | ||
506 | #define MI_SEMAPHORE_SYNC_VER (1<<16) /* RCS wait for VECS (RVESYNC) */ | ||
507 | #define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ | ||
508 | #define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ | ||
509 | #define MI_SEMAPHORE_SYNC_VEV (1<<16) /* VCS wait for VECS (VVESYNC) */ | ||
510 | #define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ | ||
511 | #define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ | ||
512 | #define MI_SEMAPHORE_SYNC_VEB (1<<16) /* BCS wait for VECS (BVESYNC) */ | ||
513 | #define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ | ||
514 | #define MI_SEMAPHORE_SYNC_BVE (0<<16) /* VECS wait for BCS (VEBSYNC) */ | ||
515 | #define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ | ||
516 | #define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ | ||
517 | #define MI_SEMAPHORE_SYNC_INVALID (3<<16) | ||
518 | #define MI_SEMAPHORE_SYNC_MASK (3<<16) | ||
519 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) | ||
520 | #define MI_MM_SPACE_GTT (1<<8) | ||
521 | #define MI_MM_SPACE_PHYSICAL (0<<8) | ||
522 | #define MI_SAVE_EXT_STATE_EN (1<<3) | ||
523 | #define MI_RESTORE_EXT_STATE_EN (1<<2) | ||
524 | #define MI_FORCE_RESTORE (1<<1) | ||
525 | #define MI_RESTORE_INHIBIT (1<<0) | ||
526 | #define HSW_MI_RS_SAVE_STATE_EN (1<<3) | ||
527 | #define HSW_MI_RS_RESTORE_STATE_EN (1<<2) | ||
528 | #define MI_SEMAPHORE_SIGNAL MI_INSTR(0x1b, 0) /* GEN8+ */ | ||
529 | #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) | ||
530 | #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ | ||
531 | #define MI_SEMAPHORE_POLL (1<<15) | ||
532 | #define MI_SEMAPHORE_SAD_GTE_SDD (1<<12) | ||
533 | #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) | ||
534 | #define MI_STORE_DWORD_IMM_GEN4 MI_INSTR(0x20, 2) | ||
535 | #define MI_MEM_VIRTUAL (1 << 22) /* 945,g33,965 */ | ||
536 | #define MI_USE_GGTT (1 << 22) /* g4x+ */ | ||
537 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) | ||
538 | #define MI_STORE_DWORD_INDEX_SHIFT 2 | ||
539 | /* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: | ||
540 | * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw | ||
541 | * simply ignores the register load under certain conditions. | ||
542 | * - One can actually load arbitrary many arbitrary registers: Simply issue x | ||
543 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! | ||
544 | */ | ||
545 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*(x)-1) | ||
546 | #define MI_LRI_FORCE_POSTED (1<<12) | ||
547 | #define MI_STORE_REGISTER_MEM MI_INSTR(0x24, 1) | ||
548 | #define MI_STORE_REGISTER_MEM_GEN8 MI_INSTR(0x24, 2) | ||
549 | #define MI_SRM_LRM_GLOBAL_GTT (1<<22) | ||
550 | #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ | ||
551 | #define MI_FLUSH_DW_STORE_INDEX (1<<21) | ||
552 | #define MI_INVALIDATE_TLB (1<<18) | ||
553 | #define MI_FLUSH_DW_OP_STOREDW (1<<14) | ||
554 | #define MI_FLUSH_DW_OP_MASK (3<<14) | ||
555 | #define MI_FLUSH_DW_NOTIFY (1<<8) | ||
556 | #define MI_INVALIDATE_BSD (1<<7) | ||
557 | #define MI_FLUSH_DW_USE_GTT (1<<2) | ||
558 | #define MI_FLUSH_DW_USE_PPGTT (0<<2) | ||
559 | #define MI_LOAD_REGISTER_MEM MI_INSTR(0x29, 1) | ||
560 | #define MI_LOAD_REGISTER_MEM_GEN8 MI_INSTR(0x29, 2) | ||
561 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) | ||
562 | #define MI_BATCH_NON_SECURE (1) | ||
563 | /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */ | ||
564 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | ||
565 | #define MI_BATCH_PPGTT_HSW (1<<8) | ||
566 | #define MI_BATCH_NON_SECURE_HSW (1<<13) | ||
567 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) | ||
568 | #define MI_BATCH_GTT (2<<6) /* aliased with (1<<7) on gen4 */ | ||
569 | #define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1) | ||
570 | #define MI_BATCH_RESOURCE_STREAMER (1<<10) | ||
571 | |||
572 | #define MI_PREDICATE_SRC0 _MMIO(0x2400) | 442 | #define MI_PREDICATE_SRC0 _MMIO(0x2400) |
573 | #define MI_PREDICATE_SRC0_UDW _MMIO(0x2400 + 4) | 443 | #define MI_PREDICATE_SRC0_UDW _MMIO(0x2400 + 4) |
574 | #define MI_PREDICATE_SRC1 _MMIO(0x2408) | 444 | #define MI_PREDICATE_SRC1 _MMIO(0x2408) |
@@ -579,130 +449,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
579 | #define LOWER_SLICE_DISABLED (0<<0) | 449 | #define LOWER_SLICE_DISABLED (0<<0) |
580 | 450 | ||
581 | /* | 451 | /* |
582 | * 3D instructions used by the kernel | ||
583 | */ | ||
584 | #define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags)) | ||
585 | |||
586 | #define GEN9_MEDIA_POOL_STATE ((0x3 << 29) | (0x2 << 27) | (0x5 << 16) | 4) | ||
587 | #define GEN9_MEDIA_POOL_ENABLE (1 << 31) | ||
588 | #define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24)) | ||
589 | #define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
590 | #define SC_UPDATE_SCISSOR (0x1<<1) | ||
591 | #define SC_ENABLE_MASK (0x1<<0) | ||
592 | #define SC_ENABLE (0x1<<0) | ||
593 | #define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16)) | ||
594 | #define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) | ||
595 | #define SCI_YMIN_MASK (0xffff<<16) | ||
596 | #define SCI_XMIN_MASK (0xffff<<0) | ||
597 | #define SCI_YMAX_MASK (0xffff<<16) | ||
598 | #define SCI_XMAX_MASK (0xffff<<0) | ||
599 | #define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
600 | #define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) | ||
601 | #define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) | ||
602 | #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) | ||
603 | #define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) | ||
604 | #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) | ||
605 | #define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) | ||
606 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) | ||
607 | #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) | ||
608 | |||
609 | #define COLOR_BLT_CMD (2<<29 | 0x40<<22 | (5-2)) | ||
610 | #define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) | ||
611 | #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) | ||
612 | #define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) | ||
613 | #define BLT_WRITE_A (2<<20) | ||
614 | #define BLT_WRITE_RGB (1<<20) | ||
615 | #define BLT_WRITE_RGBA (BLT_WRITE_RGB | BLT_WRITE_A) | ||
616 | #define BLT_DEPTH_8 (0<<24) | ||
617 | #define BLT_DEPTH_16_565 (1<<24) | ||
618 | #define BLT_DEPTH_16_1555 (2<<24) | ||
619 | #define BLT_DEPTH_32 (3<<24) | ||
620 | #define BLT_ROP_SRC_COPY (0xcc<<16) | ||
621 | #define BLT_ROP_COLOR_COPY (0xf0<<16) | ||
622 | #define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */ | ||
623 | #define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */ | ||
624 | #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) | ||
625 | #define ASYNC_FLIP (1<<22) | ||
626 | #define DISPLAY_PLANE_A (0<<20) | ||
627 | #define DISPLAY_PLANE_B (1<<20) | ||
628 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2)) | ||
629 | #define PIPE_CONTROL_FLUSH_L3 (1<<27) | ||
630 | #define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */ | ||
631 | #define PIPE_CONTROL_MMIO_WRITE (1<<23) | ||
632 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) | ||
633 | #define PIPE_CONTROL_CS_STALL (1<<20) | ||
634 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | ||
635 | #define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) | ||
636 | #define PIPE_CONTROL_QW_WRITE (1<<14) | ||
637 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | ||
638 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | ||
639 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) | ||
640 | #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ | ||
641 | #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */ | ||
642 | #define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */ | ||
643 | #define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9) | ||
644 | #define PIPE_CONTROL_NOTIFY (1<<8) | ||
645 | #define PIPE_CONTROL_FLUSH_ENABLE (1<<7) /* gen7+ */ | ||
646 | #define PIPE_CONTROL_DC_FLUSH_ENABLE (1<<5) | ||
647 | #define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4) | ||
648 | #define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3) | ||
649 | #define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2) | ||
650 | #define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1) | ||
651 | #define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0) | ||
652 | #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ | ||
653 | |||
654 | /* | ||
655 | * Commands used only by the command parser | ||
656 | */ | ||
657 | #define MI_SET_PREDICATE MI_INSTR(0x01, 0) | ||
658 | #define MI_ARB_CHECK MI_INSTR(0x05, 0) | ||
659 | #define MI_RS_CONTROL MI_INSTR(0x06, 0) | ||
660 | #define MI_URB_ATOMIC_ALLOC MI_INSTR(0x09, 0) | ||
661 | #define MI_PREDICATE MI_INSTR(0x0C, 0) | ||
662 | #define MI_RS_CONTEXT MI_INSTR(0x0F, 0) | ||
663 | #define MI_TOPOLOGY_FILTER MI_INSTR(0x0D, 0) | ||
664 | #define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0) | ||
665 | #define MI_URB_CLEAR MI_INSTR(0x19, 0) | ||
666 | #define MI_UPDATE_GTT MI_INSTR(0x23, 0) | ||
667 | #define MI_CLFLUSH MI_INSTR(0x27, 0) | ||
668 | #define MI_REPORT_PERF_COUNT MI_INSTR(0x28, 0) | ||
669 | #define MI_REPORT_PERF_COUNT_GGTT (1<<0) | ||
670 | #define MI_LOAD_REGISTER_REG MI_INSTR(0x2A, 0) | ||
671 | #define MI_RS_STORE_DATA_IMM MI_INSTR(0x2B, 0) | ||
672 | #define MI_LOAD_URB_MEM MI_INSTR(0x2C, 0) | ||
673 | #define MI_STORE_URB_MEM MI_INSTR(0x2D, 0) | ||
674 | #define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0) | ||
675 | |||
676 | #define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16)) | ||
677 | #define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16)) | ||
678 | #define MEDIA_VFE_STATE ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16)) | ||
679 | #define MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18) | ||
680 | #define GPGPU_OBJECT ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16)) | ||
681 | #define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16)) | ||
682 | #define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \ | ||
683 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16)) | ||
684 | #define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \ | ||
685 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16)) | ||
686 | #define GFX_OP_3DSTATE_SO_DECL_LIST \ | ||
687 | ((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16)) | ||
688 | |||
689 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \ | ||
690 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16)) | ||
691 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \ | ||
692 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16)) | ||
693 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \ | ||
694 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16)) | ||
695 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \ | ||
696 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16)) | ||
697 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \ | ||
698 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16)) | ||
699 | |||
700 | #define MFX_WAIT ((0x3<<29)|(0x1<<27)|(0x0<<16)) | ||
701 | |||
702 | #define COLOR_BLT ((0x2<<29)|(0x40<<22)) | ||
703 | #define SRC_COPY_BLT ((0x2<<29)|(0x43<<22)) | ||
704 | |||
705 | /* | ||
706 | * Registers used only by the command parser | 452 | * Registers used only by the command parser |
707 | */ | 453 | */ |
708 | #define BCS_SWCTRL _MMIO(0x22200) | 454 | #define BCS_SWCTRL _MMIO(0x22200) |
@@ -802,6 +548,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
802 | 548 | ||
803 | #define GEN8_OABUFFER_UDW _MMIO(0x23b4) | 549 | #define GEN8_OABUFFER_UDW _MMIO(0x23b4) |
804 | #define GEN8_OABUFFER _MMIO(0x2b14) | 550 | #define GEN8_OABUFFER _MMIO(0x2b14) |
551 | #define GEN8_OABUFFER_MEM_SELECT_GGTT (1 << 0) /* 0: PPGTT, 1: GGTT */ | ||
805 | 552 | ||
806 | #define GEN7_OASTATUS1 _MMIO(0x2364) | 553 | #define GEN7_OASTATUS1 _MMIO(0x2364) |
807 | #define GEN7_OASTATUS1_TAIL_MASK 0xffffffc0 | 554 | #define GEN7_OASTATUS1_TAIL_MASK 0xffffffc0 |
@@ -810,7 +557,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
810 | #define GEN7_OASTATUS1_REPORT_LOST (1<<0) | 557 | #define GEN7_OASTATUS1_REPORT_LOST (1<<0) |
811 | 558 | ||
812 | #define GEN7_OASTATUS2 _MMIO(0x2368) | 559 | #define GEN7_OASTATUS2 _MMIO(0x2368) |
813 | #define GEN7_OASTATUS2_HEAD_MASK 0xffffffc0 | 560 | #define GEN7_OASTATUS2_HEAD_MASK 0xffffffc0 |
561 | #define GEN7_OASTATUS2_MEM_SELECT_GGTT (1 << 0) /* 0: PPGTT, 1: GGTT */ | ||
814 | 562 | ||
815 | #define GEN8_OASTATUS _MMIO(0x2b08) | 563 | #define GEN8_OASTATUS _MMIO(0x2b08) |
816 | #define GEN8_OASTATUS_OVERRUN_STATUS (1<<3) | 564 | #define GEN8_OASTATUS_OVERRUN_STATUS (1<<3) |
@@ -832,8 +580,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
832 | #define OABUFFER_SIZE_8M (6<<3) | 580 | #define OABUFFER_SIZE_8M (6<<3) |
833 | #define OABUFFER_SIZE_16M (7<<3) | 581 | #define OABUFFER_SIZE_16M (7<<3) |
834 | 582 | ||
835 | #define OA_MEM_SELECT_GGTT (1<<0) | ||
836 | |||
837 | /* | 583 | /* |
838 | * Flexible, Aggregate EU Counter Registers. | 584 | * Flexible, Aggregate EU Counter Registers. |
839 | * Note: these aren't contiguous | 585 | * Note: these aren't contiguous |
@@ -1127,6 +873,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
1127 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK (1 << GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT) | 873 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK (1 << GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT) |
1128 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ 0 | 874 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ 0 |
1129 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ 1 | 875 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ 1 |
876 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT 3 | ||
877 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK (0x7 << GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT) | ||
878 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ 0 | ||
879 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ 1 | ||
880 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ 2 | ||
881 | #define GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ 3 | ||
1130 | #define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT 1 | 882 | #define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT 1 |
1131 | #define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK (0x3 << GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT) | 883 | #define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK (0x3 << GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT) |
1132 | 884 | ||
@@ -1948,79 +1700,100 @@ enum i915_power_well_id { | |||
1948 | #define _CNL_PORT_PCS_DW1_LN0_C 0x162C04 | 1700 | #define _CNL_PORT_PCS_DW1_LN0_C 0x162C04 |
1949 | #define _CNL_PORT_PCS_DW1_LN0_D 0x162E04 | 1701 | #define _CNL_PORT_PCS_DW1_LN0_D 0x162E04 |
1950 | #define _CNL_PORT_PCS_DW1_LN0_F 0x162804 | 1702 | #define _CNL_PORT_PCS_DW1_LN0_F 0x162804 |
1951 | #define CNL_PORT_PCS_DW1_GRP(port) _MMIO_PORT6(port, \ | 1703 | #define CNL_PORT_PCS_DW1_GRP(port) _MMIO(_PICK(port, \ |
1952 | _CNL_PORT_PCS_DW1_GRP_AE, \ | 1704 | _CNL_PORT_PCS_DW1_GRP_AE, \ |
1953 | _CNL_PORT_PCS_DW1_GRP_B, \ | 1705 | _CNL_PORT_PCS_DW1_GRP_B, \ |
1954 | _CNL_PORT_PCS_DW1_GRP_C, \ | 1706 | _CNL_PORT_PCS_DW1_GRP_C, \ |
1955 | _CNL_PORT_PCS_DW1_GRP_D, \ | 1707 | _CNL_PORT_PCS_DW1_GRP_D, \ |
1956 | _CNL_PORT_PCS_DW1_GRP_AE, \ | 1708 | _CNL_PORT_PCS_DW1_GRP_AE, \ |
1957 | _CNL_PORT_PCS_DW1_GRP_F) | 1709 | _CNL_PORT_PCS_DW1_GRP_F)) |
1958 | #define CNL_PORT_PCS_DW1_LN0(port) _MMIO_PORT6(port, \ | 1710 | |
1711 | #define CNL_PORT_PCS_DW1_LN0(port) _MMIO(_PICK(port, \ | ||
1959 | _CNL_PORT_PCS_DW1_LN0_AE, \ | 1712 | _CNL_PORT_PCS_DW1_LN0_AE, \ |
1960 | _CNL_PORT_PCS_DW1_LN0_B, \ | 1713 | _CNL_PORT_PCS_DW1_LN0_B, \ |
1961 | _CNL_PORT_PCS_DW1_LN0_C, \ | 1714 | _CNL_PORT_PCS_DW1_LN0_C, \ |
1962 | _CNL_PORT_PCS_DW1_LN0_D, \ | 1715 | _CNL_PORT_PCS_DW1_LN0_D, \ |
1963 | _CNL_PORT_PCS_DW1_LN0_AE, \ | 1716 | _CNL_PORT_PCS_DW1_LN0_AE, \ |
1964 | _CNL_PORT_PCS_DW1_LN0_F) | 1717 | _CNL_PORT_PCS_DW1_LN0_F)) |
1718 | #define _ICL_PORT_PCS_DW1_GRP_A 0x162604 | ||
1719 | #define _ICL_PORT_PCS_DW1_GRP_B 0x6C604 | ||
1720 | #define _ICL_PORT_PCS_DW1_LN0_A 0x162804 | ||
1721 | #define _ICL_PORT_PCS_DW1_LN0_B 0x6C804 | ||
1722 | #define ICL_PORT_PCS_DW1_GRP(port) _MMIO_PORT(port,\ | ||
1723 | _ICL_PORT_PCS_DW1_GRP_A, \ | ||
1724 | _ICL_PORT_PCS_DW1_GRP_B) | ||
1725 | #define ICL_PORT_PCS_DW1_LN0(port) _MMIO_PORT(port, \ | ||
1726 | _ICL_PORT_PCS_DW1_LN0_A, \ | ||
1727 | _ICL_PORT_PCS_DW1_LN0_B) | ||
1965 | #define COMMON_KEEPER_EN (1 << 26) | 1728 | #define COMMON_KEEPER_EN (1 << 26) |
1966 | 1729 | ||
1967 | #define _CNL_PORT_TX_DW2_GRP_AE 0x162348 | 1730 | /* CNL Port TX registers */ |
1968 | #define _CNL_PORT_TX_DW2_GRP_B 0x1623C8 | 1731 | #define _CNL_PORT_TX_AE_GRP_OFFSET 0x162340 |
1969 | #define _CNL_PORT_TX_DW2_GRP_C 0x162B48 | 1732 | #define _CNL_PORT_TX_B_GRP_OFFSET 0x1623C0 |
1970 | #define _CNL_PORT_TX_DW2_GRP_D 0x162BC8 | 1733 | #define _CNL_PORT_TX_C_GRP_OFFSET 0x162B40 |
1971 | #define _CNL_PORT_TX_DW2_GRP_F 0x162A48 | 1734 | #define _CNL_PORT_TX_D_GRP_OFFSET 0x162BC0 |
1972 | #define _CNL_PORT_TX_DW2_LN0_AE 0x162448 | 1735 | #define _CNL_PORT_TX_F_GRP_OFFSET 0x162A40 |
1973 | #define _CNL_PORT_TX_DW2_LN0_B 0x162648 | 1736 | #define _CNL_PORT_TX_AE_LN0_OFFSET 0x162440 |
1974 | #define _CNL_PORT_TX_DW2_LN0_C 0x162C48 | 1737 | #define _CNL_PORT_TX_B_LN0_OFFSET 0x162640 |
1975 | #define _CNL_PORT_TX_DW2_LN0_D 0x162E48 | 1738 | #define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40 |
1976 | #define _CNL_PORT_TX_DW2_LN0_F 0x162848 | 1739 | #define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40 |
1977 | #define CNL_PORT_TX_DW2_GRP(port) _MMIO_PORT6(port, \ | 1740 | #define _CNL_PORT_TX_F_LN0_OFFSET 0x162840 |
1978 | _CNL_PORT_TX_DW2_GRP_AE, \ | 1741 | #define _CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \ |
1979 | _CNL_PORT_TX_DW2_GRP_B, \ | 1742 | _CNL_PORT_TX_AE_GRP_OFFSET, \ |
1980 | _CNL_PORT_TX_DW2_GRP_C, \ | 1743 | _CNL_PORT_TX_B_GRP_OFFSET, \ |
1981 | _CNL_PORT_TX_DW2_GRP_D, \ | 1744 | _CNL_PORT_TX_B_GRP_OFFSET, \ |
1982 | _CNL_PORT_TX_DW2_GRP_AE, \ | 1745 | _CNL_PORT_TX_D_GRP_OFFSET, \ |
1983 | _CNL_PORT_TX_DW2_GRP_F) | 1746 | _CNL_PORT_TX_AE_GRP_OFFSET, \ |
1984 | #define CNL_PORT_TX_DW2_LN0(port) _MMIO_PORT6(port, \ | 1747 | _CNL_PORT_TX_F_GRP_OFFSET) + \ |
1985 | _CNL_PORT_TX_DW2_LN0_AE, \ | 1748 | 4*(dw)) |
1986 | _CNL_PORT_TX_DW2_LN0_B, \ | 1749 | #define _CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \ |
1987 | _CNL_PORT_TX_DW2_LN0_C, \ | 1750 | _CNL_PORT_TX_AE_LN0_OFFSET, \ |
1988 | _CNL_PORT_TX_DW2_LN0_D, \ | 1751 | _CNL_PORT_TX_B_LN0_OFFSET, \ |
1989 | _CNL_PORT_TX_DW2_LN0_AE, \ | 1752 | _CNL_PORT_TX_B_LN0_OFFSET, \ |
1990 | _CNL_PORT_TX_DW2_LN0_F) | 1753 | _CNL_PORT_TX_D_LN0_OFFSET, \ |
1991 | #define SWING_SEL_UPPER(x) ((x >> 3) << 15) | 1754 | _CNL_PORT_TX_AE_LN0_OFFSET, \ |
1755 | _CNL_PORT_TX_F_LN0_OFFSET) + \ | ||
1756 | 4*(dw)) | ||
1757 | |||
1758 | #define CNL_PORT_TX_DW2_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 2)) | ||
1759 | #define CNL_PORT_TX_DW2_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 2)) | ||
1760 | #define _ICL_PORT_TX_DW2_GRP_A 0x162688 | ||
1761 | #define _ICL_PORT_TX_DW2_GRP_B 0x6C688 | ||
1762 | #define _ICL_PORT_TX_DW2_LN0_A 0x162888 | ||
1763 | #define _ICL_PORT_TX_DW2_LN0_B 0x6C888 | ||
1764 | #define ICL_PORT_TX_DW2_GRP(port) _MMIO_PORT(port, \ | ||
1765 | _ICL_PORT_TX_DW2_GRP_A, \ | ||
1766 | _ICL_PORT_TX_DW2_GRP_B) | ||
1767 | #define ICL_PORT_TX_DW2_LN0(port) _MMIO_PORT(port, \ | ||
1768 | _ICL_PORT_TX_DW2_LN0_A, \ | ||
1769 | _ICL_PORT_TX_DW2_LN0_B) | ||
1770 | #define SWING_SEL_UPPER(x) (((x) >> 3) << 15) | ||
1992 | #define SWING_SEL_UPPER_MASK (1 << 15) | 1771 | #define SWING_SEL_UPPER_MASK (1 << 15) |
1993 | #define SWING_SEL_LOWER(x) ((x & 0x7) << 11) | 1772 | #define SWING_SEL_LOWER(x) (((x) & 0x7) << 11) |
1994 | #define SWING_SEL_LOWER_MASK (0x7 << 11) | 1773 | #define SWING_SEL_LOWER_MASK (0x7 << 11) |
1995 | #define RCOMP_SCALAR(x) ((x) << 0) | 1774 | #define RCOMP_SCALAR(x) ((x) << 0) |
1996 | #define RCOMP_SCALAR_MASK (0xFF << 0) | 1775 | #define RCOMP_SCALAR_MASK (0xFF << 0) |
1997 | 1776 | ||
1998 | #define _CNL_PORT_TX_DW4_GRP_AE 0x162350 | ||
1999 | #define _CNL_PORT_TX_DW4_GRP_B 0x1623D0 | ||
2000 | #define _CNL_PORT_TX_DW4_GRP_C 0x162B50 | ||
2001 | #define _CNL_PORT_TX_DW4_GRP_D 0x162BD0 | ||
2002 | #define _CNL_PORT_TX_DW4_GRP_F 0x162A50 | ||
2003 | #define _CNL_PORT_TX_DW4_LN0_AE 0x162450 | 1777 | #define _CNL_PORT_TX_DW4_LN0_AE 0x162450 |
2004 | #define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0 | 1778 | #define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0 |
2005 | #define _CNL_PORT_TX_DW4_LN0_B 0x162650 | 1779 | #define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 4)) |
2006 | #define _CNL_PORT_TX_DW4_LN0_C 0x162C50 | 1780 | #define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4)) |
2007 | #define _CNL_PORT_TX_DW4_LN0_D 0x162E50 | 1781 | #define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \ |
2008 | #define _CNL_PORT_TX_DW4_LN0_F 0x162850 | 1782 | (ln * (_CNL_PORT_TX_DW4_LN1_AE - \ |
2009 | #define CNL_PORT_TX_DW4_GRP(port) _MMIO_PORT6(port, \ | 1783 | _CNL_PORT_TX_DW4_LN0_AE))) |
2010 | _CNL_PORT_TX_DW4_GRP_AE, \ | 1784 | #define _ICL_PORT_TX_DW4_GRP_A 0x162690 |
2011 | _CNL_PORT_TX_DW4_GRP_B, \ | 1785 | #define _ICL_PORT_TX_DW4_GRP_B 0x6C690 |
2012 | _CNL_PORT_TX_DW4_GRP_C, \ | 1786 | #define _ICL_PORT_TX_DW4_LN0_A 0x162890 |
2013 | _CNL_PORT_TX_DW4_GRP_D, \ | 1787 | #define _ICL_PORT_TX_DW4_LN1_A 0x162990 |
2014 | _CNL_PORT_TX_DW4_GRP_AE, \ | 1788 | #define _ICL_PORT_TX_DW4_LN0_B 0x6C890 |
2015 | _CNL_PORT_TX_DW4_GRP_F) | 1789 | #define ICL_PORT_TX_DW4_GRP(port) _MMIO_PORT(port, \ |
2016 | #define CNL_PORT_TX_DW4_LN(port, ln) _MMIO_PORT6_LN(port, ln, \ | 1790 | _ICL_PORT_TX_DW4_GRP_A, \ |
2017 | _CNL_PORT_TX_DW4_LN0_AE, \ | 1791 | _ICL_PORT_TX_DW4_GRP_B) |
2018 | _CNL_PORT_TX_DW4_LN1_AE, \ | 1792 | #define ICL_PORT_TX_DW4_LN(port, ln) _MMIO(_PORT(port, \ |
2019 | _CNL_PORT_TX_DW4_LN0_B, \ | 1793 | _ICL_PORT_TX_DW4_LN0_A, \ |
2020 | _CNL_PORT_TX_DW4_LN0_C, \ | 1794 | _ICL_PORT_TX_DW4_LN0_B) + \ |
2021 | _CNL_PORT_TX_DW4_LN0_D, \ | 1795 | (ln * (_ICL_PORT_TX_DW4_LN1_A - \ |
2022 | _CNL_PORT_TX_DW4_LN0_AE, \ | 1796 | _ICL_PORT_TX_DW4_LN0_A))) |
2023 | _CNL_PORT_TX_DW4_LN0_F) | ||
2024 | #define LOADGEN_SELECT (1 << 31) | 1797 | #define LOADGEN_SELECT (1 << 31) |
2025 | #define POST_CURSOR_1(x) ((x) << 12) | 1798 | #define POST_CURSOR_1(x) ((x) << 12) |
2026 | #define POST_CURSOR_1_MASK (0x3F << 12) | 1799 | #define POST_CURSOR_1_MASK (0x3F << 12) |
@@ -2029,64 +1802,147 @@ enum i915_power_well_id { | |||
2029 | #define CURSOR_COEFF(x) ((x) << 0) | 1802 | #define CURSOR_COEFF(x) ((x) << 0) |
2030 | #define CURSOR_COEFF_MASK (0x3F << 0) | 1803 | #define CURSOR_COEFF_MASK (0x3F << 0) |
2031 | 1804 | ||
2032 | #define _CNL_PORT_TX_DW5_GRP_AE 0x162354 | 1805 | #define CNL_PORT_TX_DW5_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 5)) |
2033 | #define _CNL_PORT_TX_DW5_GRP_B 0x1623D4 | 1806 | #define CNL_PORT_TX_DW5_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 5)) |
2034 | #define _CNL_PORT_TX_DW5_GRP_C 0x162B54 | 1807 | #define _ICL_PORT_TX_DW5_GRP_A 0x162694 |
2035 | #define _CNL_PORT_TX_DW5_GRP_D 0x162BD4 | 1808 | #define _ICL_PORT_TX_DW5_GRP_B 0x6C694 |
2036 | #define _CNL_PORT_TX_DW5_GRP_F 0x162A54 | 1809 | #define _ICL_PORT_TX_DW5_LN0_A 0x162894 |
2037 | #define _CNL_PORT_TX_DW5_LN0_AE 0x162454 | 1810 | #define _ICL_PORT_TX_DW5_LN0_B 0x6C894 |
2038 | #define _CNL_PORT_TX_DW5_LN0_B 0x162654 | 1811 | #define ICL_PORT_TX_DW5_GRP(port) _MMIO_PORT(port, \ |
2039 | #define _CNL_PORT_TX_DW5_LN0_C 0x162C54 | 1812 | _ICL_PORT_TX_DW5_GRP_A, \ |
2040 | #define _CNL_PORT_TX_DW5_LN0_D 0x162E54 | 1813 | _ICL_PORT_TX_DW5_GRP_B) |
2041 | #define _CNL_PORT_TX_DW5_LN0_F 0x162854 | 1814 | #define ICL_PORT_TX_DW5_LN0(port) _MMIO_PORT(port, \ |
2042 | #define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \ | 1815 | _ICL_PORT_TX_DW5_LN0_A, \ |
2043 | _CNL_PORT_TX_DW5_GRP_AE, \ | 1816 | _ICL_PORT_TX_DW5_LN0_B) |
2044 | _CNL_PORT_TX_DW5_GRP_B, \ | ||
2045 | _CNL_PORT_TX_DW5_GRP_C, \ | ||
2046 | _CNL_PORT_TX_DW5_GRP_D, \ | ||
2047 | _CNL_PORT_TX_DW5_GRP_AE, \ | ||
2048 | _CNL_PORT_TX_DW5_GRP_F) | ||
2049 | #define CNL_PORT_TX_DW5_LN0(port) _MMIO_PORT6(port, \ | ||
2050 | _CNL_PORT_TX_DW5_LN0_AE, \ | ||
2051 | _CNL_PORT_TX_DW5_LN0_B, \ | ||
2052 | _CNL_PORT_TX_DW5_LN0_C, \ | ||
2053 | _CNL_PORT_TX_DW5_LN0_D, \ | ||
2054 | _CNL_PORT_TX_DW5_LN0_AE, \ | ||
2055 | _CNL_PORT_TX_DW5_LN0_F) | ||
2056 | #define TX_TRAINING_EN (1 << 31) | 1817 | #define TX_TRAINING_EN (1 << 31) |
1818 | #define TAP2_DISABLE (1 << 30) | ||
2057 | #define TAP3_DISABLE (1 << 29) | 1819 | #define TAP3_DISABLE (1 << 29) |
2058 | #define SCALING_MODE_SEL(x) ((x) << 18) | 1820 | #define SCALING_MODE_SEL(x) ((x) << 18) |
2059 | #define SCALING_MODE_SEL_MASK (0x7 << 18) | 1821 | #define SCALING_MODE_SEL_MASK (0x7 << 18) |
2060 | #define RTERM_SELECT(x) ((x) << 3) | 1822 | #define RTERM_SELECT(x) ((x) << 3) |
2061 | #define RTERM_SELECT_MASK (0x7 << 3) | 1823 | #define RTERM_SELECT_MASK (0x7 << 3) |
2062 | 1824 | ||
2063 | #define _CNL_PORT_TX_DW7_GRP_AE 0x16235C | 1825 | #define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 7)) |
2064 | #define _CNL_PORT_TX_DW7_GRP_B 0x1623DC | 1826 | #define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 7)) |
2065 | #define _CNL_PORT_TX_DW7_GRP_C 0x162B5C | ||
2066 | #define _CNL_PORT_TX_DW7_GRP_D 0x162BDC | ||
2067 | #define _CNL_PORT_TX_DW7_GRP_F 0x162A5C | ||
2068 | #define _CNL_PORT_TX_DW7_LN0_AE 0x16245C | ||
2069 | #define _CNL_PORT_TX_DW7_LN0_B 0x16265C | ||
2070 | #define _CNL_PORT_TX_DW7_LN0_C 0x162C5C | ||
2071 | #define _CNL_PORT_TX_DW7_LN0_D 0x162E5C | ||
2072 | #define _CNL_PORT_TX_DW7_LN0_F 0x16285C | ||
2073 | #define CNL_PORT_TX_DW7_GRP(port) _MMIO_PORT6(port, \ | ||
2074 | _CNL_PORT_TX_DW7_GRP_AE, \ | ||
2075 | _CNL_PORT_TX_DW7_GRP_B, \ | ||
2076 | _CNL_PORT_TX_DW7_GRP_C, \ | ||
2077 | _CNL_PORT_TX_DW7_GRP_D, \ | ||
2078 | _CNL_PORT_TX_DW7_GRP_AE, \ | ||
2079 | _CNL_PORT_TX_DW7_GRP_F) | ||
2080 | #define CNL_PORT_TX_DW7_LN0(port) _MMIO_PORT6(port, \ | ||
2081 | _CNL_PORT_TX_DW7_LN0_AE, \ | ||
2082 | _CNL_PORT_TX_DW7_LN0_B, \ | ||
2083 | _CNL_PORT_TX_DW7_LN0_C, \ | ||
2084 | _CNL_PORT_TX_DW7_LN0_D, \ | ||
2085 | _CNL_PORT_TX_DW7_LN0_AE, \ | ||
2086 | _CNL_PORT_TX_DW7_LN0_F) | ||
2087 | #define N_SCALAR(x) ((x) << 24) | 1827 | #define N_SCALAR(x) ((x) << 24) |
2088 | #define N_SCALAR_MASK (0x7F << 24) | 1828 | #define N_SCALAR_MASK (0x7F << 24) |
2089 | 1829 | ||
1830 | #define _ICL_MG_PHY_PORT_LN(port, ln, ln0p1, ln0p2, ln1p1) \ | ||
1831 | _MMIO(_PORT((port) - PORT_C, ln0p1, ln0p2) + (ln) * ((ln1p1) - (ln0p1))) | ||
1832 | |||
1833 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT1 0x16812C | ||
1834 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN1_PORT1 0x16852C | ||
1835 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT2 0x16912C | ||
1836 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN1_PORT2 0x16952C | ||
1837 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT3 0x16A12C | ||
1838 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN1_PORT3 0x16A52C | ||
1839 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT4 0x16B12C | ||
1840 | #define _ICL_MG_TX_LINK_PARAMS_TX1LN1_PORT4 0x16B52C | ||
1841 | #define ICL_PORT_MG_TX1_LINK_PARAMS(port, ln) \ | ||
1842 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT1, \ | ||
1843 | _ICL_MG_TX_LINK_PARAMS_TX1LN0_PORT2, \ | ||
1844 | _ICL_MG_TX_LINK_PARAMS_TX1LN1_PORT1) | ||
1845 | |||
1846 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT1 0x1680AC | ||
1847 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN1_PORT1 0x1684AC | ||
1848 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT2 0x1690AC | ||
1849 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN1_PORT2 0x1694AC | ||
1850 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT3 0x16A0AC | ||
1851 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN1_PORT3 0x16A4AC | ||
1852 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT4 0x16B0AC | ||
1853 | #define _ICL_MG_TX_LINK_PARAMS_TX2LN1_PORT4 0x16B4AC | ||
1854 | #define ICL_PORT_MG_TX2_LINK_PARAMS(port, ln) \ | ||
1855 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT1, \ | ||
1856 | _ICL_MG_TX_LINK_PARAMS_TX2LN0_PORT2, \ | ||
1857 | _ICL_MG_TX_LINK_PARAMS_TX2LN1_PORT1) | ||
1858 | #define CRI_USE_FS32 (1 << 5) | ||
1859 | |||
1860 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT1 0x16814C | ||
1861 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN1_PORT1 0x16854C | ||
1862 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT2 0x16914C | ||
1863 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN1_PORT2 0x16954C | ||
1864 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT3 0x16A14C | ||
1865 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN1_PORT3 0x16A54C | ||
1866 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT4 0x16B14C | ||
1867 | #define _ICL_MG_TX_PISO_READLOAD_TX1LN1_PORT4 0x16B54C | ||
1868 | #define ICL_PORT_MG_TX1_PISO_READLOAD(port, ln) \ | ||
1869 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT1, \ | ||
1870 | _ICL_MG_TX_PISO_READLOAD_TX1LN0_PORT2, \ | ||
1871 | _ICL_MG_TX_PISO_READLOAD_TX1LN1_PORT1) | ||
1872 | |||
1873 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT1 0x1680CC | ||
1874 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN1_PORT1 0x1684CC | ||
1875 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT2 0x1690CC | ||
1876 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN1_PORT2 0x1694CC | ||
1877 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT3 0x16A0CC | ||
1878 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN1_PORT3 0x16A4CC | ||
1879 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT4 0x16B0CC | ||
1880 | #define _ICL_MG_TX_PISO_READLOAD_TX2LN1_PORT4 0x16B4CC | ||
1881 | #define ICL_PORT_MG_TX2_PISO_READLOAD(port, ln) \ | ||
1882 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT1, \ | ||
1883 | _ICL_MG_TX_PISO_READLOAD_TX2LN0_PORT2, \ | ||
1884 | _ICL_MG_TX_PISO_READLOAD_TX2LN1_PORT1) | ||
1885 | #define CRI_CALCINIT (1 << 1) | ||
1886 | |||
1887 | #define _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT1 0x168148 | ||
1888 | #define _ICL_MG_TX_SWINGCTRL_TX1LN1_PORT1 0x168548 | ||
1889 | #define _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT2 0x169148 | ||
1890 | #define _ICL_MG_TX_SWINGCTRL_TX1LN1_PORT2 0x169548 | ||
1891 | #define _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT3 0x16A148 | ||
1892 | #define _ICL_MG_TX_SWINGCTRL_TX1LN1_PORT3 0x16A548 | ||
1893 | #define _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT4 0x16B148 | ||
1894 | #define _ICL_MG_TX_SWINGCTRL_TX1LN1_PORT4 0x16B548 | ||
1895 | #define ICL_PORT_MG_TX1_SWINGCTRL(port, ln) \ | ||
1896 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT1, \ | ||
1897 | _ICL_MG_TX_SWINGCTRL_TX1LN0_PORT2, \ | ||
1898 | _ICL_MG_TX_SWINGCTRL_TX1LN1_PORT1) | ||
1899 | |||
1900 | #define _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT1 0x1680C8 | ||
1901 | #define _ICL_MG_TX_SWINGCTRL_TX2LN1_PORT1 0x1684C8 | ||
1902 | #define _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT2 0x1690C8 | ||
1903 | #define _ICL_MG_TX_SWINGCTRL_TX2LN1_PORT2 0x1694C8 | ||
1904 | #define _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT3 0x16A0C8 | ||
1905 | #define _ICL_MG_TX_SWINGCTRL_TX2LN1_PORT3 0x16A4C8 | ||
1906 | #define _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT4 0x16B0C8 | ||
1907 | #define _ICL_MG_TX_SWINGCTRL_TX2LN1_PORT4 0x16B4C8 | ||
1908 | #define ICL_PORT_MG_TX2_SWINGCTRL(port, ln) \ | ||
1909 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT1, \ | ||
1910 | _ICL_MG_TX_SWINGCTRL_TX2LN0_PORT2, \ | ||
1911 | _ICL_MG_TX_SWINGCTRL_TX2LN1_PORT1) | ||
1912 | #define CRI_TXDEEMPH_OVERRIDE_17_12(x) ((x) << 0) | ||
1913 | #define CRI_TXDEEMPH_OVERRIDE_17_12_MASK (0x3F << 0) | ||
1914 | |||
1915 | #define _ICL_MG_TX_DRVCTRL_TX1LN0_PORT1 0x168144 | ||
1916 | #define _ICL_MG_TX_DRVCTRL_TX1LN1_PORT1 0x168544 | ||
1917 | #define _ICL_MG_TX_DRVCTRL_TX1LN0_PORT2 0x169144 | ||
1918 | #define _ICL_MG_TX_DRVCTRL_TX1LN1_PORT2 0x169544 | ||
1919 | #define _ICL_MG_TX_DRVCTRL_TX1LN0_PORT3 0x16A144 | ||
1920 | #define _ICL_MG_TX_DRVCTRL_TX1LN1_PORT3 0x16A544 | ||
1921 | #define _ICL_MG_TX_DRVCTRL_TX1LN0_PORT4 0x16B144 | ||
1922 | #define _ICL_MG_TX_DRVCTRL_TX1LN1_PORT4 0x16B544 | ||
1923 | #define ICL_PORT_MG_TX1_DRVCTRL(port, ln) \ | ||
1924 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_DRVCTRL_TX1LN0_PORT1, \ | ||
1925 | _ICL_MG_TX_DRVCTRL_TX1LN0_PORT2, \ | ||
1926 | _ICL_MG_TX_DRVCTRL_TX1LN1_PORT1) | ||
1927 | |||
1928 | #define _ICL_MG_TX_DRVCTRL_TX2LN0_PORT1 0x1680C4 | ||
1929 | #define _ICL_MG_TX_DRVCTRL_TX2LN1_PORT1 0x1684C4 | ||
1930 | #define _ICL_MG_TX_DRVCTRL_TX2LN0_PORT2 0x1690C4 | ||
1931 | #define _ICL_MG_TX_DRVCTRL_TX2LN1_PORT2 0x1694C4 | ||
1932 | #define _ICL_MG_TX_DRVCTRL_TX2LN0_PORT3 0x16A0C4 | ||
1933 | #define _ICL_MG_TX_DRVCTRL_TX2LN1_PORT3 0x16A4C4 | ||
1934 | #define _ICL_MG_TX_DRVCTRL_TX2LN0_PORT4 0x16B0C4 | ||
1935 | #define _ICL_MG_TX_DRVCTRL_TX2LN1_PORT4 0x16B4C4 | ||
1936 | #define ICL_PORT_MG_TX2_DRVCTRL(port, ln) \ | ||
1937 | _ICL_MG_PHY_PORT_LN(port, ln, _ICL_MG_TX_DRVCTRL_TX2LN0_PORT1, \ | ||
1938 | _ICL_MG_TX_DRVCTRL_TX2LN0_PORT2, \ | ||
1939 | _ICL_MG_TX_DRVCTRL_TX2LN1_PORT1) | ||
1940 | #define CRI_TXDEEMPH_OVERRIDE_11_6(x) ((x) << 24) | ||
1941 | #define CRI_TXDEEMPH_OVERRIDE_11_6_MASK (0x3F << 24) | ||
1942 | #define CRI_TXDEEMPH_OVERRIDE_EN (1 << 22) | ||
1943 | #define CRI_TXDEEMPH_OVERRIDE_5_0(x) ((x) << 16) | ||
1944 | #define CRI_TXDEEMPH_OVERRIDE_5_0_MASK (0x3F << 16) | ||
1945 | |||
2090 | /* The spec defines this only for BXT PHY0, but lets assume that this | 1946 | /* The spec defines this only for BXT PHY0, but lets assume that this |
2091 | * would exist for PHY1 too if it had a second channel. | 1947 | * would exist for PHY1 too if it had a second channel. |
2092 | */ | 1948 | */ |
@@ -2473,6 +2329,10 @@ enum i915_power_well_id { | |||
2473 | #define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) | 2329 | #define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) |
2474 | #define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) | 2330 | #define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) |
2475 | #define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) | 2331 | #define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) |
2332 | #define GEN11_MCR_SLICE(slice) (((slice) & 0xf) << 27) | ||
2333 | #define GEN11_MCR_SLICE_MASK GEN11_MCR_SLICE(0xf) | ||
2334 | #define GEN11_MCR_SUBSLICE(subslice) (((subslice) & 0x7) << 24) | ||
2335 | #define GEN11_MCR_SUBSLICE_MASK GEN11_MCR_SUBSLICE(0x7) | ||
2476 | #define RING_IPEIR(base) _MMIO((base)+0x64) | 2336 | #define RING_IPEIR(base) _MMIO((base)+0x64) |
2477 | #define RING_IPEHR(base) _MMIO((base)+0x68) | 2337 | #define RING_IPEHR(base) _MMIO((base)+0x68) |
2478 | /* | 2338 | /* |
@@ -2867,6 +2727,19 @@ enum i915_power_well_id { | |||
2867 | #define GEN10_EU_DISABLE3 _MMIO(0x9140) | 2727 | #define GEN10_EU_DISABLE3 _MMIO(0x9140) |
2868 | #define GEN10_EU_DIS_SS_MASK 0xff | 2728 | #define GEN10_EU_DIS_SS_MASK 0xff |
2869 | 2729 | ||
2730 | #define GEN11_GT_VEBOX_VDBOX_DISABLE _MMIO(0x9140) | ||
2731 | #define GEN11_GT_VDBOX_DISABLE_MASK 0xff | ||
2732 | #define GEN11_GT_VEBOX_DISABLE_SHIFT 16 | ||
2733 | #define GEN11_GT_VEBOX_DISABLE_MASK (0xff << GEN11_GT_VEBOX_DISABLE_SHIFT) | ||
2734 | |||
2735 | #define GEN11_EU_DISABLE _MMIO(0x9134) | ||
2736 | #define GEN11_EU_DIS_MASK 0xFF | ||
2737 | |||
2738 | #define GEN11_GT_SLICE_ENABLE _MMIO(0x9138) | ||
2739 | #define GEN11_GT_S_ENA_MASK 0xFF | ||
2740 | |||
2741 | #define GEN11_GT_SUBSLICE_DISABLE _MMIO(0x913C) | ||
2742 | |||
2870 | #define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) | 2743 | #define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) |
2871 | #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) | 2744 | #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) |
2872 | #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) | 2745 | #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) |
@@ -3951,6 +3824,9 @@ enum { | |||
3951 | #define _CLKGATE_DIS_PSL_A 0x46520 | 3824 | #define _CLKGATE_DIS_PSL_A 0x46520 |
3952 | #define _CLKGATE_DIS_PSL_B 0x46524 | 3825 | #define _CLKGATE_DIS_PSL_B 0x46524 |
3953 | #define _CLKGATE_DIS_PSL_C 0x46528 | 3826 | #define _CLKGATE_DIS_PSL_C 0x46528 |
3827 | #define DUPS1_GATING_DIS (1 << 15) | ||
3828 | #define DUPS2_GATING_DIS (1 << 19) | ||
3829 | #define DUPS3_GATING_DIS (1 << 23) | ||
3954 | #define DPF_GATING_DIS (1 << 10) | 3830 | #define DPF_GATING_DIS (1 << 10) |
3955 | #define DPF_RAM_GATING_DIS (1 << 9) | 3831 | #define DPF_RAM_GATING_DIS (1 << 9) |
3956 | #define DPFR_GATING_DIS (1 << 8) | 3832 | #define DPFR_GATING_DIS (1 << 8) |
@@ -4151,6 +4027,12 @@ enum { | |||
4151 | #define EDP_PSR_IDLE_FRAME_SHIFT 0 | 4027 | #define EDP_PSR_IDLE_FRAME_SHIFT 0 |
4152 | 4028 | ||
4153 | #define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10) | 4029 | #define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10) |
4030 | #define EDP_PSR_AUX_CTL_TIME_OUT_MASK (3 << 26) | ||
4031 | #define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK (0x1f << 20) | ||
4032 | #define EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK (0xf << 16) | ||
4033 | #define EDP_PSR_AUX_CTL_ERROR_INTERRUPT (1 << 11) | ||
4034 | #define EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK (0x7ff) | ||
4035 | |||
4154 | #define EDP_PSR_AUX_DATA(i) _MMIO(dev_priv->psr_mmio_base + 0x14 + (i) * 4) /* 5 registers */ | 4036 | #define EDP_PSR_AUX_DATA(i) _MMIO(dev_priv->psr_mmio_base + 0x14 + (i) * 4) /* 5 registers */ |
4155 | 4037 | ||
4156 | #define EDP_PSR_STATUS _MMIO(dev_priv->psr_mmio_base + 0x40) | 4038 | #define EDP_PSR_STATUS _MMIO(dev_priv->psr_mmio_base + 0x40) |
@@ -4180,17 +4062,19 @@ enum { | |||
4180 | #define EDP_PSR_PERF_CNT _MMIO(dev_priv->psr_mmio_base + 0x44) | 4062 | #define EDP_PSR_PERF_CNT _MMIO(dev_priv->psr_mmio_base + 0x44) |
4181 | #define EDP_PSR_PERF_CNT_MASK 0xffffff | 4063 | #define EDP_PSR_PERF_CNT_MASK 0xffffff |
4182 | 4064 | ||
4183 | #define EDP_PSR_DEBUG _MMIO(dev_priv->psr_mmio_base + 0x60) | 4065 | #define EDP_PSR_DEBUG _MMIO(dev_priv->psr_mmio_base + 0x60) /* PSR_MASK on SKL+ */ |
4184 | #define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1<<28) | 4066 | #define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1<<28) |
4185 | #define EDP_PSR_DEBUG_MASK_LPSP (1<<27) | 4067 | #define EDP_PSR_DEBUG_MASK_LPSP (1<<27) |
4186 | #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) | 4068 | #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) |
4187 | #define EDP_PSR_DEBUG_MASK_HPD (1<<25) | 4069 | #define EDP_PSR_DEBUG_MASK_HPD (1<<25) |
4188 | #define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (1<<16) | 4070 | #define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (1<<16) |
4189 | #define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1<<15) | 4071 | #define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1<<15) /* SKL+ */ |
4190 | 4072 | ||
4191 | #define EDP_PSR2_CTL _MMIO(0x6f900) | 4073 | #define EDP_PSR2_CTL _MMIO(0x6f900) |
4192 | #define EDP_PSR2_ENABLE (1<<31) | 4074 | #define EDP_PSR2_ENABLE (1<<31) |
4193 | #define EDP_SU_TRACK_ENABLE (1<<30) | 4075 | #define EDP_SU_TRACK_ENABLE (1<<30) |
4076 | #define EDP_Y_COORDINATE_VALID (1<<26) /* GLK and CNL+ */ | ||
4077 | #define EDP_Y_COORDINATE_ENABLE (1<<25) /* GLK and CNL+ */ | ||
4194 | #define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20) | 4078 | #define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20) |
4195 | #define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f<<20) | 4079 | #define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f<<20) |
4196 | #define EDP_PSR2_TP2_TIME_500 (0<<8) | 4080 | #define EDP_PSR2_TP2_TIME_500 (0<<8) |
@@ -4200,8 +4084,9 @@ enum { | |||
4200 | #define EDP_PSR2_TP2_TIME_MASK (3<<8) | 4084 | #define EDP_PSR2_TP2_TIME_MASK (3<<8) |
4201 | #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 | 4085 | #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 |
4202 | #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) | 4086 | #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) |
4203 | #define EDP_PSR2_IDLE_MASK 0xf | ||
4204 | #define EDP_PSR2_FRAME_BEFORE_SU(a) ((a)<<4) | 4087 | #define EDP_PSR2_FRAME_BEFORE_SU(a) ((a)<<4) |
4088 | #define EDP_PSR2_IDLE_FRAME_MASK 0xf | ||
4089 | #define EDP_PSR2_IDLE_FRAME_SHIFT 0 | ||
4205 | 4090 | ||
4206 | #define EDP_PSR2_STATUS _MMIO(0x6f940) | 4091 | #define EDP_PSR2_STATUS _MMIO(0x6f940) |
4207 | #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) | 4092 | #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) |
@@ -5265,8 +5150,6 @@ enum { | |||
5265 | #define DP_LINK_TRAIN_OFF (3 << 28) | 5150 | #define DP_LINK_TRAIN_OFF (3 << 28) |
5266 | #define DP_LINK_TRAIN_MASK (3 << 28) | 5151 | #define DP_LINK_TRAIN_MASK (3 << 28) |
5267 | #define DP_LINK_TRAIN_SHIFT 28 | 5152 | #define DP_LINK_TRAIN_SHIFT 28 |
5268 | #define DP_LINK_TRAIN_PAT_3_CHV (1 << 14) | ||
5269 | #define DP_LINK_TRAIN_MASK_CHV ((3 << 28)|(1<<14)) | ||
5270 | 5153 | ||
5271 | /* CPT Link training mode */ | 5154 | /* CPT Link training mode */ |
5272 | #define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) | 5155 | #define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) |
@@ -6009,6 +5892,7 @@ enum { | |||
6009 | #define CURSIZE _MMIO(0x700a0) /* 845/865 */ | 5892 | #define CURSIZE _MMIO(0x700a0) /* 845/865 */ |
6010 | #define _CUR_FBC_CTL_A 0x700a0 /* ivb+ */ | 5893 | #define _CUR_FBC_CTL_A 0x700a0 /* ivb+ */ |
6011 | #define CUR_FBC_CTL_EN (1 << 31) | 5894 | #define CUR_FBC_CTL_EN (1 << 31) |
5895 | #define _CURASURFLIVE 0x700ac /* g4x+ */ | ||
6012 | #define _CURBCNTR 0x700c0 | 5896 | #define _CURBCNTR 0x700c0 |
6013 | #define _CURBBASE 0x700c4 | 5897 | #define _CURBBASE 0x700c4 |
6014 | #define _CURBPOS 0x700c8 | 5898 | #define _CURBPOS 0x700c8 |
@@ -6025,6 +5909,7 @@ enum { | |||
6025 | #define CURBASE(pipe) _CURSOR2(pipe, _CURABASE) | 5909 | #define CURBASE(pipe) _CURSOR2(pipe, _CURABASE) |
6026 | #define CURPOS(pipe) _CURSOR2(pipe, _CURAPOS) | 5910 | #define CURPOS(pipe) _CURSOR2(pipe, _CURAPOS) |
6027 | #define CUR_FBC_CTL(pipe) _CURSOR2(pipe, _CUR_FBC_CTL_A) | 5911 | #define CUR_FBC_CTL(pipe) _CURSOR2(pipe, _CUR_FBC_CTL_A) |
5912 | #define CURSURFLIVE(pipe) _CURSOR2(pipe, _CURASURFLIVE) | ||
6028 | 5913 | ||
6029 | #define CURSOR_A_OFFSET 0x70080 | 5914 | #define CURSOR_A_OFFSET 0x70080 |
6030 | #define CURSOR_B_OFFSET 0x700c0 | 5915 | #define CURSOR_B_OFFSET 0x700c0 |
@@ -6779,6 +6664,8 @@ enum { | |||
6779 | #define PS_SCALER_MODE_MASK (3 << 28) | 6664 | #define PS_SCALER_MODE_MASK (3 << 28) |
6780 | #define PS_SCALER_MODE_DYN (0 << 28) | 6665 | #define PS_SCALER_MODE_DYN (0 << 28) |
6781 | #define PS_SCALER_MODE_HQ (1 << 28) | 6666 | #define PS_SCALER_MODE_HQ (1 << 28) |
6667 | #define SKL_PS_SCALER_MODE_NV12 (2 << 28) | ||
6668 | #define PS_SCALER_MODE_PLANAR (1 << 29) | ||
6782 | #define PS_PLANE_SEL_MASK (7 << 25) | 6669 | #define PS_PLANE_SEL_MASK (7 << 25) |
6783 | #define PS_PLANE_SEL(plane) (((plane) + 1) << 25) | 6670 | #define PS_PLANE_SEL(plane) (((plane) + 1) << 25) |
6784 | #define PS_FILTER_MASK (3 << 23) | 6671 | #define PS_FILTER_MASK (3 << 23) |
@@ -7117,7 +7004,9 @@ enum { | |||
7117 | #define GEN11_INTR_IDENTITY_REG0 _MMIO(0x190060) | 7004 | #define GEN11_INTR_IDENTITY_REG0 _MMIO(0x190060) |
7118 | #define GEN11_INTR_IDENTITY_REG1 _MMIO(0x190064) | 7005 | #define GEN11_INTR_IDENTITY_REG1 _MMIO(0x190064) |
7119 | #define GEN11_INTR_DATA_VALID (1 << 31) | 7006 | #define GEN11_INTR_DATA_VALID (1 << 31) |
7120 | #define GEN11_INTR_ENGINE_MASK (0xffff) | 7007 | #define GEN11_INTR_ENGINE_CLASS(x) (((x) & GENMASK(18, 16)) >> 16) |
7008 | #define GEN11_INTR_ENGINE_INSTANCE(x) (((x) & GENMASK(25, 20)) >> 20) | ||
7009 | #define GEN11_INTR_ENGINE_INTR(x) ((x) & 0xffff) | ||
7121 | 7010 | ||
7122 | #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + (x * 4)) | 7011 | #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + (x * 4)) |
7123 | 7012 | ||
@@ -7197,6 +7086,7 @@ enum { | |||
7197 | #define CHICKEN_TRANS_A 0x420c0 | 7086 | #define CHICKEN_TRANS_A 0x420c0 |
7198 | #define CHICKEN_TRANS_B 0x420c4 | 7087 | #define CHICKEN_TRANS_B 0x420c4 |
7199 | #define CHICKEN_TRANS(trans) _MMIO_TRANS(trans, CHICKEN_TRANS_A, CHICKEN_TRANS_B) | 7088 | #define CHICKEN_TRANS(trans) _MMIO_TRANS(trans, CHICKEN_TRANS_A, CHICKEN_TRANS_B) |
7089 | #define VSC_DATA_SEL_SOFTWARE_CONTROL (1<<25) /* GLK and CNL+ */ | ||
7200 | #define DDI_TRAINING_OVERRIDE_ENABLE (1<<19) | 7090 | #define DDI_TRAINING_OVERRIDE_ENABLE (1<<19) |
7201 | #define DDI_TRAINING_OVERRIDE_VALUE (1<<18) | 7091 | #define DDI_TRAINING_OVERRIDE_VALUE (1<<18) |
7202 | #define DDIE_TRAINING_OVERRIDE_ENABLE (1<<17) /* CHICKEN_TRANS_A only */ | 7092 | #define DDIE_TRAINING_OVERRIDE_ENABLE (1<<17) /* CHICKEN_TRANS_A only */ |
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 282f57630cc1..9ca9c24b4421 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c | |||
@@ -59,11 +59,7 @@ static bool i915_fence_signaled(struct dma_fence *fence) | |||
59 | 59 | ||
60 | static bool i915_fence_enable_signaling(struct dma_fence *fence) | 60 | static bool i915_fence_enable_signaling(struct dma_fence *fence) |
61 | { | 61 | { |
62 | if (i915_fence_signaled(fence)) | 62 | return intel_engine_enable_signaling(to_request(fence), true); |
63 | return false; | ||
64 | |||
65 | intel_engine_enable_signaling(to_request(fence), true); | ||
66 | return !i915_fence_signaled(fence); | ||
67 | } | 63 | } |
68 | 64 | ||
69 | static signed long i915_fence_wait(struct dma_fence *fence, | 65 | static signed long i915_fence_wait(struct dma_fence *fence, |
@@ -211,11 +207,19 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | |||
211 | if (ret) | 207 | if (ret) |
212 | return ret; | 208 | return ret; |
213 | 209 | ||
210 | GEM_BUG_ON(i915->gt.active_requests); | ||
211 | |||
214 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ | 212 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ |
215 | for_each_engine(engine, i915, id) { | 213 | for_each_engine(engine, i915, id) { |
216 | struct i915_gem_timeline *timeline; | 214 | struct i915_gem_timeline *timeline; |
217 | struct intel_timeline *tl = engine->timeline; | 215 | struct intel_timeline *tl = engine->timeline; |
218 | 216 | ||
217 | GEM_TRACE("%s seqno %d (current %d) -> %d\n", | ||
218 | engine->name, | ||
219 | tl->seqno, | ||
220 | intel_engine_get_seqno(engine), | ||
221 | seqno); | ||
222 | |||
219 | if (!i915_seqno_passed(seqno, tl->seqno)) { | 223 | if (!i915_seqno_passed(seqno, tl->seqno)) { |
220 | /* Flush any waiters before we reuse the seqno */ | 224 | /* Flush any waiters before we reuse the seqno */ |
221 | intel_engine_disarm_breadcrumbs(engine); | 225 | intel_engine_disarm_breadcrumbs(engine); |
@@ -251,47 +255,6 @@ int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) | |||
251 | return reset_all_global_seqno(i915, seqno - 1); | 255 | return reset_all_global_seqno(i915, seqno - 1); |
252 | } | 256 | } |
253 | 257 | ||
254 | static void mark_busy(struct drm_i915_private *i915) | ||
255 | { | ||
256 | if (i915->gt.awake) | ||
257 | return; | ||
258 | |||
259 | GEM_BUG_ON(!i915->gt.active_requests); | ||
260 | |||
261 | intel_runtime_pm_get_noresume(i915); | ||
262 | |||
263 | /* | ||
264 | * It seems that the DMC likes to transition between the DC states a lot | ||
265 | * when there are no connected displays (no active power domains) during | ||
266 | * command submission. | ||
267 | * | ||
268 | * This activity has negative impact on the performance of the chip with | ||
269 | * huge latencies observed in the interrupt handler and elsewhere. | ||
270 | * | ||
271 | * Work around it by grabbing a GT IRQ power domain whilst there is any | ||
272 | * GT activity, preventing any DC state transitions. | ||
273 | */ | ||
274 | intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ); | ||
275 | |||
276 | i915->gt.awake = true; | ||
277 | if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */ | ||
278 | i915->gt.epoch = 1; | ||
279 | |||
280 | intel_enable_gt_powersave(i915); | ||
281 | i915_update_gfx_val(i915); | ||
282 | if (INTEL_GEN(i915) >= 6) | ||
283 | gen6_rps_busy(i915); | ||
284 | i915_pmu_gt_unparked(i915); | ||
285 | |||
286 | intel_engines_unpark(i915); | ||
287 | |||
288 | i915_queue_hangcheck(i915); | ||
289 | |||
290 | queue_delayed_work(i915->wq, | ||
291 | &i915->gt.retire_work, | ||
292 | round_jiffies_up_relative(HZ)); | ||
293 | } | ||
294 | |||
295 | static int reserve_engine(struct intel_engine_cs *engine) | 258 | static int reserve_engine(struct intel_engine_cs *engine) |
296 | { | 259 | { |
297 | struct drm_i915_private *i915 = engine->i915; | 260 | struct drm_i915_private *i915 = engine->i915; |
@@ -309,7 +272,7 @@ static int reserve_engine(struct intel_engine_cs *engine) | |||
309 | } | 272 | } |
310 | 273 | ||
311 | if (!i915->gt.active_requests++) | 274 | if (!i915->gt.active_requests++) |
312 | mark_busy(i915); | 275 | i915_gem_unpark(i915); |
313 | 276 | ||
314 | return 0; | 277 | return 0; |
315 | } | 278 | } |
@@ -318,13 +281,8 @@ static void unreserve_engine(struct intel_engine_cs *engine) | |||
318 | { | 281 | { |
319 | struct drm_i915_private *i915 = engine->i915; | 282 | struct drm_i915_private *i915 = engine->i915; |
320 | 283 | ||
321 | if (!--i915->gt.active_requests) { | 284 | if (!--i915->gt.active_requests) |
322 | /* Cancel the mark_busy() from our reserve_engine() */ | 285 | i915_gem_park(i915); |
323 | GEM_BUG_ON(!i915->gt.awake); | ||
324 | mod_delayed_work(i915->wq, | ||
325 | &i915->gt.idle_work, | ||
326 | msecs_to_jiffies(100)); | ||
327 | } | ||
328 | 286 | ||
329 | GEM_BUG_ON(!engine->timeline->inflight_seqnos); | 287 | GEM_BUG_ON(!engine->timeline->inflight_seqnos); |
330 | engine->timeline->inflight_seqnos--; | 288 | engine->timeline->inflight_seqnos--; |
@@ -358,7 +316,7 @@ static void advance_ring(struct i915_request *request) | |||
358 | * is just about to be. Either works, if we miss the last two | 316 | * is just about to be. Either works, if we miss the last two |
359 | * noops - they are safe to be replayed on a reset. | 317 | * noops - they are safe to be replayed on a reset. |
360 | */ | 318 | */ |
361 | tail = READ_ONCE(request->ring->tail); | 319 | tail = READ_ONCE(request->tail); |
362 | } else { | 320 | } else { |
363 | tail = request->postfix; | 321 | tail = request->postfix; |
364 | } | 322 | } |
@@ -385,6 +343,12 @@ static void i915_request_retire(struct i915_request *request) | |||
385 | struct intel_engine_cs *engine = request->engine; | 343 | struct intel_engine_cs *engine = request->engine; |
386 | struct i915_gem_active *active, *next; | 344 | struct i915_gem_active *active, *next; |
387 | 345 | ||
346 | GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", | ||
347 | engine->name, | ||
348 | request->fence.context, request->fence.seqno, | ||
349 | request->global_seqno, | ||
350 | intel_engine_get_seqno(engine)); | ||
351 | |||
388 | lockdep_assert_held(&request->i915->drm.struct_mutex); | 352 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
389 | GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); | 353 | GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); |
390 | GEM_BUG_ON(!i915_request_completed(request)); | 354 | GEM_BUG_ON(!i915_request_completed(request)); |
@@ -486,21 +450,34 @@ static u32 timeline_get_seqno(struct intel_timeline *tl) | |||
486 | return ++tl->seqno; | 450 | return ++tl->seqno; |
487 | } | 451 | } |
488 | 452 | ||
453 | static void move_to_timeline(struct i915_request *request, | ||
454 | struct intel_timeline *timeline) | ||
455 | { | ||
456 | GEM_BUG_ON(request->timeline == request->engine->timeline); | ||
457 | lockdep_assert_held(&request->engine->timeline->lock); | ||
458 | |||
459 | spin_lock(&request->timeline->lock); | ||
460 | list_move_tail(&request->link, &timeline->requests); | ||
461 | spin_unlock(&request->timeline->lock); | ||
462 | } | ||
463 | |||
489 | void __i915_request_submit(struct i915_request *request) | 464 | void __i915_request_submit(struct i915_request *request) |
490 | { | 465 | { |
491 | struct intel_engine_cs *engine = request->engine; | 466 | struct intel_engine_cs *engine = request->engine; |
492 | struct intel_timeline *timeline; | ||
493 | u32 seqno; | 467 | u32 seqno; |
494 | 468 | ||
469 | GEM_TRACE("%s fence %llx:%d -> global=%d, current %d\n", | ||
470 | engine->name, | ||
471 | request->fence.context, request->fence.seqno, | ||
472 | engine->timeline->seqno + 1, | ||
473 | intel_engine_get_seqno(engine)); | ||
474 | |||
495 | GEM_BUG_ON(!irqs_disabled()); | 475 | GEM_BUG_ON(!irqs_disabled()); |
496 | lockdep_assert_held(&engine->timeline->lock); | 476 | lockdep_assert_held(&engine->timeline->lock); |
497 | 477 | ||
498 | /* Transfer from per-context onto the global per-engine timeline */ | ||
499 | timeline = engine->timeline; | ||
500 | GEM_BUG_ON(timeline == request->timeline); | ||
501 | GEM_BUG_ON(request->global_seqno); | 478 | GEM_BUG_ON(request->global_seqno); |
502 | 479 | ||
503 | seqno = timeline_get_seqno(timeline); | 480 | seqno = timeline_get_seqno(engine->timeline); |
504 | GEM_BUG_ON(!seqno); | 481 | GEM_BUG_ON(!seqno); |
505 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); | 482 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); |
506 | 483 | ||
@@ -514,9 +491,8 @@ void __i915_request_submit(struct i915_request *request) | |||
514 | engine->emit_breadcrumb(request, | 491 | engine->emit_breadcrumb(request, |
515 | request->ring->vaddr + request->postfix); | 492 | request->ring->vaddr + request->postfix); |
516 | 493 | ||
517 | spin_lock(&request->timeline->lock); | 494 | /* Transfer from per-context onto the global per-engine timeline */ |
518 | list_move_tail(&request->link, &timeline->requests); | 495 | move_to_timeline(request, engine->timeline); |
519 | spin_unlock(&request->timeline->lock); | ||
520 | 496 | ||
521 | trace_i915_request_execute(request); | 497 | trace_i915_request_execute(request); |
522 | 498 | ||
@@ -539,7 +515,12 @@ void i915_request_submit(struct i915_request *request) | |||
539 | void __i915_request_unsubmit(struct i915_request *request) | 515 | void __i915_request_unsubmit(struct i915_request *request) |
540 | { | 516 | { |
541 | struct intel_engine_cs *engine = request->engine; | 517 | struct intel_engine_cs *engine = request->engine; |
542 | struct intel_timeline *timeline; | 518 | |
519 | GEM_TRACE("%s fence %llx:%d <- global=%d, current %d\n", | ||
520 | engine->name, | ||
521 | request->fence.context, request->fence.seqno, | ||
522 | request->global_seqno, | ||
523 | intel_engine_get_seqno(engine)); | ||
543 | 524 | ||
544 | GEM_BUG_ON(!irqs_disabled()); | 525 | GEM_BUG_ON(!irqs_disabled()); |
545 | lockdep_assert_held(&engine->timeline->lock); | 526 | lockdep_assert_held(&engine->timeline->lock); |
@@ -562,12 +543,7 @@ void __i915_request_unsubmit(struct i915_request *request) | |||
562 | spin_unlock(&request->lock); | 543 | spin_unlock(&request->lock); |
563 | 544 | ||
564 | /* Transfer back from the global per-engine timeline to per-context */ | 545 | /* Transfer back from the global per-engine timeline to per-context */ |
565 | timeline = request->timeline; | 546 | move_to_timeline(request, request->timeline); |
566 | GEM_BUG_ON(timeline == engine->timeline); | ||
567 | |||
568 | spin_lock(&timeline->lock); | ||
569 | list_move(&request->link, &timeline->requests); | ||
570 | spin_unlock(&timeline->lock); | ||
571 | 547 | ||
572 | /* | 548 | /* |
573 | * We don't need to wake_up any waiters on request->execute, they | 549 | * We don't need to wake_up any waiters on request->execute, they |
@@ -1000,6 +976,9 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) | |||
1000 | u32 *cs; | 976 | u32 *cs; |
1001 | int err; | 977 | int err; |
1002 | 978 | ||
979 | GEM_TRACE("%s fence %llx:%d\n", | ||
980 | engine->name, request->fence.context, request->fence.seqno); | ||
981 | |||
1003 | lockdep_assert_held(&request->i915->drm.struct_mutex); | 982 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
1004 | trace_i915_request_add(request); | 983 | trace_i915_request_add(request); |
1005 | 984 | ||
@@ -1206,11 +1185,13 @@ static bool __i915_spin_request(const struct i915_request *rq, | |||
1206 | 1185 | ||
1207 | static bool __i915_wait_request_check_and_reset(struct i915_request *request) | 1186 | static bool __i915_wait_request_check_and_reset(struct i915_request *request) |
1208 | { | 1187 | { |
1209 | if (likely(!i915_reset_handoff(&request->i915->gpu_error))) | 1188 | struct i915_gpu_error *error = &request->i915->gpu_error; |
1189 | |||
1190 | if (likely(!i915_reset_handoff(error))) | ||
1210 | return false; | 1191 | return false; |
1211 | 1192 | ||
1212 | __set_current_state(TASK_RUNNING); | 1193 | __set_current_state(TASK_RUNNING); |
1213 | i915_reset(request->i915, 0); | 1194 | i915_reset(request->i915, error->stalled_mask, error->reason); |
1214 | return true; | 1195 | return true; |
1215 | } | 1196 | } |
1216 | 1197 | ||
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 51dbfe5bb418..0695717522ea 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h | |||
@@ -40,8 +40,8 @@ | |||
40 | #undef WARN_ON_ONCE | 40 | #undef WARN_ON_ONCE |
41 | #define WARN_ON_ONCE(x) WARN_ONCE((x), "%s", "WARN_ON_ONCE(" __stringify(x) ")") | 41 | #define WARN_ON_ONCE(x) WARN_ONCE((x), "%s", "WARN_ON_ONCE(" __stringify(x) ")") |
42 | 42 | ||
43 | #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ | 43 | #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ |
44 | (long)(x), __func__) | 44 | __stringify(x), (long)(x)) |
45 | 45 | ||
46 | #if GCC_VERSION >= 70000 | 46 | #if GCC_VERSION >= 70000 |
47 | #define add_overflows(A, B) \ | 47 | #define add_overflows(A, B) \ |
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index e9fb692076d7..40285d1b91b7 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c | |||
@@ -227,6 +227,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, | |||
227 | struct intel_crtc_scaler_state *scaler_state = | 227 | struct intel_crtc_scaler_state *scaler_state = |
228 | &crtc_state->scaler_state; | 228 | &crtc_state->scaler_state; |
229 | struct drm_atomic_state *drm_state = crtc_state->base.state; | 229 | struct drm_atomic_state *drm_state = crtc_state->base.state; |
230 | struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state); | ||
230 | int num_scalers_need; | 231 | int num_scalers_need; |
231 | int i, j; | 232 | int i, j; |
232 | 233 | ||
@@ -304,8 +305,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, | |||
304 | continue; | 305 | continue; |
305 | } | 306 | } |
306 | 307 | ||
307 | plane_state = intel_atomic_get_existing_plane_state(drm_state, | 308 | plane_state = intel_atomic_get_new_plane_state(intel_state, |
308 | intel_plane); | 309 | intel_plane); |
309 | scaler_id = &plane_state->scaler_id; | 310 | scaler_id = &plane_state->scaler_id; |
310 | } | 311 | } |
311 | 312 | ||
@@ -328,8 +329,18 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, | |||
328 | } | 329 | } |
329 | 330 | ||
330 | /* set scaler mode */ | 331 | /* set scaler mode */ |
331 | if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 332 | if ((INTEL_GEN(dev_priv) >= 9) && |
332 | scaler_state->scalers[*scaler_id].mode = 0; | 333 | plane_state && plane_state->base.fb && |
334 | plane_state->base.fb->format->format == | ||
335 | DRM_FORMAT_NV12) { | ||
336 | if (INTEL_GEN(dev_priv) == 9 && | ||
337 | !IS_GEMINILAKE(dev_priv) && | ||
338 | !IS_SKYLAKE(dev_priv)) | ||
339 | scaler_state->scalers[*scaler_id].mode = | ||
340 | SKL_PS_SCALER_MODE_NV12; | ||
341 | else | ||
342 | scaler_state->scalers[*scaler_id].mode = | ||
343 | PS_SCALER_MODE_PLANAR; | ||
333 | } else if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) { | 344 | } else if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) { |
334 | /* | 345 | /* |
335 | * when only 1 scaler is in use on either pipe A or B, | 346 | * when only 1 scaler is in use on either pipe A or B, |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 447b721c3be9..702d3fab97fc 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -1215,10 +1215,8 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
1215 | { | 1215 | { |
1216 | struct child_device_config *it, *child = NULL; | 1216 | struct child_device_config *it, *child = NULL; |
1217 | struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; | 1217 | struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; |
1218 | uint8_t hdmi_level_shift; | ||
1219 | int i, j; | 1218 | int i, j; |
1220 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; | 1219 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; |
1221 | uint8_t aux_channel, ddc_pin; | ||
1222 | /* Each DDI port can have more than one value on the "DVO Port" field, | 1220 | /* Each DDI port can have more than one value on the "DVO Port" field, |
1223 | * so look for all the possible values for each port. | 1221 | * so look for all the possible values for each port. |
1224 | */ | 1222 | */ |
@@ -1255,8 +1253,6 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
1255 | if (!child) | 1253 | if (!child) |
1256 | return; | 1254 | return; |
1257 | 1255 | ||
1258 | aux_channel = child->aux_channel; | ||
1259 | |||
1260 | is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; | 1256 | is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; |
1261 | is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; | 1257 | is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; |
1262 | is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT; | 1258 | is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT; |
@@ -1270,13 +1266,6 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
1270 | is_hdmi = false; | 1266 | is_hdmi = false; |
1271 | } | 1267 | } |
1272 | 1268 | ||
1273 | if (port == PORT_A && is_dvi) { | ||
1274 | DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", | ||
1275 | is_hdmi ? "/HDMI" : ""); | ||
1276 | is_dvi = false; | ||
1277 | is_hdmi = false; | ||
1278 | } | ||
1279 | |||
1280 | info->supports_dvi = is_dvi; | 1269 | info->supports_dvi = is_dvi; |
1281 | info->supports_hdmi = is_hdmi; | 1270 | info->supports_hdmi = is_hdmi; |
1282 | info->supports_dp = is_dp; | 1271 | info->supports_dp = is_dp; |
@@ -1302,6 +1291,8 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
1302 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); | 1291 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
1303 | 1292 | ||
1304 | if (is_dvi) { | 1293 | if (is_dvi) { |
1294 | u8 ddc_pin; | ||
1295 | |||
1305 | ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin); | 1296 | ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin); |
1306 | if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) { | 1297 | if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) { |
1307 | info->alternate_ddc_pin = ddc_pin; | 1298 | info->alternate_ddc_pin = ddc_pin; |
@@ -1314,14 +1305,14 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
1314 | } | 1305 | } |
1315 | 1306 | ||
1316 | if (is_dp) { | 1307 | if (is_dp) { |
1317 | info->alternate_aux_channel = aux_channel; | 1308 | info->alternate_aux_channel = child->aux_channel; |
1318 | 1309 | ||
1319 | sanitize_aux_ch(dev_priv, port); | 1310 | sanitize_aux_ch(dev_priv, port); |
1320 | } | 1311 | } |
1321 | 1312 | ||
1322 | if (bdb_version >= 158) { | 1313 | if (bdb_version >= 158) { |
1323 | /* The VBT HDMI level shift values match the table we have. */ | 1314 | /* The VBT HDMI level shift values match the table we have. */ |
1324 | hdmi_level_shift = child->hdmi_level_shifter_value; | 1315 | u8 hdmi_level_shift = child->hdmi_level_shifter_value; |
1325 | DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", | 1316 | DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", |
1326 | port_name(port), | 1317 | port_name(port), |
1327 | hdmi_level_shift); | 1318 | hdmi_level_shift); |
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 1f79e7a47433..671a6d61e29d 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
@@ -730,10 +730,11 @@ static void insert_signal(struct intel_breadcrumbs *b, | |||
730 | list_add(&request->signaling.link, &iter->signaling.link); | 730 | list_add(&request->signaling.link, &iter->signaling.link); |
731 | } | 731 | } |
732 | 732 | ||
733 | void intel_engine_enable_signaling(struct i915_request *request, bool wakeup) | 733 | bool intel_engine_enable_signaling(struct i915_request *request, bool wakeup) |
734 | { | 734 | { |
735 | struct intel_engine_cs *engine = request->engine; | 735 | struct intel_engine_cs *engine = request->engine; |
736 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 736 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
737 | struct intel_wait *wait = &request->signaling.wait; | ||
737 | u32 seqno; | 738 | u32 seqno; |
738 | 739 | ||
739 | /* | 740 | /* |
@@ -750,12 +751,12 @@ void intel_engine_enable_signaling(struct i915_request *request, bool wakeup) | |||
750 | 751 | ||
751 | seqno = i915_request_global_seqno(request); | 752 | seqno = i915_request_global_seqno(request); |
752 | if (!seqno) /* will be enabled later upon execution */ | 753 | if (!seqno) /* will be enabled later upon execution */ |
753 | return; | 754 | return true; |
754 | 755 | ||
755 | GEM_BUG_ON(request->signaling.wait.seqno); | 756 | GEM_BUG_ON(wait->seqno); |
756 | request->signaling.wait.tsk = b->signaler; | 757 | wait->tsk = b->signaler; |
757 | request->signaling.wait.request = request; | 758 | wait->request = request; |
758 | request->signaling.wait.seqno = seqno; | 759 | wait->seqno = seqno; |
759 | 760 | ||
760 | /* | 761 | /* |
761 | * Add ourselves into the list of waiters, but registering our | 762 | * Add ourselves into the list of waiters, but registering our |
@@ -768,11 +769,15 @@ void intel_engine_enable_signaling(struct i915_request *request, bool wakeup) | |||
768 | */ | 769 | */ |
769 | spin_lock(&b->rb_lock); | 770 | spin_lock(&b->rb_lock); |
770 | insert_signal(b, request, seqno); | 771 | insert_signal(b, request, seqno); |
771 | wakeup &= __intel_engine_add_wait(engine, &request->signaling.wait); | 772 | wakeup &= __intel_engine_add_wait(engine, wait); |
772 | spin_unlock(&b->rb_lock); | 773 | spin_unlock(&b->rb_lock); |
773 | 774 | ||
774 | if (wakeup) | 775 | if (wakeup) { |
775 | wake_up_process(b->signaler); | 776 | wake_up_process(b->signaler); |
777 | return !intel_wait_complete(wait); | ||
778 | } | ||
779 | |||
780 | return true; | ||
776 | } | 781 | } |
777 | 782 | ||
778 | void intel_engine_cancel_signaling(struct i915_request *request) | 783 | void intel_engine_cancel_signaling(struct i915_request *request) |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 8c2d778560f0..92cb26b18a9b 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -493,6 +493,125 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = { | |||
493 | { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */ | 493 | { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */ |
494 | }; | 494 | }; |
495 | 495 | ||
496 | struct icl_combo_phy_ddi_buf_trans { | ||
497 | u32 dw2_swing_select; | ||
498 | u32 dw2_swing_scalar; | ||
499 | u32 dw4_scaling; | ||
500 | }; | ||
501 | |||
502 | /* Voltage Swing Programming for VccIO 0.85V for DP */ | ||
503 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = { | ||
504 | /* Voltage mV db */ | ||
505 | { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ | ||
506 | { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ | ||
507 | { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ | ||
508 | { 0x2, 0x98, 0x900F }, /* 400 9.5 */ | ||
509 | { 0xB, 0x70, 0x0018 }, /* 600 0.0 */ | ||
510 | { 0xB, 0x70, 0x3015 }, /* 600 3.5 */ | ||
511 | { 0xB, 0x70, 0x6012 }, /* 600 6.0 */ | ||
512 | { 0x5, 0x00, 0x0018 }, /* 800 0.0 */ | ||
513 | { 0x5, 0x00, 0x3015 }, /* 800 3.5 */ | ||
514 | { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ | ||
515 | }; | ||
516 | |||
517 | /* FIXME - After table is updated in Bspec */ | ||
518 | /* Voltage Swing Programming for VccIO 0.85V for eDP */ | ||
519 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = { | ||
520 | /* Voltage mV db */ | ||
521 | { 0x0, 0x00, 0x00 }, /* 200 0.0 */ | ||
522 | { 0x0, 0x00, 0x00 }, /* 200 1.5 */ | ||
523 | { 0x0, 0x00, 0x00 }, /* 200 4.0 */ | ||
524 | { 0x0, 0x00, 0x00 }, /* 200 6.0 */ | ||
525 | { 0x0, 0x00, 0x00 }, /* 250 0.0 */ | ||
526 | { 0x0, 0x00, 0x00 }, /* 250 1.5 */ | ||
527 | { 0x0, 0x00, 0x00 }, /* 250 4.0 */ | ||
528 | { 0x0, 0x00, 0x00 }, /* 300 0.0 */ | ||
529 | { 0x0, 0x00, 0x00 }, /* 300 1.5 */ | ||
530 | { 0x0, 0x00, 0x00 }, /* 350 0.0 */ | ||
531 | }; | ||
532 | |||
533 | /* Voltage Swing Programming for VccIO 0.95V for DP */ | ||
534 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = { | ||
535 | /* Voltage mV db */ | ||
536 | { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ | ||
537 | { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ | ||
538 | { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ | ||
539 | { 0x2, 0x98, 0x900F }, /* 400 9.5 */ | ||
540 | { 0x4, 0x98, 0x0018 }, /* 600 0.0 */ | ||
541 | { 0x4, 0x98, 0x3015 }, /* 600 3.5 */ | ||
542 | { 0x4, 0x98, 0x6012 }, /* 600 6.0 */ | ||
543 | { 0x5, 0x76, 0x0018 }, /* 800 0.0 */ | ||
544 | { 0x5, 0x76, 0x3015 }, /* 800 3.5 */ | ||
545 | { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ | ||
546 | }; | ||
547 | |||
548 | /* FIXME - After table is updated in Bspec */ | ||
549 | /* Voltage Swing Programming for VccIO 0.95V for eDP */ | ||
550 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = { | ||
551 | /* Voltage mV db */ | ||
552 | { 0x0, 0x00, 0x00 }, /* 200 0.0 */ | ||
553 | { 0x0, 0x00, 0x00 }, /* 200 1.5 */ | ||
554 | { 0x0, 0x00, 0x00 }, /* 200 4.0 */ | ||
555 | { 0x0, 0x00, 0x00 }, /* 200 6.0 */ | ||
556 | { 0x0, 0x00, 0x00 }, /* 250 0.0 */ | ||
557 | { 0x0, 0x00, 0x00 }, /* 250 1.5 */ | ||
558 | { 0x0, 0x00, 0x00 }, /* 250 4.0 */ | ||
559 | { 0x0, 0x00, 0x00 }, /* 300 0.0 */ | ||
560 | { 0x0, 0x00, 0x00 }, /* 300 1.5 */ | ||
561 | { 0x0, 0x00, 0x00 }, /* 350 0.0 */ | ||
562 | }; | ||
563 | |||
564 | /* Voltage Swing Programming for VccIO 1.05V for DP */ | ||
565 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = { | ||
566 | /* Voltage mV db */ | ||
567 | { 0x2, 0x98, 0x0018 }, /* 400 0.0 */ | ||
568 | { 0x2, 0x98, 0x3015 }, /* 400 3.5 */ | ||
569 | { 0x2, 0x98, 0x6012 }, /* 400 6.0 */ | ||
570 | { 0x2, 0x98, 0x900F }, /* 400 9.5 */ | ||
571 | { 0x4, 0x98, 0x0018 }, /* 600 0.0 */ | ||
572 | { 0x4, 0x98, 0x3015 }, /* 600 3.5 */ | ||
573 | { 0x4, 0x98, 0x6012 }, /* 600 6.0 */ | ||
574 | { 0x5, 0x71, 0x0018 }, /* 800 0.0 */ | ||
575 | { 0x5, 0x71, 0x3015 }, /* 800 3.5 */ | ||
576 | { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */ | ||
577 | }; | ||
578 | |||
579 | /* FIXME - After table is updated in Bspec */ | ||
580 | /* Voltage Swing Programming for VccIO 1.05V for eDP */ | ||
581 | static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = { | ||
582 | /* Voltage mV db */ | ||
583 | { 0x0, 0x00, 0x00 }, /* 200 0.0 */ | ||
584 | { 0x0, 0x00, 0x00 }, /* 200 1.5 */ | ||
585 | { 0x0, 0x00, 0x00 }, /* 200 4.0 */ | ||
586 | { 0x0, 0x00, 0x00 }, /* 200 6.0 */ | ||
587 | { 0x0, 0x00, 0x00 }, /* 250 0.0 */ | ||
588 | { 0x0, 0x00, 0x00 }, /* 250 1.5 */ | ||
589 | { 0x0, 0x00, 0x00 }, /* 250 4.0 */ | ||
590 | { 0x0, 0x00, 0x00 }, /* 300 0.0 */ | ||
591 | { 0x0, 0x00, 0x00 }, /* 300 1.5 */ | ||
592 | { 0x0, 0x00, 0x00 }, /* 350 0.0 */ | ||
593 | }; | ||
594 | |||
595 | struct icl_mg_phy_ddi_buf_trans { | ||
596 | u32 cri_txdeemph_override_5_0; | ||
597 | u32 cri_txdeemph_override_11_6; | ||
598 | u32 cri_txdeemph_override_17_12; | ||
599 | }; | ||
600 | |||
601 | static const struct icl_mg_phy_ddi_buf_trans icl_mg_phy_ddi_translations[] = { | ||
602 | /* Voltage swing pre-emphasis */ | ||
603 | { 0x0, 0x1B, 0x00 }, /* 0 0 */ | ||
604 | { 0x0, 0x23, 0x08 }, /* 0 1 */ | ||
605 | { 0x0, 0x2D, 0x12 }, /* 0 2 */ | ||
606 | { 0x0, 0x00, 0x00 }, /* 0 3 */ | ||
607 | { 0x0, 0x23, 0x00 }, /* 1 0 */ | ||
608 | { 0x0, 0x2B, 0x09 }, /* 1 1 */ | ||
609 | { 0x0, 0x2E, 0x11 }, /* 1 2 */ | ||
610 | { 0x0, 0x2F, 0x00 }, /* 2 0 */ | ||
611 | { 0x0, 0x33, 0x0C }, /* 2 1 */ | ||
612 | { 0x0, 0x00, 0x00 }, /* 3 0 */ | ||
613 | }; | ||
614 | |||
496 | static const struct ddi_buf_trans * | 615 | static const struct ddi_buf_trans * |
497 | bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) | 616 | bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) |
498 | { | 617 | { |
@@ -875,7 +994,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, | |||
875 | 994 | ||
876 | static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) | 995 | static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) |
877 | { | 996 | { |
878 | switch (pll->id) { | 997 | switch (pll->info->id) { |
879 | case DPLL_ID_WRPLL1: | 998 | case DPLL_ID_WRPLL1: |
880 | return PORT_CLK_SEL_WRPLL1; | 999 | return PORT_CLK_SEL_WRPLL1; |
881 | case DPLL_ID_WRPLL2: | 1000 | case DPLL_ID_WRPLL2: |
@@ -889,7 +1008,7 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) | |||
889 | case DPLL_ID_LCPLL_2700: | 1008 | case DPLL_ID_LCPLL_2700: |
890 | return PORT_CLK_SEL_LCPLL_2700; | 1009 | return PORT_CLK_SEL_LCPLL_2700; |
891 | default: | 1010 | default: |
892 | MISSING_CASE(pll->id); | 1011 | MISSING_CASE(pll->info->id); |
893 | return PORT_CLK_SEL_NONE; | 1012 | return PORT_CLK_SEL_NONE; |
894 | } | 1013 | } |
895 | } | 1014 | } |
@@ -2131,7 +2250,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, | |||
2131 | /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ | 2250 | /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ |
2132 | val = I915_READ(DPCLKA_CFGCR0); | 2251 | val = I915_READ(DPCLKA_CFGCR0); |
2133 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); | 2252 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); |
2134 | val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->id, port); | 2253 | val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port); |
2135 | I915_WRITE(DPCLKA_CFGCR0, val); | 2254 | I915_WRITE(DPCLKA_CFGCR0, val); |
2136 | 2255 | ||
2137 | /* | 2256 | /* |
@@ -2148,7 +2267,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, | |||
2148 | 2267 | ||
2149 | val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | | 2268 | val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | |
2150 | DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); | 2269 | DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); |
2151 | val |= (DPLL_CTRL2_DDI_CLK_SEL(pll->id, port) | | 2270 | val |= (DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) | |
2152 | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); | 2271 | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); |
2153 | 2272 | ||
2154 | I915_WRITE(DPLL_CTRL2, val); | 2273 | I915_WRITE(DPLL_CTRL2, val); |
@@ -2205,7 +2324,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, | |||
2205 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); | 2324 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); |
2206 | 2325 | ||
2207 | intel_ddi_init_dp_buf_reg(encoder); | 2326 | intel_ddi_init_dp_buf_reg(encoder); |
2208 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | 2327 | if (!is_mst) |
2328 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | ||
2209 | intel_dp_start_link_train(intel_dp); | 2329 | intel_dp_start_link_train(intel_dp); |
2210 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) | 2330 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) |
2211 | intel_dp_stop_link_train(intel_dp); | 2331 | intel_dp_stop_link_train(intel_dp); |
@@ -2303,12 +2423,15 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, | |||
2303 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 2423 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
2304 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); | 2424 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
2305 | struct intel_dp *intel_dp = &dig_port->dp; | 2425 | struct intel_dp *intel_dp = &dig_port->dp; |
2426 | bool is_mst = intel_crtc_has_type(old_crtc_state, | ||
2427 | INTEL_OUTPUT_DP_MST); | ||
2306 | 2428 | ||
2307 | /* | 2429 | /* |
2308 | * Power down sink before disabling the port, otherwise we end | 2430 | * Power down sink before disabling the port, otherwise we end |
2309 | * up getting interrupts from the sink on detecting link loss. | 2431 | * up getting interrupts from the sink on detecting link loss. |
2310 | */ | 2432 | */ |
2311 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | 2433 | if (!is_mst) |
2434 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | ||
2312 | 2435 | ||
2313 | intel_disable_ddi_buf(encoder); | 2436 | intel_disable_ddi_buf(encoder); |
2314 | 2437 | ||
@@ -2424,12 +2547,14 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder, | |||
2424 | { | 2547 | { |
2425 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 2548 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
2426 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); | 2549 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
2550 | struct drm_connector *connector = conn_state->connector; | ||
2427 | enum port port = encoder->port; | 2551 | enum port port = encoder->port; |
2428 | 2552 | ||
2429 | intel_hdmi_handle_sink_scrambling(encoder, | 2553 | if (!intel_hdmi_handle_sink_scrambling(encoder, connector, |
2430 | conn_state->connector, | 2554 | crtc_state->hdmi_high_tmds_clock_ratio, |
2431 | crtc_state->hdmi_high_tmds_clock_ratio, | 2555 | crtc_state->hdmi_scrambling)) |
2432 | crtc_state->hdmi_scrambling); | 2556 | DRM_ERROR("[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n", |
2557 | connector->base.id, connector->name); | ||
2433 | 2558 | ||
2434 | /* Display WA #1143: skl,kbl,cfl */ | 2559 | /* Display WA #1143: skl,kbl,cfl */ |
2435 | if (IS_GEN9_BC(dev_priv)) { | 2560 | if (IS_GEN9_BC(dev_priv)) { |
@@ -2520,13 +2645,16 @@ static void intel_disable_ddi_hdmi(struct intel_encoder *encoder, | |||
2520 | const struct intel_crtc_state *old_crtc_state, | 2645 | const struct intel_crtc_state *old_crtc_state, |
2521 | const struct drm_connector_state *old_conn_state) | 2646 | const struct drm_connector_state *old_conn_state) |
2522 | { | 2647 | { |
2648 | struct drm_connector *connector = old_conn_state->connector; | ||
2649 | |||
2523 | if (old_crtc_state->has_audio) | 2650 | if (old_crtc_state->has_audio) |
2524 | intel_audio_codec_disable(encoder, | 2651 | intel_audio_codec_disable(encoder, |
2525 | old_crtc_state, old_conn_state); | 2652 | old_crtc_state, old_conn_state); |
2526 | 2653 | ||
2527 | intel_hdmi_handle_sink_scrambling(encoder, | 2654 | if (!intel_hdmi_handle_sink_scrambling(encoder, connector, |
2528 | old_conn_state->connector, | 2655 | false, false)) |
2529 | false, false); | 2656 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n", |
2657 | connector->base.id, connector->name); | ||
2530 | } | 2658 | } |
2531 | 2659 | ||
2532 | static void intel_disable_ddi(struct intel_encoder *encoder, | 2660 | static void intel_disable_ddi(struct intel_encoder *encoder, |
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 3dd350f7b8e6..a32ba72c514e 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c | |||
@@ -83,11 +83,11 @@ static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) | |||
83 | { | 83 | { |
84 | int s; | 84 | int s; |
85 | 85 | ||
86 | drm_printf(p, "slice mask: %04x\n", sseu->slice_mask); | 86 | drm_printf(p, "slice total: %u, mask=%04x\n", |
87 | drm_printf(p, "slice total: %u\n", hweight8(sseu->slice_mask)); | 87 | hweight8(sseu->slice_mask), sseu->slice_mask); |
88 | drm_printf(p, "subslice total: %u\n", sseu_subslice_total(sseu)); | 88 | drm_printf(p, "subslice total: %u\n", sseu_subslice_total(sseu)); |
89 | for (s = 0; s < ARRAY_SIZE(sseu->subslice_mask); s++) { | 89 | for (s = 0; s < sseu->max_slices; s++) { |
90 | drm_printf(p, "slice%d %u subslices mask=%04x\n", | 90 | drm_printf(p, "slice%d: %u subslices, mask=%04x\n", |
91 | s, hweight8(sseu->subslice_mask[s]), | 91 | s, hweight8(sseu->subslice_mask[s]), |
92 | sseu->subslice_mask[s]); | 92 | sseu->subslice_mask[s]); |
93 | } | 93 | } |
@@ -158,6 +158,45 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu) | |||
158 | return total; | 158 | return total; |
159 | } | 159 | } |
160 | 160 | ||
161 | static void gen11_sseu_info_init(struct drm_i915_private *dev_priv) | ||
162 | { | ||
163 | struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; | ||
164 | u8 s_en; | ||
165 | u32 ss_en, ss_en_mask; | ||
166 | u8 eu_en; | ||
167 | int s; | ||
168 | |||
169 | sseu->max_slices = 1; | ||
170 | sseu->max_subslices = 8; | ||
171 | sseu->max_eus_per_subslice = 8; | ||
172 | |||
173 | s_en = I915_READ(GEN11_GT_SLICE_ENABLE) & GEN11_GT_S_ENA_MASK; | ||
174 | ss_en = ~I915_READ(GEN11_GT_SUBSLICE_DISABLE); | ||
175 | ss_en_mask = BIT(sseu->max_subslices) - 1; | ||
176 | eu_en = ~(I915_READ(GEN11_EU_DISABLE) & GEN11_EU_DIS_MASK); | ||
177 | |||
178 | for (s = 0; s < sseu->max_slices; s++) { | ||
179 | if (s_en & BIT(s)) { | ||
180 | int ss_idx = sseu->max_subslices * s; | ||
181 | int ss; | ||
182 | |||
183 | sseu->slice_mask |= BIT(s); | ||
184 | sseu->subslice_mask[s] = (ss_en >> ss_idx) & ss_en_mask; | ||
185 | for (ss = 0; ss < sseu->max_subslices; ss++) { | ||
186 | if (sseu->subslice_mask[s] & BIT(ss)) | ||
187 | sseu_set_eus(sseu, s, ss, eu_en); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | sseu->eu_per_subslice = hweight8(eu_en); | ||
192 | sseu->eu_total = compute_eu_total(sseu); | ||
193 | |||
194 | /* ICL has no power gating restrictions. */ | ||
195 | sseu->has_slice_pg = 1; | ||
196 | sseu->has_subslice_pg = 1; | ||
197 | sseu->has_eu_pg = 1; | ||
198 | } | ||
199 | |||
161 | static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) | 200 | static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) |
162 | { | 201 | { |
163 | struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; | 202 | struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; |
@@ -557,6 +596,52 @@ static u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) | |||
557 | return base_freq + frac_freq; | 596 | return base_freq + frac_freq; |
558 | } | 597 | } |
559 | 598 | ||
599 | static u32 gen10_get_crystal_clock_freq(struct drm_i915_private *dev_priv, | ||
600 | u32 rpm_config_reg) | ||
601 | { | ||
602 | u32 f19_2_mhz = 19200; | ||
603 | u32 f24_mhz = 24000; | ||
604 | u32 crystal_clock = (rpm_config_reg & | ||
605 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | ||
606 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | ||
607 | |||
608 | switch (crystal_clock) { | ||
609 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | ||
610 | return f19_2_mhz; | ||
611 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | ||
612 | return f24_mhz; | ||
613 | default: | ||
614 | MISSING_CASE(crystal_clock); | ||
615 | return 0; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static u32 gen11_get_crystal_clock_freq(struct drm_i915_private *dev_priv, | ||
620 | u32 rpm_config_reg) | ||
621 | { | ||
622 | u32 f19_2_mhz = 19200; | ||
623 | u32 f24_mhz = 24000; | ||
624 | u32 f25_mhz = 25000; | ||
625 | u32 f38_4_mhz = 38400; | ||
626 | u32 crystal_clock = (rpm_config_reg & | ||
627 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | ||
628 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | ||
629 | |||
630 | switch (crystal_clock) { | ||
631 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | ||
632 | return f24_mhz; | ||
633 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | ||
634 | return f19_2_mhz; | ||
635 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ: | ||
636 | return f38_4_mhz; | ||
637 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ: | ||
638 | return f25_mhz; | ||
639 | default: | ||
640 | MISSING_CASE(crystal_clock); | ||
641 | return 0; | ||
642 | } | ||
643 | } | ||
644 | |||
560 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) | 645 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) |
561 | { | 646 | { |
562 | u32 f12_5_mhz = 12500; | 647 | u32 f12_5_mhz = 12500; |
@@ -597,10 +682,9 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) | |||
597 | } | 682 | } |
598 | 683 | ||
599 | return freq; | 684 | return freq; |
600 | } else if (INTEL_GEN(dev_priv) <= 10) { | 685 | } else if (INTEL_GEN(dev_priv) <= 11) { |
601 | u32 ctc_reg = I915_READ(CTC_MODE); | 686 | u32 ctc_reg = I915_READ(CTC_MODE); |
602 | u32 freq = 0; | 687 | u32 freq = 0; |
603 | u32 rpm_config_reg = 0; | ||
604 | 688 | ||
605 | /* First figure out the reference frequency. There are 2 ways | 689 | /* First figure out the reference frequency. There are 2 ways |
606 | * we can compute the frequency, either through the | 690 | * we can compute the frequency, either through the |
@@ -610,20 +694,14 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) | |||
610 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | 694 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { |
611 | freq = read_reference_ts_freq(dev_priv); | 695 | freq = read_reference_ts_freq(dev_priv); |
612 | } else { | 696 | } else { |
613 | u32 crystal_clock; | 697 | u32 rpm_config_reg = I915_READ(RPM_CONFIG0); |
614 | 698 | ||
615 | rpm_config_reg = I915_READ(RPM_CONFIG0); | 699 | if (INTEL_GEN(dev_priv) <= 10) |
616 | crystal_clock = (rpm_config_reg & | 700 | freq = gen10_get_crystal_clock_freq(dev_priv, |
617 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | 701 | rpm_config_reg); |
618 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | 702 | else |
619 | switch (crystal_clock) { | 703 | freq = gen11_get_crystal_clock_freq(dev_priv, |
620 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | 704 | rpm_config_reg); |
621 | freq = f19_2_mhz; | ||
622 | break; | ||
623 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | ||
624 | freq = f24_mhz; | ||
625 | break; | ||
626 | } | ||
627 | 705 | ||
628 | /* Now figure out how the command stream's timestamp | 706 | /* Now figure out how the command stream's timestamp |
629 | * register increments from this frequency (it might | 707 | * register increments from this frequency (it might |
@@ -768,8 +846,10 @@ void intel_device_info_runtime_init(struct intel_device_info *info) | |||
768 | broadwell_sseu_info_init(dev_priv); | 846 | broadwell_sseu_info_init(dev_priv); |
769 | else if (INTEL_GEN(dev_priv) == 9) | 847 | else if (INTEL_GEN(dev_priv) == 9) |
770 | gen9_sseu_info_init(dev_priv); | 848 | gen9_sseu_info_init(dev_priv); |
771 | else if (INTEL_GEN(dev_priv) >= 10) | 849 | else if (INTEL_GEN(dev_priv) == 10) |
772 | gen10_sseu_info_init(dev_priv); | 850 | gen10_sseu_info_init(dev_priv); |
851 | else if (INTEL_INFO(dev_priv)->gen >= 11) | ||
852 | gen11_sseu_info_init(dev_priv); | ||
773 | 853 | ||
774 | /* Initialize command stream timestamp frequency */ | 854 | /* Initialize command stream timestamp frequency */ |
775 | info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); | 855 | info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); |
@@ -780,3 +860,50 @@ void intel_driver_caps_print(const struct intel_driver_caps *caps, | |||
780 | { | 860 | { |
781 | drm_printf(p, "scheduler: %x\n", caps->scheduler); | 861 | drm_printf(p, "scheduler: %x\n", caps->scheduler); |
782 | } | 862 | } |
863 | |||
864 | /* | ||
865 | * Determine which engines are fused off in our particular hardware. Since the | ||
866 | * fuse register is in the blitter powerwell, we need forcewake to be ready at | ||
867 | * this point (but later we need to prune the forcewake domains for engines that | ||
868 | * are indeed fused off). | ||
869 | */ | ||
870 | void intel_device_info_init_mmio(struct drm_i915_private *dev_priv) | ||
871 | { | ||
872 | struct intel_device_info *info = mkwrite_device_info(dev_priv); | ||
873 | u8 vdbox_disable, vebox_disable; | ||
874 | u32 media_fuse; | ||
875 | int i; | ||
876 | |||
877 | if (INTEL_GEN(dev_priv) < 11) | ||
878 | return; | ||
879 | |||
880 | media_fuse = I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE); | ||
881 | |||
882 | vdbox_disable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK; | ||
883 | vebox_disable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >> | ||
884 | GEN11_GT_VEBOX_DISABLE_SHIFT; | ||
885 | |||
886 | DRM_DEBUG_DRIVER("vdbox disable: %04x\n", vdbox_disable); | ||
887 | for (i = 0; i < I915_MAX_VCS; i++) { | ||
888 | if (!HAS_ENGINE(dev_priv, _VCS(i))) | ||
889 | continue; | ||
890 | |||
891 | if (!(BIT(i) & vdbox_disable)) | ||
892 | continue; | ||
893 | |||
894 | info->ring_mask &= ~ENGINE_MASK(_VCS(i)); | ||
895 | DRM_DEBUG_DRIVER("vcs%u fused off\n", i); | ||
896 | } | ||
897 | |||
898 | DRM_DEBUG_DRIVER("vebox disable: %04x\n", vebox_disable); | ||
899 | for (i = 0; i < I915_MAX_VECS; i++) { | ||
900 | if (!HAS_ENGINE(dev_priv, _VECS(i))) | ||
901 | continue; | ||
902 | |||
903 | if (!(BIT(i) & vebox_disable)) | ||
904 | continue; | ||
905 | |||
906 | info->ring_mask &= ~ENGINE_MASK(_VECS(i)); | ||
907 | DRM_DEBUG_DRIVER("vecs%u fused off\n", i); | ||
908 | } | ||
909 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 0835752c8b22..933e31669557 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h | |||
@@ -114,7 +114,7 @@ enum intel_platform { | |||
114 | func(has_ipc); | 114 | func(has_ipc); |
115 | 115 | ||
116 | #define GEN_MAX_SLICES (6) /* CNL upper bound */ | 116 | #define GEN_MAX_SLICES (6) /* CNL upper bound */ |
117 | #define GEN_MAX_SUBSLICES (7) | 117 | #define GEN_MAX_SUBSLICES (8) /* ICL upper bound */ |
118 | 118 | ||
119 | struct sseu_dev_info { | 119 | struct sseu_dev_info { |
120 | u8 slice_mask; | 120 | u8 slice_mask; |
@@ -247,6 +247,8 @@ void intel_device_info_dump_runtime(const struct intel_device_info *info, | |||
247 | void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, | 247 | void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, |
248 | struct drm_printer *p); | 248 | struct drm_printer *p); |
249 | 249 | ||
250 | void intel_device_info_init_mmio(struct drm_i915_private *dev_priv); | ||
251 | |||
250 | void intel_driver_caps_print(const struct intel_driver_caps *caps, | 252 | void intel_driver_caps_print(const struct intel_driver_caps *caps, |
251 | struct drm_printer *p); | 253 | struct drm_printer *p); |
252 | 254 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 182f9bf98484..020900e08d42 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -488,6 +488,21 @@ static const struct intel_limit intel_limits_bxt = { | |||
488 | .p2 = { .p2_slow = 1, .p2_fast = 20 }, | 488 | .p2 = { .p2_slow = 1, .p2_fast = 20 }, |
489 | }; | 489 | }; |
490 | 490 | ||
491 | static void | ||
492 | skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable) | ||
493 | { | ||
494 | if (IS_SKYLAKE(dev_priv)) | ||
495 | return; | ||
496 | |||
497 | if (enable) | ||
498 | I915_WRITE(CLKGATE_DIS_PSL(pipe), | ||
499 | DUPS1_GATING_DIS | DUPS2_GATING_DIS); | ||
500 | else | ||
501 | I915_WRITE(CLKGATE_DIS_PSL(pipe), | ||
502 | I915_READ(CLKGATE_DIS_PSL(pipe)) & | ||
503 | ~(DUPS1_GATING_DIS | DUPS2_GATING_DIS)); | ||
504 | } | ||
505 | |||
491 | static bool | 506 | static bool |
492 | needs_modeset(const struct drm_crtc_state *state) | 507 | needs_modeset(const struct drm_crtc_state *state) |
493 | { | 508 | { |
@@ -2657,11 +2672,13 @@ static int i9xx_format_to_fourcc(int format) | |||
2657 | } | 2672 | } |
2658 | } | 2673 | } |
2659 | 2674 | ||
2660 | static int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) | 2675 | int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) |
2661 | { | 2676 | { |
2662 | switch (format) { | 2677 | switch (format) { |
2663 | case PLANE_CTL_FORMAT_RGB_565: | 2678 | case PLANE_CTL_FORMAT_RGB_565: |
2664 | return DRM_FORMAT_RGB565; | 2679 | return DRM_FORMAT_RGB565; |
2680 | case PLANE_CTL_FORMAT_NV12: | ||
2681 | return DRM_FORMAT_NV12; | ||
2665 | default: | 2682 | default: |
2666 | case PLANE_CTL_FORMAT_XRGB_8888: | 2683 | case PLANE_CTL_FORMAT_XRGB_8888: |
2667 | if (rgb_order) { | 2684 | if (rgb_order) { |
@@ -2858,6 +2875,9 @@ valid_fb: | |||
2858 | return; | 2875 | return; |
2859 | } | 2876 | } |
2860 | 2877 | ||
2878 | obj = intel_fb_obj(fb); | ||
2879 | intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | ||
2880 | |||
2861 | plane_state->src_x = 0; | 2881 | plane_state->src_x = 0; |
2862 | plane_state->src_y = 0; | 2882 | plane_state->src_y = 0; |
2863 | plane_state->src_w = fb->width << 16; | 2883 | plane_state->src_w = fb->width << 16; |
@@ -2871,7 +2891,6 @@ valid_fb: | |||
2871 | intel_state->base.src = drm_plane_state_src(plane_state); | 2891 | intel_state->base.src = drm_plane_state_src(plane_state); |
2872 | intel_state->base.dst = drm_plane_state_dest(plane_state); | 2892 | intel_state->base.dst = drm_plane_state_dest(plane_state); |
2873 | 2893 | ||
2874 | obj = intel_fb_obj(fb); | ||
2875 | if (i915_gem_object_is_tiled(obj)) | 2894 | if (i915_gem_object_is_tiled(obj)) |
2876 | dev_priv->preserve_bios_swizzle = true; | 2895 | dev_priv->preserve_bios_swizzle = true; |
2877 | 2896 | ||
@@ -3464,6 +3483,8 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format) | |||
3464 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY; | 3483 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY; |
3465 | case DRM_FORMAT_VYUY: | 3484 | case DRM_FORMAT_VYUY: |
3466 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY; | 3485 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY; |
3486 | case DRM_FORMAT_NV12: | ||
3487 | return PLANE_CTL_FORMAT_NV12; | ||
3467 | default: | 3488 | default: |
3468 | MISSING_CASE(pixel_format); | 3489 | MISSING_CASE(pixel_format); |
3469 | } | 3490 | } |
@@ -3611,6 +3632,11 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |||
3611 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); | 3632 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); |
3612 | 3633 | ||
3613 | if (intel_format_is_yuv(fb->format->format)) { | 3634 | if (intel_format_is_yuv(fb->format->format)) { |
3635 | if (fb->format->format == DRM_FORMAT_NV12) { | ||
3636 | plane_color_ctl |= | ||
3637 | PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; | ||
3638 | goto out; | ||
3639 | } | ||
3614 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | 3640 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) |
3615 | plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; | 3641 | plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; |
3616 | else | 3642 | else |
@@ -3619,7 +3645,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |||
3619 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | 3645 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) |
3620 | plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; | 3646 | plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; |
3621 | } | 3647 | } |
3622 | 3648 | out: | |
3623 | return plane_color_ctl; | 3649 | return plane_color_ctl; |
3624 | } | 3650 | } |
3625 | 3651 | ||
@@ -3675,7 +3701,6 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) | |||
3675 | struct drm_atomic_state *state; | 3701 | struct drm_atomic_state *state; |
3676 | int ret; | 3702 | int ret; |
3677 | 3703 | ||
3678 | |||
3679 | /* reset doesn't touch the display */ | 3704 | /* reset doesn't touch the display */ |
3680 | if (!i915_modparams.force_reset_modeset_test && | 3705 | if (!i915_modparams.force_reset_modeset_test && |
3681 | !gpu_reset_clobbers_display(dev_priv)) | 3706 | !gpu_reset_clobbers_display(dev_priv)) |
@@ -3729,19 +3754,17 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) | |||
3729 | { | 3754 | { |
3730 | struct drm_device *dev = &dev_priv->drm; | 3755 | struct drm_device *dev = &dev_priv->drm; |
3731 | struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; | 3756 | struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; |
3732 | struct drm_atomic_state *state = dev_priv->modeset_restore_state; | 3757 | struct drm_atomic_state *state; |
3733 | int ret; | 3758 | int ret; |
3734 | 3759 | ||
3735 | /* reset doesn't touch the display */ | 3760 | /* reset doesn't touch the display */ |
3736 | if (!i915_modparams.force_reset_modeset_test && | 3761 | if (!test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags)) |
3737 | !gpu_reset_clobbers_display(dev_priv)) | ||
3738 | return; | 3762 | return; |
3739 | 3763 | ||
3764 | state = fetch_and_zero(&dev_priv->modeset_restore_state); | ||
3740 | if (!state) | 3765 | if (!state) |
3741 | goto unlock; | 3766 | goto unlock; |
3742 | 3767 | ||
3743 | dev_priv->modeset_restore_state = NULL; | ||
3744 | |||
3745 | /* reset doesn't touch the display */ | 3768 | /* reset doesn't touch the display */ |
3746 | if (!gpu_reset_clobbers_display(dev_priv)) { | 3769 | if (!gpu_reset_clobbers_display(dev_priv)) { |
3747 | /* for testing only restore the display */ | 3770 | /* for testing only restore the display */ |
@@ -4703,7 +4726,9 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) | |||
4703 | static int | 4726 | static int |
4704 | skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, | 4727 | skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, |
4705 | unsigned int scaler_user, int *scaler_id, | 4728 | unsigned int scaler_user, int *scaler_id, |
4706 | int src_w, int src_h, int dst_w, int dst_h) | 4729 | int src_w, int src_h, int dst_w, int dst_h, |
4730 | bool plane_scaler_check, | ||
4731 | uint32_t pixel_format) | ||
4707 | { | 4732 | { |
4708 | struct intel_crtc_scaler_state *scaler_state = | 4733 | struct intel_crtc_scaler_state *scaler_state = |
4709 | &crtc_state->scaler_state; | 4734 | &crtc_state->scaler_state; |
@@ -4721,6 +4746,10 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, | |||
4721 | */ | 4746 | */ |
4722 | need_scaling = src_w != dst_w || src_h != dst_h; | 4747 | need_scaling = src_w != dst_w || src_h != dst_h; |
4723 | 4748 | ||
4749 | if (plane_scaler_check) | ||
4750 | if (pixel_format == DRM_FORMAT_NV12) | ||
4751 | need_scaling = true; | ||
4752 | |||
4724 | if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX) | 4753 | if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX) |
4725 | need_scaling = true; | 4754 | need_scaling = true; |
4726 | 4755 | ||
@@ -4760,12 +4789,22 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, | |||
4760 | return 0; | 4789 | return 0; |
4761 | } | 4790 | } |
4762 | 4791 | ||
4792 | if (plane_scaler_check && pixel_format == DRM_FORMAT_NV12 && | ||
4793 | (src_h < SKL_MIN_YUV_420_SRC_H || (src_w % 4) != 0 || | ||
4794 | (src_h % 4) != 0)) { | ||
4795 | DRM_DEBUG_KMS("NV12: src dimensions not met\n"); | ||
4796 | return -EINVAL; | ||
4797 | } | ||
4798 | |||
4763 | /* range checks */ | 4799 | /* range checks */ |
4764 | if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H || | 4800 | if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H || |
4765 | dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || | 4801 | dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || |
4766 | 4802 | (IS_GEN11(dev_priv) && | |
4767 | src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || | 4803 | (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H || |
4768 | dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H) { | 4804 | dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) || |
4805 | (!IS_GEN11(dev_priv) && | ||
4806 | (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || | ||
4807 | dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) { | ||
4769 | DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u " | 4808 | DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u " |
4770 | "size is out of scaler range\n", | 4809 | "size is out of scaler range\n", |
4771 | intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h); | 4810 | intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h); |
@@ -4796,9 +4835,10 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) | |||
4796 | const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode; | 4835 | const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode; |
4797 | 4836 | ||
4798 | return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, | 4837 | return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, |
4799 | &state->scaler_state.scaler_id, | 4838 | &state->scaler_state.scaler_id, |
4800 | state->pipe_src_w, state->pipe_src_h, | 4839 | state->pipe_src_w, state->pipe_src_h, |
4801 | adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay); | 4840 | adjusted_mode->crtc_hdisplay, |
4841 | adjusted_mode->crtc_vdisplay, false, 0); | ||
4802 | } | 4842 | } |
4803 | 4843 | ||
4804 | /** | 4844 | /** |
@@ -4827,7 +4867,8 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, | |||
4827 | drm_rect_width(&plane_state->base.src) >> 16, | 4867 | drm_rect_width(&plane_state->base.src) >> 16, |
4828 | drm_rect_height(&plane_state->base.src) >> 16, | 4868 | drm_rect_height(&plane_state->base.src) >> 16, |
4829 | drm_rect_width(&plane_state->base.dst), | 4869 | drm_rect_width(&plane_state->base.dst), |
4830 | drm_rect_height(&plane_state->base.dst)); | 4870 | drm_rect_height(&plane_state->base.dst), |
4871 | fb ? true : false, fb ? fb->format->format : 0); | ||
4831 | 4872 | ||
4832 | if (ret || plane_state->scaler_id < 0) | 4873 | if (ret || plane_state->scaler_id < 0) |
4833 | return ret; | 4874 | return ret; |
@@ -4853,6 +4894,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, | |||
4853 | case DRM_FORMAT_YVYU: | 4894 | case DRM_FORMAT_YVYU: |
4854 | case DRM_FORMAT_UYVY: | 4895 | case DRM_FORMAT_UYVY: |
4855 | case DRM_FORMAT_VYUY: | 4896 | case DRM_FORMAT_VYUY: |
4897 | case DRM_FORMAT_NV12: | ||
4856 | break; | 4898 | break; |
4857 | default: | 4899 | default: |
4858 | DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", | 4900 | DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", |
@@ -5099,13 +5141,15 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s | |||
5099 | static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) | 5141 | static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) |
5100 | { | 5142 | { |
5101 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | 5143 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); |
5144 | struct drm_device *dev = crtc->base.dev; | ||
5145 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
5102 | struct drm_atomic_state *old_state = old_crtc_state->base.state; | 5146 | struct drm_atomic_state *old_state = old_crtc_state->base.state; |
5103 | struct intel_crtc_state *pipe_config = | 5147 | struct intel_crtc_state *pipe_config = |
5104 | intel_atomic_get_new_crtc_state(to_intel_atomic_state(old_state), | 5148 | intel_atomic_get_new_crtc_state(to_intel_atomic_state(old_state), |
5105 | crtc); | 5149 | crtc); |
5106 | struct drm_plane *primary = crtc->base.primary; | 5150 | struct drm_plane *primary = crtc->base.primary; |
5107 | struct drm_plane_state *old_pri_state = | 5151 | struct drm_plane_state *old_primary_state = |
5108 | drm_atomic_get_existing_plane_state(old_state, primary); | 5152 | drm_atomic_get_old_plane_state(old_state, primary); |
5109 | 5153 | ||
5110 | intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits); | 5154 | intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits); |
5111 | 5155 | ||
@@ -5115,19 +5159,25 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) | |||
5115 | if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) | 5159 | if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) |
5116 | hsw_enable_ips(pipe_config); | 5160 | hsw_enable_ips(pipe_config); |
5117 | 5161 | ||
5118 | if (old_pri_state) { | 5162 | if (old_primary_state) { |
5119 | struct intel_plane_state *primary_state = | 5163 | struct drm_plane_state *new_primary_state = |
5120 | intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state), | 5164 | drm_atomic_get_new_plane_state(old_state, primary); |
5121 | to_intel_plane(primary)); | 5165 | struct drm_framebuffer *fb = new_primary_state->fb; |
5122 | struct intel_plane_state *old_primary_state = | ||
5123 | to_intel_plane_state(old_pri_state); | ||
5124 | 5166 | ||
5125 | intel_fbc_post_update(crtc); | 5167 | intel_fbc_post_update(crtc); |
5126 | 5168 | ||
5127 | if (primary_state->base.visible && | 5169 | if (new_primary_state->visible && |
5128 | (needs_modeset(&pipe_config->base) || | 5170 | (needs_modeset(&pipe_config->base) || |
5129 | !old_primary_state->base.visible)) | 5171 | !old_primary_state->visible)) |
5130 | intel_post_enable_primary(&crtc->base, pipe_config); | 5172 | intel_post_enable_primary(&crtc->base, pipe_config); |
5173 | |||
5174 | /* Display WA 827 */ | ||
5175 | if ((INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) || | ||
5176 | IS_CANNONLAKE(dev_priv)) { | ||
5177 | if (fb && fb->format->format == DRM_FORMAT_NV12) | ||
5178 | skl_wa_clkgate(dev_priv, crtc->pipe, false); | ||
5179 | } | ||
5180 | |||
5131 | } | 5181 | } |
5132 | } | 5182 | } |
5133 | 5183 | ||
@@ -5139,8 +5189,8 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, | |||
5139 | struct drm_i915_private *dev_priv = to_i915(dev); | 5189 | struct drm_i915_private *dev_priv = to_i915(dev); |
5140 | struct drm_atomic_state *old_state = old_crtc_state->base.state; | 5190 | struct drm_atomic_state *old_state = old_crtc_state->base.state; |
5141 | struct drm_plane *primary = crtc->base.primary; | 5191 | struct drm_plane *primary = crtc->base.primary; |
5142 | struct drm_plane_state *old_pri_state = | 5192 | struct drm_plane_state *old_primary_state = |
5143 | drm_atomic_get_existing_plane_state(old_state, primary); | 5193 | drm_atomic_get_old_plane_state(old_state, primary); |
5144 | bool modeset = needs_modeset(&pipe_config->base); | 5194 | bool modeset = needs_modeset(&pipe_config->base); |
5145 | struct intel_atomic_state *old_intel_state = | 5195 | struct intel_atomic_state *old_intel_state = |
5146 | to_intel_atomic_state(old_state); | 5196 | to_intel_atomic_state(old_state); |
@@ -5148,20 +5198,26 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, | |||
5148 | if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) | 5198 | if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) |
5149 | hsw_disable_ips(old_crtc_state); | 5199 | hsw_disable_ips(old_crtc_state); |
5150 | 5200 | ||
5151 | if (old_pri_state) { | 5201 | if (old_primary_state) { |
5152 | struct intel_plane_state *primary_state = | 5202 | struct intel_plane_state *new_primary_state = |
5153 | intel_atomic_get_new_plane_state(old_intel_state, | 5203 | intel_atomic_get_new_plane_state(old_intel_state, |
5154 | to_intel_plane(primary)); | 5204 | to_intel_plane(primary)); |
5155 | struct intel_plane_state *old_primary_state = | 5205 | struct drm_framebuffer *fb = new_primary_state->base.fb; |
5156 | to_intel_plane_state(old_pri_state); | 5206 | |
5207 | /* Display WA 827 */ | ||
5208 | if ((INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) || | ||
5209 | IS_CANNONLAKE(dev_priv)) { | ||
5210 | if (fb && fb->format->format == DRM_FORMAT_NV12) | ||
5211 | skl_wa_clkgate(dev_priv, crtc->pipe, true); | ||
5212 | } | ||
5157 | 5213 | ||
5158 | intel_fbc_pre_update(crtc, pipe_config, primary_state); | 5214 | intel_fbc_pre_update(crtc, pipe_config, new_primary_state); |
5159 | /* | 5215 | /* |
5160 | * Gen2 reports pipe underruns whenever all planes are disabled. | 5216 | * Gen2 reports pipe underruns whenever all planes are disabled. |
5161 | * So disable underrun reporting before all the planes get disabled. | 5217 | * So disable underrun reporting before all the planes get disabled. |
5162 | */ | 5218 | */ |
5163 | if (IS_GEN2(dev_priv) && old_primary_state->base.visible && | 5219 | if (IS_GEN2(dev_priv) && old_primary_state->visible && |
5164 | (modeset || !primary_state->base.visible)) | 5220 | (modeset || !new_primary_state->base.visible)) |
5165 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); | 5221 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); |
5166 | } | 5222 | } |
5167 | 5223 | ||
@@ -8766,8 +8822,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, | |||
8766 | intel_get_shared_dpll_by_id(dev_priv, pll_id); | 8822 | intel_get_shared_dpll_by_id(dev_priv, pll_id); |
8767 | pll = pipe_config->shared_dpll; | 8823 | pll = pipe_config->shared_dpll; |
8768 | 8824 | ||
8769 | WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, | 8825 | WARN_ON(!pll->info->funcs->get_hw_state(dev_priv, pll, |
8770 | &pipe_config->dpll_hw_state)); | 8826 | &pipe_config->dpll_hw_state)); |
8771 | 8827 | ||
8772 | tmp = pipe_config->dpll_hw_state.dpll; | 8828 | tmp = pipe_config->dpll_hw_state.dpll; |
8773 | pipe_config->pixel_multiplier = | 8829 | pipe_config->pixel_multiplier = |
@@ -9243,8 +9299,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, | |||
9243 | 9299 | ||
9244 | pll = pipe_config->shared_dpll; | 9300 | pll = pipe_config->shared_dpll; |
9245 | if (pll) { | 9301 | if (pll) { |
9246 | WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, | 9302 | WARN_ON(!pll->info->funcs->get_hw_state(dev_priv, pll, |
9247 | &pipe_config->dpll_hw_state)); | 9303 | &pipe_config->dpll_hw_state)); |
9248 | } | 9304 | } |
9249 | 9305 | ||
9250 | /* | 9306 | /* |
@@ -10775,7 +10831,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) | |||
10775 | struct drm_connector_state *connector_state; | 10831 | struct drm_connector_state *connector_state; |
10776 | struct intel_encoder *encoder; | 10832 | struct intel_encoder *encoder; |
10777 | 10833 | ||
10778 | connector_state = drm_atomic_get_existing_connector_state(state, connector); | 10834 | connector_state = drm_atomic_get_new_connector_state(state, connector); |
10779 | if (!connector_state) | 10835 | if (!connector_state) |
10780 | connector_state = connector->state; | 10836 | connector_state = connector->state; |
10781 | 10837 | ||
@@ -11645,11 +11701,11 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv, | |||
11645 | 11701 | ||
11646 | memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); | 11702 | memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); |
11647 | 11703 | ||
11648 | DRM_DEBUG_KMS("%s\n", pll->name); | 11704 | DRM_DEBUG_KMS("%s\n", pll->info->name); |
11649 | 11705 | ||
11650 | active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state); | 11706 | active = pll->info->funcs->get_hw_state(dev_priv, pll, &dpll_hw_state); |
11651 | 11707 | ||
11652 | if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) { | 11708 | if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) { |
11653 | I915_STATE_WARN(!pll->on && pll->active_mask, | 11709 | I915_STATE_WARN(!pll->on && pll->active_mask, |
11654 | "pll in active use but not on in sw tracking\n"); | 11710 | "pll in active use but not on in sw tracking\n"); |
11655 | I915_STATE_WARN(pll->on && !pll->active_mask, | 11711 | I915_STATE_WARN(pll->on && !pll->active_mask, |
@@ -12138,20 +12194,23 @@ static void intel_update_crtc(struct drm_crtc *crtc, | |||
12138 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 12194 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
12139 | struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state); | 12195 | struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state); |
12140 | bool modeset = needs_modeset(new_crtc_state); | 12196 | bool modeset = needs_modeset(new_crtc_state); |
12197 | struct intel_plane_state *new_plane_state = | ||
12198 | intel_atomic_get_new_plane_state(to_intel_atomic_state(state), | ||
12199 | to_intel_plane(crtc->primary)); | ||
12141 | 12200 | ||
12142 | if (modeset) { | 12201 | if (modeset) { |
12143 | update_scanline_offset(intel_crtc); | 12202 | update_scanline_offset(intel_crtc); |
12144 | dev_priv->display.crtc_enable(pipe_config, state); | 12203 | dev_priv->display.crtc_enable(pipe_config, state); |
12204 | |||
12205 | /* vblanks work again, re-enable pipe CRC. */ | ||
12206 | intel_crtc_enable_pipe_crc(intel_crtc); | ||
12145 | } else { | 12207 | } else { |
12146 | intel_pre_plane_update(to_intel_crtc_state(old_crtc_state), | 12208 | intel_pre_plane_update(to_intel_crtc_state(old_crtc_state), |
12147 | pipe_config); | 12209 | pipe_config); |
12148 | } | 12210 | } |
12149 | 12211 | ||
12150 | if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { | 12212 | if (new_plane_state) |
12151 | intel_fbc_enable( | 12213 | intel_fbc_enable(intel_crtc, pipe_config, new_plane_state); |
12152 | intel_crtc, pipe_config, | ||
12153 | to_intel_plane_state(crtc->primary->state)); | ||
12154 | } | ||
12155 | 12214 | ||
12156 | drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); | 12215 | drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); |
12157 | } | 12216 | } |
@@ -12322,6 +12381,13 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) | |||
12322 | 12381 | ||
12323 | if (old_crtc_state->active) { | 12382 | if (old_crtc_state->active) { |
12324 | intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask); | 12383 | intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask); |
12384 | |||
12385 | /* | ||
12386 | * We need to disable pipe CRC before disabling the pipe, | ||
12387 | * or we race against vblank off. | ||
12388 | */ | ||
12389 | intel_crtc_disable_pipe_crc(intel_crtc); | ||
12390 | |||
12325 | dev_priv->display.crtc_disable(to_intel_crtc_state(old_crtc_state), state); | 12391 | dev_priv->display.crtc_disable(to_intel_crtc_state(old_crtc_state), state); |
12326 | intel_crtc->active = false; | 12392 | intel_crtc->active = false; |
12327 | intel_fbc_disable(intel_crtc); | 12393 | intel_fbc_disable(intel_crtc); |
@@ -12725,8 +12791,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
12725 | 12791 | ||
12726 | if (old_obj) { | 12792 | if (old_obj) { |
12727 | struct drm_crtc_state *crtc_state = | 12793 | struct drm_crtc_state *crtc_state = |
12728 | drm_atomic_get_existing_crtc_state(new_state->state, | 12794 | drm_atomic_get_new_crtc_state(new_state->state, |
12729 | plane->state->crtc); | 12795 | plane->state->crtc); |
12730 | 12796 | ||
12731 | /* Big Hammer, we also need to ensure that any pending | 12797 | /* Big Hammer, we also need to ensure that any pending |
12732 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the | 12798 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the |
@@ -12780,6 +12846,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
12780 | if (ret) | 12846 | if (ret) |
12781 | return ret; | 12847 | return ret; |
12782 | 12848 | ||
12849 | intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | ||
12850 | |||
12783 | if (!new_state->fence) { /* implicit fencing */ | 12851 | if (!new_state->fence) { /* implicit fencing */ |
12784 | struct dma_fence *fence; | 12852 | struct dma_fence *fence; |
12785 | 12853 | ||
@@ -12824,11 +12892,13 @@ intel_cleanup_plane_fb(struct drm_plane *plane, | |||
12824 | } | 12892 | } |
12825 | 12893 | ||
12826 | int | 12894 | int |
12827 | skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state) | 12895 | skl_max_scale(struct intel_crtc *intel_crtc, |
12896 | struct intel_crtc_state *crtc_state, | ||
12897 | uint32_t pixel_format) | ||
12828 | { | 12898 | { |
12829 | struct drm_i915_private *dev_priv; | 12899 | struct drm_i915_private *dev_priv; |
12830 | int max_scale; | 12900 | int max_scale, mult; |
12831 | int crtc_clock, max_dotclk; | 12901 | int crtc_clock, max_dotclk, tmpclk1, tmpclk2; |
12832 | 12902 | ||
12833 | if (!intel_crtc || !crtc_state->base.enable) | 12903 | if (!intel_crtc || !crtc_state->base.enable) |
12834 | return DRM_PLANE_HELPER_NO_SCALING; | 12904 | return DRM_PLANE_HELPER_NO_SCALING; |
@@ -12850,8 +12920,10 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state | |||
12850 | * or | 12920 | * or |
12851 | * cdclk/crtc_clock | 12921 | * cdclk/crtc_clock |
12852 | */ | 12922 | */ |
12853 | max_scale = min((1 << 16) * 3 - 1, | 12923 | mult = pixel_format == DRM_FORMAT_NV12 ? 2 : 3; |
12854 | (1 << 8) * ((max_dotclk << 8) / crtc_clock)); | 12924 | tmpclk1 = (1 << 16) * mult - 1; |
12925 | tmpclk2 = (1 << 8) * ((max_dotclk << 8) / crtc_clock); | ||
12926 | max_scale = min(tmpclk1, tmpclk2); | ||
12855 | 12927 | ||
12856 | return max_scale; | 12928 | return max_scale; |
12857 | } | 12929 | } |
@@ -12867,12 +12939,16 @@ intel_check_primary_plane(struct intel_plane *plane, | |||
12867 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; | 12939 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; |
12868 | bool can_position = false; | 12940 | bool can_position = false; |
12869 | int ret; | 12941 | int ret; |
12942 | uint32_t pixel_format = 0; | ||
12870 | 12943 | ||
12871 | if (INTEL_GEN(dev_priv) >= 9) { | 12944 | if (INTEL_GEN(dev_priv) >= 9) { |
12872 | /* use scaler when colorkey is not required */ | 12945 | /* use scaler when colorkey is not required */ |
12873 | if (!state->ckey.flags) { | 12946 | if (!state->ckey.flags) { |
12874 | min_scale = 1; | 12947 | min_scale = 1; |
12875 | max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state); | 12948 | if (state->base.fb) |
12949 | pixel_format = state->base.fb->format->format; | ||
12950 | max_scale = skl_max_scale(to_intel_crtc(crtc), | ||
12951 | crtc_state, pixel_format); | ||
12876 | } | 12952 | } |
12877 | can_position = true; | 12953 | can_position = true; |
12878 | } | 12954 | } |
@@ -12945,10 +13021,25 @@ out: | |||
12945 | intel_cstate); | 13021 | intel_cstate); |
12946 | } | 13022 | } |
12947 | 13023 | ||
13024 | void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, | ||
13025 | struct intel_crtc_state *crtc_state) | ||
13026 | { | ||
13027 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | ||
13028 | |||
13029 | if (!IS_GEN2(dev_priv)) | ||
13030 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); | ||
13031 | |||
13032 | if (crtc_state->has_pch_encoder) { | ||
13033 | enum pipe pch_transcoder = | ||
13034 | intel_crtc_pch_transcoder(crtc); | ||
13035 | |||
13036 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true); | ||
13037 | } | ||
13038 | } | ||
13039 | |||
12948 | static void intel_finish_crtc_commit(struct drm_crtc *crtc, | 13040 | static void intel_finish_crtc_commit(struct drm_crtc *crtc, |
12949 | struct drm_crtc_state *old_crtc_state) | 13041 | struct drm_crtc_state *old_crtc_state) |
12950 | { | 13042 | { |
12951 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | ||
12952 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 13043 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
12953 | struct intel_atomic_state *old_intel_state = | 13044 | struct intel_atomic_state *old_intel_state = |
12954 | to_intel_atomic_state(old_crtc_state->state); | 13045 | to_intel_atomic_state(old_crtc_state->state); |
@@ -12959,17 +13050,8 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, | |||
12959 | 13050 | ||
12960 | if (new_crtc_state->update_pipe && | 13051 | if (new_crtc_state->update_pipe && |
12961 | !needs_modeset(&new_crtc_state->base) && | 13052 | !needs_modeset(&new_crtc_state->base) && |
12962 | old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) { | 13053 | old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) |
12963 | if (!IS_GEN2(dev_priv)) | 13054 | intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state); |
12964 | intel_set_cpu_fifo_underrun_reporting(dev_priv, intel_crtc->pipe, true); | ||
12965 | |||
12966 | if (new_crtc_state->has_pch_encoder) { | ||
12967 | enum pipe pch_transcoder = | ||
12968 | intel_crtc_pch_transcoder(intel_crtc); | ||
12969 | |||
12970 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true); | ||
12971 | } | ||
12972 | } | ||
12973 | } | 13055 | } |
12974 | 13056 | ||
12975 | /** | 13057 | /** |
@@ -13167,8 +13249,9 @@ intel_legacy_cursor_update(struct drm_plane *plane, | |||
13167 | if (ret) | 13249 | if (ret) |
13168 | goto out_unlock; | 13250 | goto out_unlock; |
13169 | 13251 | ||
13170 | old_fb = old_plane_state->fb; | 13252 | intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_FLIP); |
13171 | 13253 | ||
13254 | old_fb = old_plane_state->fb; | ||
13172 | i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), | 13255 | i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), |
13173 | intel_plane->frontbuffer_bit); | 13256 | intel_plane->frontbuffer_bit); |
13174 | 13257 | ||
@@ -13555,10 +13638,17 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
13555 | /* initialize shared scalers */ | 13638 | /* initialize shared scalers */ |
13556 | intel_crtc_init_scalers(intel_crtc, crtc_state); | 13639 | intel_crtc_init_scalers(intel_crtc, crtc_state); |
13557 | 13640 | ||
13558 | BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || | 13641 | BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || |
13559 | dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] != NULL); | 13642 | dev_priv->pipe_to_crtc_mapping[pipe] != NULL); |
13560 | dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] = intel_crtc; | 13643 | dev_priv->pipe_to_crtc_mapping[pipe] = intel_crtc; |
13561 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc; | 13644 | |
13645 | if (INTEL_GEN(dev_priv) < 9) { | ||
13646 | enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; | ||
13647 | |||
13648 | BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || | ||
13649 | dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); | ||
13650 | dev_priv->plane_to_crtc_mapping[i9xx_plane] = intel_crtc; | ||
13651 | } | ||
13562 | 13652 | ||
13563 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); | 13653 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); |
13564 | 13654 | ||
@@ -15103,8 +15193,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) | |||
15103 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { | 15193 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
15104 | struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; | 15194 | struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; |
15105 | 15195 | ||
15106 | pll->on = pll->funcs.get_hw_state(dev_priv, pll, | 15196 | pll->on = pll->info->funcs->get_hw_state(dev_priv, pll, |
15107 | &pll->state.hw_state); | 15197 | &pll->state.hw_state); |
15108 | pll->state.crtc_mask = 0; | 15198 | pll->state.crtc_mask = 0; |
15109 | for_each_intel_crtc(dev, crtc) { | 15199 | for_each_intel_crtc(dev, crtc) { |
15110 | struct intel_crtc_state *crtc_state = | 15200 | struct intel_crtc_state *crtc_state = |
@@ -15117,7 +15207,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) | |||
15117 | pll->active_mask = pll->state.crtc_mask; | 15207 | pll->active_mask = pll->state.crtc_mask; |
15118 | 15208 | ||
15119 | DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n", | 15209 | DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n", |
15120 | pll->name, pll->state.crtc_mask, pll->on); | 15210 | pll->info->name, pll->state.crtc_mask, pll->on); |
15121 | } | 15211 | } |
15122 | 15212 | ||
15123 | for_each_intel_encoder(dev, encoder) { | 15213 | for_each_intel_encoder(dev, encoder) { |
@@ -15291,9 +15381,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev, | |||
15291 | if (!pll->on || pll->active_mask) | 15381 | if (!pll->on || pll->active_mask) |
15292 | continue; | 15382 | continue; |
15293 | 15383 | ||
15294 | DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name); | 15384 | DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", |
15385 | pll->info->name); | ||
15295 | 15386 | ||
15296 | pll->funcs.disable(dev_priv, pll); | 15387 | pll->info->funcs->disable(dev_priv, pll); |
15297 | pll->on = false; | 15388 | pll->on = false; |
15298 | } | 15389 | } |
15299 | 15390 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9a4a51e79fa1..62f82c4298ac 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <drm/i915_drm.h> | 43 | #include <drm/i915_drm.h> |
44 | #include "i915_drv.h" | 44 | #include "i915_drv.h" |
45 | 45 | ||
46 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | ||
47 | #define DP_DPRX_ESI_LEN 14 | 46 | #define DP_DPRX_ESI_LEN 14 |
48 | 47 | ||
49 | /* Compliance test status bits */ | 48 | /* Compliance test status bits */ |
@@ -92,8 +91,6 @@ static const struct dp_link_dpll chv_dpll[] = { | |||
92 | { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, | 91 | { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, |
93 | { 270000, /* m2_int = 27, m2_fraction = 0 */ | 92 | { 270000, /* m2_int = 27, m2_fraction = 0 */ |
94 | { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, | 93 | { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, |
95 | { 540000, /* m2_int = 27, m2_fraction = 0 */ | ||
96 | { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } | ||
97 | }; | 94 | }; |
98 | 95 | ||
99 | /** | 96 | /** |
@@ -2901,10 +2898,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
2901 | } | 2898 | } |
2902 | 2899 | ||
2903 | } else { | 2900 | } else { |
2904 | if (IS_CHERRYVIEW(dev_priv)) | 2901 | *DP &= ~DP_LINK_TRAIN_MASK; |
2905 | *DP &= ~DP_LINK_TRAIN_MASK_CHV; | ||
2906 | else | ||
2907 | *DP &= ~DP_LINK_TRAIN_MASK; | ||
2908 | 2902 | ||
2909 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { | 2903 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
2910 | case DP_TRAINING_PATTERN_DISABLE: | 2904 | case DP_TRAINING_PATTERN_DISABLE: |
@@ -2917,12 +2911,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
2917 | *DP |= DP_LINK_TRAIN_PAT_2; | 2911 | *DP |= DP_LINK_TRAIN_PAT_2; |
2918 | break; | 2912 | break; |
2919 | case DP_TRAINING_PATTERN_3: | 2913 | case DP_TRAINING_PATTERN_3: |
2920 | if (IS_CHERRYVIEW(dev_priv)) { | 2914 | DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); |
2921 | *DP |= DP_LINK_TRAIN_PAT_3_CHV; | 2915 | *DP |= DP_LINK_TRAIN_PAT_2; |
2922 | } else { | ||
2923 | DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); | ||
2924 | *DP |= DP_LINK_TRAIN_PAT_2; | ||
2925 | } | ||
2926 | break; | 2916 | break; |
2927 | } | 2917 | } |
2928 | } | 2918 | } |
@@ -3661,10 +3651,7 @@ intel_dp_link_down(struct intel_encoder *encoder, | |||
3661 | DP &= ~DP_LINK_TRAIN_MASK_CPT; | 3651 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
3662 | DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; | 3652 | DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; |
3663 | } else { | 3653 | } else { |
3664 | if (IS_CHERRYVIEW(dev_priv)) | 3654 | DP &= ~DP_LINK_TRAIN_MASK; |
3665 | DP &= ~DP_LINK_TRAIN_MASK_CHV; | ||
3666 | else | ||
3667 | DP &= ~DP_LINK_TRAIN_MASK; | ||
3668 | DP |= DP_LINK_TRAIN_PAT_IDLE; | 3655 | DP |= DP_LINK_TRAIN_PAT_IDLE; |
3669 | } | 3656 | } |
3670 | I915_WRITE(intel_dp->output_reg, DP); | 3657 | I915_WRITE(intel_dp->output_reg, DP); |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index c3de0918ee13..9e6956c08688 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
@@ -180,9 +180,11 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, | |||
180 | intel_dp->active_mst_links--; | 180 | intel_dp->active_mst_links--; |
181 | 181 | ||
182 | intel_mst->connector = NULL; | 182 | intel_mst->connector = NULL; |
183 | if (intel_dp->active_mst_links == 0) | 183 | if (intel_dp->active_mst_links == 0) { |
184 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | ||
184 | intel_dig_port->base.post_disable(&intel_dig_port->base, | 185 | intel_dig_port->base.post_disable(&intel_dig_port->base, |
185 | old_crtc_state, NULL); | 186 | old_crtc_state, NULL); |
187 | } | ||
186 | 188 | ||
187 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); | 189 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); |
188 | } | 190 | } |
@@ -223,7 +225,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, | |||
223 | 225 | ||
224 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); | 226 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); |
225 | 227 | ||
228 | if (intel_dp->active_mst_links == 0) | ||
229 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | ||
230 | |||
226 | drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); | 231 | drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); |
232 | |||
227 | if (intel_dp->active_mst_links == 0) | 233 | if (intel_dp->active_mst_links == 0) |
228 | intel_dig_port->base.pre_enable(&intel_dig_port->base, | 234 | intel_dig_port->base.pre_enable(&intel_dig_port->base, |
229 | pipe_config, NULL); | 235 | pipe_config, NULL); |
diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index c8e9e44e5981..00b3ab656b06 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c | |||
@@ -380,13 +380,14 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, | |||
380 | * all 1s. Eventually they become accessible as they power up, then | 380 | * all 1s. Eventually they become accessible as they power up, then |
381 | * the reserved bit will give the default 0. Poll on the reserved bit | 381 | * the reserved bit will give the default 0. Poll on the reserved bit |
382 | * becoming 0 to find when the PHY is accessible. | 382 | * becoming 0 to find when the PHY is accessible. |
383 | * HW team confirmed that the time to reach phypowergood status is | 383 | * The flag should get set in 100us according to the HW team, but |
384 | * anywhere between 50 us and 100us. | 384 | * use 1ms due to occasional timeouts observed with that. |
385 | */ | 385 | */ |
386 | if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & | 386 | if (intel_wait_for_register_fw(dev_priv, BXT_PORT_CL1CM_DW0(phy), |
387 | (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { | 387 | PHY_RESERVED | PHY_POWER_GOOD, |
388 | PHY_POWER_GOOD, | ||
389 | 1)) | ||
388 | DRM_ERROR("timeout during PHY%d power on\n", phy); | 390 | DRM_ERROR("timeout during PHY%d power on\n", phy); |
389 | } | ||
390 | 391 | ||
391 | /* Program PLL Rcomp code offset */ | 392 | /* Program PLL Rcomp code offset */ |
392 | val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); | 393 | val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); |
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 51c5ae4e9116..d5e114e9660b 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c | |||
@@ -118,10 +118,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, | |||
118 | if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) | 118 | if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) |
119 | return; | 119 | return; |
120 | 120 | ||
121 | cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state); | 121 | cur_state = pll->info->funcs->get_hw_state(dev_priv, pll, &hw_state); |
122 | I915_STATE_WARN(cur_state != state, | 122 | I915_STATE_WARN(cur_state != state, |
123 | "%s assertion failure (expected %s, current %s)\n", | 123 | "%s assertion failure (expected %s, current %s)\n", |
124 | pll->name, onoff(state), onoff(cur_state)); | 124 | pll->info->name, onoff(state), onoff(cur_state)); |
125 | } | 125 | } |
126 | 126 | ||
127 | /** | 127 | /** |
@@ -143,11 +143,11 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc) | |||
143 | mutex_lock(&dev_priv->dpll_lock); | 143 | mutex_lock(&dev_priv->dpll_lock); |
144 | WARN_ON(!pll->state.crtc_mask); | 144 | WARN_ON(!pll->state.crtc_mask); |
145 | if (!pll->active_mask) { | 145 | if (!pll->active_mask) { |
146 | DRM_DEBUG_DRIVER("setting up %s\n", pll->name); | 146 | DRM_DEBUG_DRIVER("setting up %s\n", pll->info->name); |
147 | WARN_ON(pll->on); | 147 | WARN_ON(pll->on); |
148 | assert_shared_dpll_disabled(dev_priv, pll); | 148 | assert_shared_dpll_disabled(dev_priv, pll); |
149 | 149 | ||
150 | pll->funcs.prepare(dev_priv, pll); | 150 | pll->info->funcs->prepare(dev_priv, pll); |
151 | } | 151 | } |
152 | mutex_unlock(&dev_priv->dpll_lock); | 152 | mutex_unlock(&dev_priv->dpll_lock); |
153 | } | 153 | } |
@@ -179,7 +179,7 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) | |||
179 | pll->active_mask |= crtc_mask; | 179 | pll->active_mask |= crtc_mask; |
180 | 180 | ||
181 | DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n", | 181 | DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n", |
182 | pll->name, pll->active_mask, pll->on, | 182 | pll->info->name, pll->active_mask, pll->on, |
183 | crtc->base.base.id); | 183 | crtc->base.base.id); |
184 | 184 | ||
185 | if (old_mask) { | 185 | if (old_mask) { |
@@ -189,8 +189,8 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) | |||
189 | } | 189 | } |
190 | WARN_ON(pll->on); | 190 | WARN_ON(pll->on); |
191 | 191 | ||
192 | DRM_DEBUG_KMS("enabling %s\n", pll->name); | 192 | DRM_DEBUG_KMS("enabling %s\n", pll->info->name); |
193 | pll->funcs.enable(dev_priv, pll); | 193 | pll->info->funcs->enable(dev_priv, pll); |
194 | pll->on = true; | 194 | pll->on = true; |
195 | 195 | ||
196 | out: | 196 | out: |
@@ -221,7 +221,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) | |||
221 | goto out; | 221 | goto out; |
222 | 222 | ||
223 | DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", | 223 | DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", |
224 | pll->name, pll->active_mask, pll->on, | 224 | pll->info->name, pll->active_mask, pll->on, |
225 | crtc->base.base.id); | 225 | crtc->base.base.id); |
226 | 226 | ||
227 | assert_shared_dpll_enabled(dev_priv, pll); | 227 | assert_shared_dpll_enabled(dev_priv, pll); |
@@ -231,8 +231,8 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) | |||
231 | if (pll->active_mask) | 231 | if (pll->active_mask) |
232 | goto out; | 232 | goto out; |
233 | 233 | ||
234 | DRM_DEBUG_KMS("disabling %s\n", pll->name); | 234 | DRM_DEBUG_KMS("disabling %s\n", pll->info->name); |
235 | pll->funcs.disable(dev_priv, pll); | 235 | pll->info->funcs->disable(dev_priv, pll); |
236 | pll->on = false; | 236 | pll->on = false; |
237 | 237 | ||
238 | out: | 238 | out: |
@@ -263,7 +263,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc, | |||
263 | &shared_dpll[i].hw_state, | 263 | &shared_dpll[i].hw_state, |
264 | sizeof(crtc_state->dpll_hw_state)) == 0) { | 264 | sizeof(crtc_state->dpll_hw_state)) == 0) { |
265 | DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n", | 265 | DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n", |
266 | crtc->base.base.id, crtc->base.name, pll->name, | 266 | crtc->base.base.id, crtc->base.name, |
267 | pll->info->name, | ||
267 | shared_dpll[i].crtc_mask, | 268 | shared_dpll[i].crtc_mask, |
268 | pll->active_mask); | 269 | pll->active_mask); |
269 | return pll; | 270 | return pll; |
@@ -275,7 +276,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc, | |||
275 | pll = &dev_priv->shared_dplls[i]; | 276 | pll = &dev_priv->shared_dplls[i]; |
276 | if (shared_dpll[i].crtc_mask == 0) { | 277 | if (shared_dpll[i].crtc_mask == 0) { |
277 | DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n", | 278 | DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n", |
278 | crtc->base.base.id, crtc->base.name, pll->name); | 279 | crtc->base.base.id, crtc->base.name, |
280 | pll->info->name); | ||
279 | return pll; | 281 | return pll; |
280 | } | 282 | } |
281 | } | 283 | } |
@@ -289,19 +291,19 @@ intel_reference_shared_dpll(struct intel_shared_dpll *pll, | |||
289 | { | 291 | { |
290 | struct intel_shared_dpll_state *shared_dpll; | 292 | struct intel_shared_dpll_state *shared_dpll; |
291 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 293 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
292 | enum intel_dpll_id i = pll->id; | 294 | const enum intel_dpll_id id = pll->info->id; |
293 | 295 | ||
294 | shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); | 296 | shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); |
295 | 297 | ||
296 | if (shared_dpll[i].crtc_mask == 0) | 298 | if (shared_dpll[id].crtc_mask == 0) |
297 | shared_dpll[i].hw_state = | 299 | shared_dpll[id].hw_state = |
298 | crtc_state->dpll_hw_state; | 300 | crtc_state->dpll_hw_state; |
299 | 301 | ||
300 | crtc_state->shared_dpll = pll; | 302 | crtc_state->shared_dpll = pll; |
301 | DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, | 303 | DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->info->name, |
302 | pipe_name(crtc->pipe)); | 304 | pipe_name(crtc->pipe)); |
303 | 305 | ||
304 | shared_dpll[pll->id].crtc_mask |= 1 << crtc->pipe; | 306 | shared_dpll[id].crtc_mask |= 1 << crtc->pipe; |
305 | } | 307 | } |
306 | 308 | ||
307 | /** | 309 | /** |
@@ -341,15 +343,16 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, | |||
341 | struct intel_shared_dpll *pll, | 343 | struct intel_shared_dpll *pll, |
342 | struct intel_dpll_hw_state *hw_state) | 344 | struct intel_dpll_hw_state *hw_state) |
343 | { | 345 | { |
346 | const enum intel_dpll_id id = pll->info->id; | ||
344 | uint32_t val; | 347 | uint32_t val; |
345 | 348 | ||
346 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) | 349 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
347 | return false; | 350 | return false; |
348 | 351 | ||
349 | val = I915_READ(PCH_DPLL(pll->id)); | 352 | val = I915_READ(PCH_DPLL(id)); |
350 | hw_state->dpll = val; | 353 | hw_state->dpll = val; |
351 | hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); | 354 | hw_state->fp0 = I915_READ(PCH_FP0(id)); |
352 | hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); | 355 | hw_state->fp1 = I915_READ(PCH_FP1(id)); |
353 | 356 | ||
354 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); | 357 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); |
355 | 358 | ||
@@ -359,8 +362,10 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, | |||
359 | static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv, | 362 | static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv, |
360 | struct intel_shared_dpll *pll) | 363 | struct intel_shared_dpll *pll) |
361 | { | 364 | { |
362 | I915_WRITE(PCH_FP0(pll->id), pll->state.hw_state.fp0); | 365 | const enum intel_dpll_id id = pll->info->id; |
363 | I915_WRITE(PCH_FP1(pll->id), pll->state.hw_state.fp1); | 366 | |
367 | I915_WRITE(PCH_FP0(id), pll->state.hw_state.fp0); | ||
368 | I915_WRITE(PCH_FP1(id), pll->state.hw_state.fp1); | ||
364 | } | 369 | } |
365 | 370 | ||
366 | static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) | 371 | static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) |
@@ -379,13 +384,15 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) | |||
379 | static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, | 384 | static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, |
380 | struct intel_shared_dpll *pll) | 385 | struct intel_shared_dpll *pll) |
381 | { | 386 | { |
387 | const enum intel_dpll_id id = pll->info->id; | ||
388 | |||
382 | /* PCH refclock must be enabled first */ | 389 | /* PCH refclock must be enabled first */ |
383 | ibx_assert_pch_refclk_enabled(dev_priv); | 390 | ibx_assert_pch_refclk_enabled(dev_priv); |
384 | 391 | ||
385 | I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll); | 392 | I915_WRITE(PCH_DPLL(id), pll->state.hw_state.dpll); |
386 | 393 | ||
387 | /* Wait for the clocks to stabilize. */ | 394 | /* Wait for the clocks to stabilize. */ |
388 | POSTING_READ(PCH_DPLL(pll->id)); | 395 | POSTING_READ(PCH_DPLL(id)); |
389 | udelay(150); | 396 | udelay(150); |
390 | 397 | ||
391 | /* The pixel multiplier can only be updated once the | 398 | /* The pixel multiplier can only be updated once the |
@@ -393,14 +400,15 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, | |||
393 | * | 400 | * |
394 | * So write it again. | 401 | * So write it again. |
395 | */ | 402 | */ |
396 | I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll); | 403 | I915_WRITE(PCH_DPLL(id), pll->state.hw_state.dpll); |
397 | POSTING_READ(PCH_DPLL(pll->id)); | 404 | POSTING_READ(PCH_DPLL(id)); |
398 | udelay(200); | 405 | udelay(200); |
399 | } | 406 | } |
400 | 407 | ||
401 | static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, | 408 | static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, |
402 | struct intel_shared_dpll *pll) | 409 | struct intel_shared_dpll *pll) |
403 | { | 410 | { |
411 | const enum intel_dpll_id id = pll->info->id; | ||
404 | struct drm_device *dev = &dev_priv->drm; | 412 | struct drm_device *dev = &dev_priv->drm; |
405 | struct intel_crtc *crtc; | 413 | struct intel_crtc *crtc; |
406 | 414 | ||
@@ -410,8 +418,8 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, | |||
410 | assert_pch_transcoder_disabled(dev_priv, crtc->pipe); | 418 | assert_pch_transcoder_disabled(dev_priv, crtc->pipe); |
411 | } | 419 | } |
412 | 420 | ||
413 | I915_WRITE(PCH_DPLL(pll->id), 0); | 421 | I915_WRITE(PCH_DPLL(id), 0); |
414 | POSTING_READ(PCH_DPLL(pll->id)); | 422 | POSTING_READ(PCH_DPLL(id)); |
415 | udelay(200); | 423 | udelay(200); |
416 | } | 424 | } |
417 | 425 | ||
@@ -429,7 +437,8 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, | |||
429 | pll = &dev_priv->shared_dplls[i]; | 437 | pll = &dev_priv->shared_dplls[i]; |
430 | 438 | ||
431 | DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", | 439 | DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", |
432 | crtc->base.base.id, crtc->base.name, pll->name); | 440 | crtc->base.base.id, crtc->base.name, |
441 | pll->info->name); | ||
433 | } else { | 442 | } else { |
434 | pll = intel_find_shared_dpll(crtc, crtc_state, | 443 | pll = intel_find_shared_dpll(crtc, crtc_state, |
435 | DPLL_ID_PCH_PLL_A, | 444 | DPLL_ID_PCH_PLL_A, |
@@ -466,8 +475,10 @@ static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { | |||
466 | static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, | 475 | static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, |
467 | struct intel_shared_dpll *pll) | 476 | struct intel_shared_dpll *pll) |
468 | { | 477 | { |
469 | I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll); | 478 | const enum intel_dpll_id id = pll->info->id; |
470 | POSTING_READ(WRPLL_CTL(pll->id)); | 479 | |
480 | I915_WRITE(WRPLL_CTL(id), pll->state.hw_state.wrpll); | ||
481 | POSTING_READ(WRPLL_CTL(id)); | ||
471 | udelay(20); | 482 | udelay(20); |
472 | } | 483 | } |
473 | 484 | ||
@@ -482,11 +493,12 @@ static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv, | |||
482 | static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, | 493 | static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, |
483 | struct intel_shared_dpll *pll) | 494 | struct intel_shared_dpll *pll) |
484 | { | 495 | { |
496 | const enum intel_dpll_id id = pll->info->id; | ||
485 | uint32_t val; | 497 | uint32_t val; |
486 | 498 | ||
487 | val = I915_READ(WRPLL_CTL(pll->id)); | 499 | val = I915_READ(WRPLL_CTL(id)); |
488 | I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); | 500 | I915_WRITE(WRPLL_CTL(id), val & ~WRPLL_PLL_ENABLE); |
489 | POSTING_READ(WRPLL_CTL(pll->id)); | 501 | POSTING_READ(WRPLL_CTL(id)); |
490 | } | 502 | } |
491 | 503 | ||
492 | static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, | 504 | static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, |
@@ -503,12 +515,13 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, | |||
503 | struct intel_shared_dpll *pll, | 515 | struct intel_shared_dpll *pll, |
504 | struct intel_dpll_hw_state *hw_state) | 516 | struct intel_dpll_hw_state *hw_state) |
505 | { | 517 | { |
518 | const enum intel_dpll_id id = pll->info->id; | ||
506 | uint32_t val; | 519 | uint32_t val; |
507 | 520 | ||
508 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) | 521 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
509 | return false; | 522 | return false; |
510 | 523 | ||
511 | val = I915_READ(WRPLL_CTL(pll->id)); | 524 | val = I915_READ(WRPLL_CTL(id)); |
512 | hw_state->wrpll = val; | 525 | hw_state->wrpll = val; |
513 | 526 | ||
514 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); | 527 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); |
@@ -914,13 +927,15 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = { | |||
914 | static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, | 927 | static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, |
915 | struct intel_shared_dpll *pll) | 928 | struct intel_shared_dpll *pll) |
916 | { | 929 | { |
930 | const enum intel_dpll_id id = pll->info->id; | ||
917 | uint32_t val; | 931 | uint32_t val; |
918 | 932 | ||
919 | val = I915_READ(DPLL_CTRL1); | 933 | val = I915_READ(DPLL_CTRL1); |
920 | 934 | ||
921 | val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) | | 935 | val &= ~(DPLL_CTRL1_HDMI_MODE(id) | |
922 | DPLL_CTRL1_LINK_RATE_MASK(pll->id)); | 936 | DPLL_CTRL1_SSC(id) | |
923 | val |= pll->state.hw_state.ctrl1 << (pll->id * 6); | 937 | DPLL_CTRL1_LINK_RATE_MASK(id)); |
938 | val |= pll->state.hw_state.ctrl1 << (id * 6); | ||
924 | 939 | ||
925 | I915_WRITE(DPLL_CTRL1, val); | 940 | I915_WRITE(DPLL_CTRL1, val); |
926 | POSTING_READ(DPLL_CTRL1); | 941 | POSTING_READ(DPLL_CTRL1); |
@@ -930,24 +945,25 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, | |||
930 | struct intel_shared_dpll *pll) | 945 | struct intel_shared_dpll *pll) |
931 | { | 946 | { |
932 | const struct skl_dpll_regs *regs = skl_dpll_regs; | 947 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
948 | const enum intel_dpll_id id = pll->info->id; | ||
933 | 949 | ||
934 | skl_ddi_pll_write_ctrl1(dev_priv, pll); | 950 | skl_ddi_pll_write_ctrl1(dev_priv, pll); |
935 | 951 | ||
936 | I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1); | 952 | I915_WRITE(regs[id].cfgcr1, pll->state.hw_state.cfgcr1); |
937 | I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2); | 953 | I915_WRITE(regs[id].cfgcr2, pll->state.hw_state.cfgcr2); |
938 | POSTING_READ(regs[pll->id].cfgcr1); | 954 | POSTING_READ(regs[id].cfgcr1); |
939 | POSTING_READ(regs[pll->id].cfgcr2); | 955 | POSTING_READ(regs[id].cfgcr2); |
940 | 956 | ||
941 | /* the enable bit is always bit 31 */ | 957 | /* the enable bit is always bit 31 */ |
942 | I915_WRITE(regs[pll->id].ctl, | 958 | I915_WRITE(regs[id].ctl, |
943 | I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); | 959 | I915_READ(regs[id].ctl) | LCPLL_PLL_ENABLE); |
944 | 960 | ||
945 | if (intel_wait_for_register(dev_priv, | 961 | if (intel_wait_for_register(dev_priv, |
946 | DPLL_STATUS, | 962 | DPLL_STATUS, |
947 | DPLL_LOCK(pll->id), | 963 | DPLL_LOCK(id), |
948 | DPLL_LOCK(pll->id), | 964 | DPLL_LOCK(id), |
949 | 5)) | 965 | 5)) |
950 | DRM_ERROR("DPLL %d not locked\n", pll->id); | 966 | DRM_ERROR("DPLL %d not locked\n", id); |
951 | } | 967 | } |
952 | 968 | ||
953 | static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv, | 969 | static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv, |
@@ -960,11 +976,12 @@ static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, | |||
960 | struct intel_shared_dpll *pll) | 976 | struct intel_shared_dpll *pll) |
961 | { | 977 | { |
962 | const struct skl_dpll_regs *regs = skl_dpll_regs; | 978 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
979 | const enum intel_dpll_id id = pll->info->id; | ||
963 | 980 | ||
964 | /* the enable bit is always bit 31 */ | 981 | /* the enable bit is always bit 31 */ |
965 | I915_WRITE(regs[pll->id].ctl, | 982 | I915_WRITE(regs[id].ctl, |
966 | I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); | 983 | I915_READ(regs[id].ctl) & ~LCPLL_PLL_ENABLE); |
967 | POSTING_READ(regs[pll->id].ctl); | 984 | POSTING_READ(regs[id].ctl); |
968 | } | 985 | } |
969 | 986 | ||
970 | static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv, | 987 | static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv, |
@@ -978,6 +995,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, | |||
978 | { | 995 | { |
979 | uint32_t val; | 996 | uint32_t val; |
980 | const struct skl_dpll_regs *regs = skl_dpll_regs; | 997 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
998 | const enum intel_dpll_id id = pll->info->id; | ||
981 | bool ret; | 999 | bool ret; |
982 | 1000 | ||
983 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) | 1001 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
@@ -985,17 +1003,17 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, | |||
985 | 1003 | ||
986 | ret = false; | 1004 | ret = false; |
987 | 1005 | ||
988 | val = I915_READ(regs[pll->id].ctl); | 1006 | val = I915_READ(regs[id].ctl); |
989 | if (!(val & LCPLL_PLL_ENABLE)) | 1007 | if (!(val & LCPLL_PLL_ENABLE)) |
990 | goto out; | 1008 | goto out; |
991 | 1009 | ||
992 | val = I915_READ(DPLL_CTRL1); | 1010 | val = I915_READ(DPLL_CTRL1); |
993 | hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; | 1011 | hw_state->ctrl1 = (val >> (id * 6)) & 0x3f; |
994 | 1012 | ||
995 | /* avoid reading back stale values if HDMI mode is not enabled */ | 1013 | /* avoid reading back stale values if HDMI mode is not enabled */ |
996 | if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) { | 1014 | if (val & DPLL_CTRL1_HDMI_MODE(id)) { |
997 | hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); | 1015 | hw_state->cfgcr1 = I915_READ(regs[id].cfgcr1); |
998 | hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); | 1016 | hw_state->cfgcr2 = I915_READ(regs[id].cfgcr2); |
999 | } | 1017 | } |
1000 | ret = true; | 1018 | ret = true; |
1001 | 1019 | ||
@@ -1011,6 +1029,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, | |||
1011 | { | 1029 | { |
1012 | uint32_t val; | 1030 | uint32_t val; |
1013 | const struct skl_dpll_regs *regs = skl_dpll_regs; | 1031 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
1032 | const enum intel_dpll_id id = pll->info->id; | ||
1014 | bool ret; | 1033 | bool ret; |
1015 | 1034 | ||
1016 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) | 1035 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
@@ -1019,12 +1038,12 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, | |||
1019 | ret = false; | 1038 | ret = false; |
1020 | 1039 | ||
1021 | /* DPLL0 is always enabled since it drives CDCLK */ | 1040 | /* DPLL0 is always enabled since it drives CDCLK */ |
1022 | val = I915_READ(regs[pll->id].ctl); | 1041 | val = I915_READ(regs[id].ctl); |
1023 | if (WARN_ON(!(val & LCPLL_PLL_ENABLE))) | 1042 | if (WARN_ON(!(val & LCPLL_PLL_ENABLE))) |
1024 | goto out; | 1043 | goto out; |
1025 | 1044 | ||
1026 | val = I915_READ(DPLL_CTRL1); | 1045 | val = I915_READ(DPLL_CTRL1); |
1027 | hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; | 1046 | hw_state->ctrl1 = (val >> (id * 6)) & 0x3f; |
1028 | 1047 | ||
1029 | ret = true; | 1048 | ret = true; |
1030 | 1049 | ||
@@ -1424,7 +1443,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, | |||
1424 | struct intel_shared_dpll *pll) | 1443 | struct intel_shared_dpll *pll) |
1425 | { | 1444 | { |
1426 | uint32_t temp; | 1445 | uint32_t temp; |
1427 | enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ | 1446 | enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ |
1428 | enum dpio_phy phy; | 1447 | enum dpio_phy phy; |
1429 | enum dpio_channel ch; | 1448 | enum dpio_channel ch; |
1430 | 1449 | ||
@@ -1543,7 +1562,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, | |||
1543 | static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, | 1562 | static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, |
1544 | struct intel_shared_dpll *pll) | 1563 | struct intel_shared_dpll *pll) |
1545 | { | 1564 | { |
1546 | enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ | 1565 | enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ |
1547 | uint32_t temp; | 1566 | uint32_t temp; |
1548 | 1567 | ||
1549 | temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); | 1568 | temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); |
@@ -1566,7 +1585,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, | |||
1566 | struct intel_shared_dpll *pll, | 1585 | struct intel_shared_dpll *pll, |
1567 | struct intel_dpll_hw_state *hw_state) | 1586 | struct intel_dpll_hw_state *hw_state) |
1568 | { | 1587 | { |
1569 | enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ | 1588 | enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ |
1570 | uint32_t val; | 1589 | uint32_t val; |
1571 | bool ret; | 1590 | bool ret; |
1572 | enum dpio_phy phy; | 1591 | enum dpio_phy phy; |
@@ -1824,7 +1843,7 @@ bxt_get_dpll(struct intel_crtc *crtc, | |||
1824 | pll = intel_get_shared_dpll_by_id(dev_priv, i); | 1843 | pll = intel_get_shared_dpll_by_id(dev_priv, i); |
1825 | 1844 | ||
1826 | DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", | 1845 | DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", |
1827 | crtc->base.base.id, crtc->base.name, pll->name); | 1846 | crtc->base.base.id, crtc->base.name, pll->info->name); |
1828 | 1847 | ||
1829 | intel_reference_shared_dpll(pll, crtc_state); | 1848 | intel_reference_shared_dpll(pll, crtc_state); |
1830 | 1849 | ||
@@ -1877,13 +1896,6 @@ static void intel_ddi_pll_init(struct drm_device *dev) | |||
1877 | } | 1896 | } |
1878 | } | 1897 | } |
1879 | 1898 | ||
1880 | struct dpll_info { | ||
1881 | const char *name; | ||
1882 | const int id; | ||
1883 | const struct intel_shared_dpll_funcs *funcs; | ||
1884 | uint32_t flags; | ||
1885 | }; | ||
1886 | |||
1887 | struct intel_dpll_mgr { | 1899 | struct intel_dpll_mgr { |
1888 | const struct dpll_info *dpll_info; | 1900 | const struct dpll_info *dpll_info; |
1889 | 1901 | ||
@@ -1896,9 +1908,9 @@ struct intel_dpll_mgr { | |||
1896 | }; | 1908 | }; |
1897 | 1909 | ||
1898 | static const struct dpll_info pch_plls[] = { | 1910 | static const struct dpll_info pch_plls[] = { |
1899 | { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 }, | 1911 | { "PCH DPLL A", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_A, 0 }, |
1900 | { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 }, | 1912 | { "PCH DPLL B", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_B, 0 }, |
1901 | { NULL, -1, NULL, 0 }, | 1913 | { }, |
1902 | }; | 1914 | }; |
1903 | 1915 | ||
1904 | static const struct intel_dpll_mgr pch_pll_mgr = { | 1916 | static const struct intel_dpll_mgr pch_pll_mgr = { |
@@ -1908,13 +1920,13 @@ static const struct intel_dpll_mgr pch_pll_mgr = { | |||
1908 | }; | 1920 | }; |
1909 | 1921 | ||
1910 | static const struct dpll_info hsw_plls[] = { | 1922 | static const struct dpll_info hsw_plls[] = { |
1911 | { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 }, | 1923 | { "WRPLL 1", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL1, 0 }, |
1912 | { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 }, | 1924 | { "WRPLL 2", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL2, 0 }, |
1913 | { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 }, | 1925 | { "SPLL", &hsw_ddi_spll_funcs, DPLL_ID_SPLL, 0 }, |
1914 | { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | 1926 | { "LCPLL 810", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_810, INTEL_DPLL_ALWAYS_ON }, |
1915 | { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | 1927 | { "LCPLL 1350", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_1350, INTEL_DPLL_ALWAYS_ON }, |
1916 | { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | 1928 | { "LCPLL 2700", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_2700, INTEL_DPLL_ALWAYS_ON }, |
1917 | { NULL, -1, NULL, }, | 1929 | { }, |
1918 | }; | 1930 | }; |
1919 | 1931 | ||
1920 | static const struct intel_dpll_mgr hsw_pll_mgr = { | 1932 | static const struct intel_dpll_mgr hsw_pll_mgr = { |
@@ -1924,11 +1936,11 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { | |||
1924 | }; | 1936 | }; |
1925 | 1937 | ||
1926 | static const struct dpll_info skl_plls[] = { | 1938 | static const struct dpll_info skl_plls[] = { |
1927 | { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON }, | 1939 | { "DPLL 0", &skl_ddi_dpll0_funcs, DPLL_ID_SKL_DPLL0, INTEL_DPLL_ALWAYS_ON }, |
1928 | { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, | 1940 | { "DPLL 1", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, |
1929 | { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, | 1941 | { "DPLL 2", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, |
1930 | { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, | 1942 | { "DPLL 3", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL3, 0 }, |
1931 | { NULL, -1, NULL, }, | 1943 | { }, |
1932 | }; | 1944 | }; |
1933 | 1945 | ||
1934 | static const struct intel_dpll_mgr skl_pll_mgr = { | 1946 | static const struct intel_dpll_mgr skl_pll_mgr = { |
@@ -1938,10 +1950,10 @@ static const struct intel_dpll_mgr skl_pll_mgr = { | |||
1938 | }; | 1950 | }; |
1939 | 1951 | ||
1940 | static const struct dpll_info bxt_plls[] = { | 1952 | static const struct dpll_info bxt_plls[] = { |
1941 | { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 }, | 1953 | { "PORT PLL A", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 }, |
1942 | { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 }, | 1954 | { "PORT PLL B", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, |
1943 | { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 }, | 1955 | { "PORT PLL C", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, |
1944 | { NULL, -1, NULL, }, | 1956 | { }, |
1945 | }; | 1957 | }; |
1946 | 1958 | ||
1947 | static const struct intel_dpll_mgr bxt_pll_mgr = { | 1959 | static const struct intel_dpll_mgr bxt_pll_mgr = { |
@@ -1953,38 +1965,39 @@ static const struct intel_dpll_mgr bxt_pll_mgr = { | |||
1953 | static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, | 1965 | static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, |
1954 | struct intel_shared_dpll *pll) | 1966 | struct intel_shared_dpll *pll) |
1955 | { | 1967 | { |
1968 | const enum intel_dpll_id id = pll->info->id; | ||
1956 | uint32_t val; | 1969 | uint32_t val; |
1957 | 1970 | ||
1958 | /* 1. Enable DPLL power in DPLL_ENABLE. */ | 1971 | /* 1. Enable DPLL power in DPLL_ENABLE. */ |
1959 | val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | 1972 | val = I915_READ(CNL_DPLL_ENABLE(id)); |
1960 | val |= PLL_POWER_ENABLE; | 1973 | val |= PLL_POWER_ENABLE; |
1961 | I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | 1974 | I915_WRITE(CNL_DPLL_ENABLE(id), val); |
1962 | 1975 | ||
1963 | /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */ | 1976 | /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */ |
1964 | if (intel_wait_for_register(dev_priv, | 1977 | if (intel_wait_for_register(dev_priv, |
1965 | CNL_DPLL_ENABLE(pll->id), | 1978 | CNL_DPLL_ENABLE(id), |
1966 | PLL_POWER_STATE, | 1979 | PLL_POWER_STATE, |
1967 | PLL_POWER_STATE, | 1980 | PLL_POWER_STATE, |
1968 | 5)) | 1981 | 5)) |
1969 | DRM_ERROR("PLL %d Power not enabled\n", pll->id); | 1982 | DRM_ERROR("PLL %d Power not enabled\n", id); |
1970 | 1983 | ||
1971 | /* | 1984 | /* |
1972 | * 3. Configure DPLL_CFGCR0 to set SSC enable/disable, | 1985 | * 3. Configure DPLL_CFGCR0 to set SSC enable/disable, |
1973 | * select DP mode, and set DP link rate. | 1986 | * select DP mode, and set DP link rate. |
1974 | */ | 1987 | */ |
1975 | val = pll->state.hw_state.cfgcr0; | 1988 | val = pll->state.hw_state.cfgcr0; |
1976 | I915_WRITE(CNL_DPLL_CFGCR0(pll->id), val); | 1989 | I915_WRITE(CNL_DPLL_CFGCR0(id), val); |
1977 | 1990 | ||
1978 | /* 4. Reab back to ensure writes completed */ | 1991 | /* 4. Reab back to ensure writes completed */ |
1979 | POSTING_READ(CNL_DPLL_CFGCR0(pll->id)); | 1992 | POSTING_READ(CNL_DPLL_CFGCR0(id)); |
1980 | 1993 | ||
1981 | /* 3. Configure DPLL_CFGCR0 */ | 1994 | /* 3. Configure DPLL_CFGCR0 */ |
1982 | /* Avoid touch CFGCR1 if HDMI mode is not enabled */ | 1995 | /* Avoid touch CFGCR1 if HDMI mode is not enabled */ |
1983 | if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) { | 1996 | if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) { |
1984 | val = pll->state.hw_state.cfgcr1; | 1997 | val = pll->state.hw_state.cfgcr1; |
1985 | I915_WRITE(CNL_DPLL_CFGCR1(pll->id), val); | 1998 | I915_WRITE(CNL_DPLL_CFGCR1(id), val); |
1986 | /* 4. Reab back to ensure writes completed */ | 1999 | /* 4. Reab back to ensure writes completed */ |
1987 | POSTING_READ(CNL_DPLL_CFGCR1(pll->id)); | 2000 | POSTING_READ(CNL_DPLL_CFGCR1(id)); |
1988 | } | 2001 | } |
1989 | 2002 | ||
1990 | /* | 2003 | /* |
@@ -1997,17 +2010,17 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, | |||
1997 | */ | 2010 | */ |
1998 | 2011 | ||
1999 | /* 6. Enable DPLL in DPLL_ENABLE. */ | 2012 | /* 6. Enable DPLL in DPLL_ENABLE. */ |
2000 | val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | 2013 | val = I915_READ(CNL_DPLL_ENABLE(id)); |
2001 | val |= PLL_ENABLE; | 2014 | val |= PLL_ENABLE; |
2002 | I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | 2015 | I915_WRITE(CNL_DPLL_ENABLE(id), val); |
2003 | 2016 | ||
2004 | /* 7. Wait for PLL lock status in DPLL_ENABLE. */ | 2017 | /* 7. Wait for PLL lock status in DPLL_ENABLE. */ |
2005 | if (intel_wait_for_register(dev_priv, | 2018 | if (intel_wait_for_register(dev_priv, |
2006 | CNL_DPLL_ENABLE(pll->id), | 2019 | CNL_DPLL_ENABLE(id), |
2007 | PLL_LOCK, | 2020 | PLL_LOCK, |
2008 | PLL_LOCK, | 2021 | PLL_LOCK, |
2009 | 5)) | 2022 | 5)) |
2010 | DRM_ERROR("PLL %d not locked\n", pll->id); | 2023 | DRM_ERROR("PLL %d not locked\n", id); |
2011 | 2024 | ||
2012 | /* | 2025 | /* |
2013 | * 8. If the frequency will result in a change to the voltage | 2026 | * 8. If the frequency will result in a change to the voltage |
@@ -2027,6 +2040,7 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, | |||
2027 | static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, | 2040 | static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, |
2028 | struct intel_shared_dpll *pll) | 2041 | struct intel_shared_dpll *pll) |
2029 | { | 2042 | { |
2043 | const enum intel_dpll_id id = pll->info->id; | ||
2030 | uint32_t val; | 2044 | uint32_t val; |
2031 | 2045 | ||
2032 | /* | 2046 | /* |
@@ -2044,17 +2058,17 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, | |||
2044 | */ | 2058 | */ |
2045 | 2059 | ||
2046 | /* 3. Disable DPLL through DPLL_ENABLE. */ | 2060 | /* 3. Disable DPLL through DPLL_ENABLE. */ |
2047 | val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | 2061 | val = I915_READ(CNL_DPLL_ENABLE(id)); |
2048 | val &= ~PLL_ENABLE; | 2062 | val &= ~PLL_ENABLE; |
2049 | I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | 2063 | I915_WRITE(CNL_DPLL_ENABLE(id), val); |
2050 | 2064 | ||
2051 | /* 4. Wait for PLL not locked status in DPLL_ENABLE. */ | 2065 | /* 4. Wait for PLL not locked status in DPLL_ENABLE. */ |
2052 | if (intel_wait_for_register(dev_priv, | 2066 | if (intel_wait_for_register(dev_priv, |
2053 | CNL_DPLL_ENABLE(pll->id), | 2067 | CNL_DPLL_ENABLE(id), |
2054 | PLL_LOCK, | 2068 | PLL_LOCK, |
2055 | 0, | 2069 | 0, |
2056 | 5)) | 2070 | 5)) |
2057 | DRM_ERROR("PLL %d locked\n", pll->id); | 2071 | DRM_ERROR("PLL %d locked\n", id); |
2058 | 2072 | ||
2059 | /* | 2073 | /* |
2060 | * 5. If the frequency will result in a change to the voltage | 2074 | * 5. If the frequency will result in a change to the voltage |
@@ -2066,23 +2080,24 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, | |||
2066 | */ | 2080 | */ |
2067 | 2081 | ||
2068 | /* 6. Disable DPLL power in DPLL_ENABLE. */ | 2082 | /* 6. Disable DPLL power in DPLL_ENABLE. */ |
2069 | val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | 2083 | val = I915_READ(CNL_DPLL_ENABLE(id)); |
2070 | val &= ~PLL_POWER_ENABLE; | 2084 | val &= ~PLL_POWER_ENABLE; |
2071 | I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | 2085 | I915_WRITE(CNL_DPLL_ENABLE(id), val); |
2072 | 2086 | ||
2073 | /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */ | 2087 | /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */ |
2074 | if (intel_wait_for_register(dev_priv, | 2088 | if (intel_wait_for_register(dev_priv, |
2075 | CNL_DPLL_ENABLE(pll->id), | 2089 | CNL_DPLL_ENABLE(id), |
2076 | PLL_POWER_STATE, | 2090 | PLL_POWER_STATE, |
2077 | 0, | 2091 | 0, |
2078 | 5)) | 2092 | 5)) |
2079 | DRM_ERROR("PLL %d Power not disabled\n", pll->id); | 2093 | DRM_ERROR("PLL %d Power not disabled\n", id); |
2080 | } | 2094 | } |
2081 | 2095 | ||
2082 | static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, | 2096 | static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, |
2083 | struct intel_shared_dpll *pll, | 2097 | struct intel_shared_dpll *pll, |
2084 | struct intel_dpll_hw_state *hw_state) | 2098 | struct intel_dpll_hw_state *hw_state) |
2085 | { | 2099 | { |
2100 | const enum intel_dpll_id id = pll->info->id; | ||
2086 | uint32_t val; | 2101 | uint32_t val; |
2087 | bool ret; | 2102 | bool ret; |
2088 | 2103 | ||
@@ -2091,16 +2106,16 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, | |||
2091 | 2106 | ||
2092 | ret = false; | 2107 | ret = false; |
2093 | 2108 | ||
2094 | val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | 2109 | val = I915_READ(CNL_DPLL_ENABLE(id)); |
2095 | if (!(val & PLL_ENABLE)) | 2110 | if (!(val & PLL_ENABLE)) |
2096 | goto out; | 2111 | goto out; |
2097 | 2112 | ||
2098 | val = I915_READ(CNL_DPLL_CFGCR0(pll->id)); | 2113 | val = I915_READ(CNL_DPLL_CFGCR0(id)); |
2099 | hw_state->cfgcr0 = val; | 2114 | hw_state->cfgcr0 = val; |
2100 | 2115 | ||
2101 | /* avoid reading back stale values if HDMI mode is not enabled */ | 2116 | /* avoid reading back stale values if HDMI mode is not enabled */ |
2102 | if (val & DPLL_CFGCR0_HDMI_MODE) { | 2117 | if (val & DPLL_CFGCR0_HDMI_MODE) { |
2103 | hw_state->cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll->id)); | 2118 | hw_state->cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(id)); |
2104 | } | 2119 | } |
2105 | ret = true; | 2120 | ret = true; |
2106 | 2121 | ||
@@ -2372,10 +2387,10 @@ static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = { | |||
2372 | }; | 2387 | }; |
2373 | 2388 | ||
2374 | static const struct dpll_info cnl_plls[] = { | 2389 | static const struct dpll_info cnl_plls[] = { |
2375 | { "DPLL 0", DPLL_ID_SKL_DPLL0, &cnl_ddi_pll_funcs, 0 }, | 2390 | { "DPLL 0", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 }, |
2376 | { "DPLL 1", DPLL_ID_SKL_DPLL1, &cnl_ddi_pll_funcs, 0 }, | 2391 | { "DPLL 1", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, |
2377 | { "DPLL 2", DPLL_ID_SKL_DPLL2, &cnl_ddi_pll_funcs, 0 }, | 2392 | { "DPLL 2", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, |
2378 | { NULL, -1, NULL, }, | 2393 | { }, |
2379 | }; | 2394 | }; |
2380 | 2395 | ||
2381 | static const struct intel_dpll_mgr cnl_pll_mgr = { | 2396 | static const struct intel_dpll_mgr cnl_pll_mgr = { |
@@ -2415,13 +2430,9 @@ void intel_shared_dpll_init(struct drm_device *dev) | |||
2415 | 2430 | ||
2416 | dpll_info = dpll_mgr->dpll_info; | 2431 | dpll_info = dpll_mgr->dpll_info; |
2417 | 2432 | ||
2418 | for (i = 0; dpll_info[i].id >= 0; i++) { | 2433 | for (i = 0; dpll_info[i].name; i++) { |
2419 | WARN_ON(i != dpll_info[i].id); | 2434 | WARN_ON(i != dpll_info[i].id); |
2420 | 2435 | dev_priv->shared_dplls[i].info = &dpll_info[i]; | |
2421 | dev_priv->shared_dplls[i].id = dpll_info[i].id; | ||
2422 | dev_priv->shared_dplls[i].name = dpll_info[i].name; | ||
2423 | dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs; | ||
2424 | dev_priv->shared_dplls[i].flags = dpll_info[i].flags; | ||
2425 | } | 2436 | } |
2426 | 2437 | ||
2427 | dev_priv->dpll_mgr = dpll_mgr; | 2438 | dev_priv->dpll_mgr = dpll_mgr; |
@@ -2481,7 +2492,7 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll, | |||
2481 | struct intel_shared_dpll_state *shared_dpll_state; | 2492 | struct intel_shared_dpll_state *shared_dpll_state; |
2482 | 2493 | ||
2483 | shared_dpll_state = intel_atomic_get_shared_dpll_state(state); | 2494 | shared_dpll_state = intel_atomic_get_shared_dpll_state(state); |
2484 | shared_dpll_state[dpll->id].crtc_mask &= ~(1 << crtc->pipe); | 2495 | shared_dpll_state[dpll->info->id].crtc_mask &= ~(1 << crtc->pipe); |
2485 | } | 2496 | } |
2486 | 2497 | ||
2487 | /** | 2498 | /** |
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index f24ccf443d25..4febfaa90bde 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h | |||
@@ -206,6 +206,37 @@ struct intel_shared_dpll_funcs { | |||
206 | }; | 206 | }; |
207 | 207 | ||
208 | /** | 208 | /** |
209 | * struct dpll_info - display PLL platform specific info | ||
210 | */ | ||
211 | struct dpll_info { | ||
212 | /** | ||
213 | * @name: DPLL name; used for logging | ||
214 | */ | ||
215 | const char *name; | ||
216 | |||
217 | /** | ||
218 | * @funcs: platform specific hooks | ||
219 | */ | ||
220 | const struct intel_shared_dpll_funcs *funcs; | ||
221 | |||
222 | /** | ||
223 | * @id: unique indentifier for this DPLL; should match the index in the | ||
224 | * dev_priv->shared_dplls array | ||
225 | */ | ||
226 | enum intel_dpll_id id; | ||
227 | |||
228 | #define INTEL_DPLL_ALWAYS_ON (1 << 0) | ||
229 | /** | ||
230 | * @flags: | ||
231 | * | ||
232 | * INTEL_DPLL_ALWAYS_ON | ||
233 | * Inform the state checker that the DPLL is kept enabled even if | ||
234 | * not in use by any CRTC. | ||
235 | */ | ||
236 | uint32_t flags; | ||
237 | }; | ||
238 | |||
239 | /** | ||
209 | * struct intel_shared_dpll - display PLL with tracked state and users | 240 | * struct intel_shared_dpll - display PLL with tracked state and users |
210 | */ | 241 | */ |
211 | struct intel_shared_dpll { | 242 | struct intel_shared_dpll { |
@@ -228,30 +259,9 @@ struct intel_shared_dpll { | |||
228 | bool on; | 259 | bool on; |
229 | 260 | ||
230 | /** | 261 | /** |
231 | * @name: DPLL name; used for logging | 262 | * @info: platform specific info |
232 | */ | 263 | */ |
233 | const char *name; | 264 | const struct dpll_info *info; |
234 | |||
235 | /** | ||
236 | * @id: unique indentifier for this DPLL; should match the index in the | ||
237 | * dev_priv->shared_dplls array | ||
238 | */ | ||
239 | enum intel_dpll_id id; | ||
240 | |||
241 | /** | ||
242 | * @funcs: platform specific hooks | ||
243 | */ | ||
244 | struct intel_shared_dpll_funcs funcs; | ||
245 | |||
246 | #define INTEL_DPLL_ALWAYS_ON (1 << 0) | ||
247 | /** | ||
248 | * @flags: | ||
249 | * | ||
250 | * INTEL_DPLL_ALWAYS_ON | ||
251 | * Inform the state checker that the DPLL is kept enabled even if | ||
252 | * not in use by any CRTC. | ||
253 | */ | ||
254 | uint32_t flags; | ||
255 | }; | 265 | }; |
256 | 266 | ||
257 | #define SKL_DPLL0 0 | 267 | #define SKL_DPLL0 0 |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a80fbad9be0f..6bd7bff0947a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -482,7 +482,7 @@ struct intel_atomic_state { | |||
482 | bool skip_intermediate_wm; | 482 | bool skip_intermediate_wm; |
483 | 483 | ||
484 | /* Gen9+ only */ | 484 | /* Gen9+ only */ |
485 | struct skl_wm_values wm_results; | 485 | struct skl_ddb_values wm_results; |
486 | 486 | ||
487 | struct i915_sw_fence commit_ready; | 487 | struct i915_sw_fence commit_ready; |
488 | 488 | ||
@@ -548,6 +548,12 @@ struct intel_initial_plane_config { | |||
548 | #define SKL_MAX_DST_W 4096 | 548 | #define SKL_MAX_DST_W 4096 |
549 | #define SKL_MIN_DST_H 8 | 549 | #define SKL_MIN_DST_H 8 |
550 | #define SKL_MAX_DST_H 4096 | 550 | #define SKL_MAX_DST_H 4096 |
551 | #define ICL_MAX_SRC_W 5120 | ||
552 | #define ICL_MAX_SRC_H 4096 | ||
553 | #define ICL_MAX_DST_W 5120 | ||
554 | #define ICL_MAX_DST_H 4096 | ||
555 | #define SKL_MIN_YUV_420_SRC_W 16 | ||
556 | #define SKL_MIN_YUV_420_SRC_H 16 | ||
551 | 557 | ||
552 | struct intel_scaler { | 558 | struct intel_scaler { |
553 | int in_use; | 559 | int in_use; |
@@ -598,7 +604,9 @@ struct intel_pipe_wm { | |||
598 | 604 | ||
599 | struct skl_plane_wm { | 605 | struct skl_plane_wm { |
600 | struct skl_wm_level wm[8]; | 606 | struct skl_wm_level wm[8]; |
607 | struct skl_wm_level uv_wm[8]; | ||
601 | struct skl_wm_level trans_wm; | 608 | struct skl_wm_level trans_wm; |
609 | bool is_planar; | ||
602 | }; | 610 | }; |
603 | 611 | ||
604 | struct skl_pipe_wm { | 612 | struct skl_pipe_wm { |
@@ -1325,6 +1333,7 @@ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); | |||
1325 | void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); | 1333 | void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); |
1326 | void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); | 1334 | void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); |
1327 | void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); | 1335 | void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); |
1336 | void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv); | ||
1328 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); | 1337 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); |
1329 | void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv); | 1338 | void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv); |
1330 | void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv); | 1339 | void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv); |
@@ -1588,9 +1597,12 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state); | |||
1588 | enum intel_display_power_domain intel_port_to_power_domain(enum port port); | 1597 | enum intel_display_power_domain intel_port_to_power_domain(enum port port); |
1589 | void intel_mode_from_pipe_config(struct drm_display_mode *mode, | 1598 | void intel_mode_from_pipe_config(struct drm_display_mode *mode, |
1590 | struct intel_crtc_state *pipe_config); | 1599 | struct intel_crtc_state *pipe_config); |
1600 | void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, | ||
1601 | struct intel_crtc_state *crtc_state); | ||
1591 | 1602 | ||
1592 | int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); | 1603 | int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); |
1593 | int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); | 1604 | int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, |
1605 | uint32_t pixel_format); | ||
1594 | 1606 | ||
1595 | static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) | 1607 | static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) |
1596 | { | 1608 | { |
@@ -1607,6 +1619,7 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, | |||
1607 | int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, | 1619 | int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, |
1608 | struct intel_plane_state *plane_state); | 1620 | struct intel_plane_state *plane_state); |
1609 | int i9xx_check_plane_surface(struct intel_plane_state *plane_state); | 1621 | int i9xx_check_plane_surface(struct intel_plane_state *plane_state); |
1622 | int skl_format_to_fourcc(int format, bool rgb_order, bool alpha); | ||
1610 | 1623 | ||
1611 | /* intel_csr.c */ | 1624 | /* intel_csr.c */ |
1612 | void intel_csr_ucode_init(struct drm_i915_private *); | 1625 | void intel_csr_ucode_init(struct drm_i915_private *); |
@@ -1773,6 +1786,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, | |||
1773 | unsigned int frontbuffer_bits, enum fb_op_origin origin); | 1786 | unsigned int frontbuffer_bits, enum fb_op_origin origin); |
1774 | void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); | 1787 | void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); |
1775 | void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); | 1788 | void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); |
1789 | int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv); | ||
1776 | 1790 | ||
1777 | /* intel_hdmi.c */ | 1791 | /* intel_hdmi.c */ |
1778 | void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, | 1792 | void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, |
@@ -1783,7 +1797,7 @@ struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); | |||
1783 | bool intel_hdmi_compute_config(struct intel_encoder *encoder, | 1797 | bool intel_hdmi_compute_config(struct intel_encoder *encoder, |
1784 | struct intel_crtc_state *pipe_config, | 1798 | struct intel_crtc_state *pipe_config, |
1785 | struct drm_connector_state *conn_state); | 1799 | struct drm_connector_state *conn_state); |
1786 | void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder, | 1800 | bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, |
1787 | struct drm_connector *connector, | 1801 | struct drm_connector *connector, |
1788 | bool high_tmds_clock_ratio, | 1802 | bool high_tmds_clock_ratio, |
1789 | bool scrambling); | 1803 | bool scrambling); |
@@ -1877,7 +1891,8 @@ void intel_psr_enable(struct intel_dp *intel_dp, | |||
1877 | void intel_psr_disable(struct intel_dp *intel_dp, | 1891 | void intel_psr_disable(struct intel_dp *intel_dp, |
1878 | const struct intel_crtc_state *old_crtc_state); | 1892 | const struct intel_crtc_state *old_crtc_state); |
1879 | void intel_psr_invalidate(struct drm_i915_private *dev_priv, | 1893 | void intel_psr_invalidate(struct drm_i915_private *dev_priv, |
1880 | unsigned frontbuffer_bits); | 1894 | unsigned frontbuffer_bits, |
1895 | enum fb_op_origin origin); | ||
1881 | void intel_psr_flush(struct drm_i915_private *dev_priv, | 1896 | void intel_psr_flush(struct drm_i915_private *dev_priv, |
1882 | unsigned frontbuffer_bits, | 1897 | unsigned frontbuffer_bits, |
1883 | enum fb_op_origin origin); | 1898 | enum fb_op_origin origin); |
@@ -2046,6 +2061,7 @@ void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc); | |||
2046 | bool skl_plane_get_hw_state(struct intel_plane *plane); | 2061 | bool skl_plane_get_hw_state(struct intel_plane *plane); |
2047 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, | 2062 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, |
2048 | enum pipe pipe, enum plane_id plane_id); | 2063 | enum pipe pipe, enum plane_id plane_id); |
2064 | bool intel_format_is_yuv(uint32_t format); | ||
2049 | 2065 | ||
2050 | /* intel_tv.c */ | 2066 | /* intel_tv.c */ |
2051 | void intel_tv_init(struct drm_i915_private *dev_priv); | 2067 | void intel_tv_init(struct drm_i915_private *dev_priv); |
@@ -2082,31 +2098,6 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, | |||
2082 | return to_intel_crtc_state(crtc_state); | 2098 | return to_intel_crtc_state(crtc_state); |
2083 | } | 2099 | } |
2084 | 2100 | ||
2085 | static inline struct intel_crtc_state * | ||
2086 | intel_atomic_get_existing_crtc_state(struct drm_atomic_state *state, | ||
2087 | struct intel_crtc *crtc) | ||
2088 | { | ||
2089 | struct drm_crtc_state *crtc_state; | ||
2090 | |||
2091 | crtc_state = drm_atomic_get_existing_crtc_state(state, &crtc->base); | ||
2092 | |||
2093 | if (crtc_state) | ||
2094 | return to_intel_crtc_state(crtc_state); | ||
2095 | else | ||
2096 | return NULL; | ||
2097 | } | ||
2098 | |||
2099 | static inline struct intel_plane_state * | ||
2100 | intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, | ||
2101 | struct intel_plane *plane) | ||
2102 | { | ||
2103 | struct drm_plane_state *plane_state; | ||
2104 | |||
2105 | plane_state = drm_atomic_get_existing_plane_state(state, &plane->base); | ||
2106 | |||
2107 | return to_intel_plane_state(plane_state); | ||
2108 | } | ||
2109 | |||
2110 | int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, | 2101 | int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, |
2111 | struct intel_crtc *intel_crtc, | 2102 | struct intel_crtc *intel_crtc, |
2112 | struct intel_crtc_state *crtc_state); | 2103 | struct intel_crtc_state *crtc_state); |
@@ -2138,8 +2129,17 @@ int intel_pipe_crc_create(struct drm_minor *minor); | |||
2138 | #ifdef CONFIG_DEBUG_FS | 2129 | #ifdef CONFIG_DEBUG_FS |
2139 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, | 2130 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, |
2140 | size_t *values_cnt); | 2131 | size_t *values_cnt); |
2132 | void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc); | ||
2133 | void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc); | ||
2141 | #else | 2134 | #else |
2142 | #define intel_crtc_set_crc_source NULL | 2135 | #define intel_crtc_set_crc_source NULL |
2136 | static inline void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) | ||
2137 | { | ||
2138 | } | ||
2139 | |||
2140 | static inline void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) | ||
2141 | { | ||
2142 | } | ||
2143 | #endif | 2143 | #endif |
2144 | extern const struct file_operations i915_display_crc_ctl_fops; | 2144 | extern const struct file_operations i915_display_crc_ctl_fops; |
2145 | #endif /* __INTEL_DRV_H__ */ | 2145 | #endif /* __INTEL_DRV_H__ */ |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 4ba139c27fba..1a8370779bbb 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
@@ -81,13 +81,17 @@ static const struct engine_class_info intel_engine_classes[] = { | |||
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | #define MAX_MMIO_BASES 3 | ||
84 | struct engine_info { | 85 | struct engine_info { |
85 | unsigned int hw_id; | 86 | unsigned int hw_id; |
86 | unsigned int uabi_id; | 87 | unsigned int uabi_id; |
87 | u8 class; | 88 | u8 class; |
88 | u8 instance; | 89 | u8 instance; |
89 | u32 mmio_base; | 90 | /* mmio bases table *must* be sorted in reverse gen order */ |
90 | unsigned irq_shift; | 91 | struct engine_mmio_base { |
92 | u32 gen : 8; | ||
93 | u32 base : 24; | ||
94 | } mmio_bases[MAX_MMIO_BASES]; | ||
91 | }; | 95 | }; |
92 | 96 | ||
93 | static const struct engine_info intel_engines[] = { | 97 | static const struct engine_info intel_engines[] = { |
@@ -96,64 +100,76 @@ static const struct engine_info intel_engines[] = { | |||
96 | .uabi_id = I915_EXEC_RENDER, | 100 | .uabi_id = I915_EXEC_RENDER, |
97 | .class = RENDER_CLASS, | 101 | .class = RENDER_CLASS, |
98 | .instance = 0, | 102 | .instance = 0, |
99 | .mmio_base = RENDER_RING_BASE, | 103 | .mmio_bases = { |
100 | .irq_shift = GEN8_RCS_IRQ_SHIFT, | 104 | { .gen = 1, .base = RENDER_RING_BASE } |
105 | }, | ||
101 | }, | 106 | }, |
102 | [BCS] = { | 107 | [BCS] = { |
103 | .hw_id = BCS_HW, | 108 | .hw_id = BCS_HW, |
104 | .uabi_id = I915_EXEC_BLT, | 109 | .uabi_id = I915_EXEC_BLT, |
105 | .class = COPY_ENGINE_CLASS, | 110 | .class = COPY_ENGINE_CLASS, |
106 | .instance = 0, | 111 | .instance = 0, |
107 | .mmio_base = BLT_RING_BASE, | 112 | .mmio_bases = { |
108 | .irq_shift = GEN8_BCS_IRQ_SHIFT, | 113 | { .gen = 6, .base = BLT_RING_BASE } |
114 | }, | ||
109 | }, | 115 | }, |
110 | [VCS] = { | 116 | [VCS] = { |
111 | .hw_id = VCS_HW, | 117 | .hw_id = VCS_HW, |
112 | .uabi_id = I915_EXEC_BSD, | 118 | .uabi_id = I915_EXEC_BSD, |
113 | .class = VIDEO_DECODE_CLASS, | 119 | .class = VIDEO_DECODE_CLASS, |
114 | .instance = 0, | 120 | .instance = 0, |
115 | .mmio_base = GEN6_BSD_RING_BASE, | 121 | .mmio_bases = { |
116 | .irq_shift = GEN8_VCS1_IRQ_SHIFT, | 122 | { .gen = 11, .base = GEN11_BSD_RING_BASE }, |
123 | { .gen = 6, .base = GEN6_BSD_RING_BASE }, | ||
124 | { .gen = 4, .base = BSD_RING_BASE } | ||
125 | }, | ||
117 | }, | 126 | }, |
118 | [VCS2] = { | 127 | [VCS2] = { |
119 | .hw_id = VCS2_HW, | 128 | .hw_id = VCS2_HW, |
120 | .uabi_id = I915_EXEC_BSD, | 129 | .uabi_id = I915_EXEC_BSD, |
121 | .class = VIDEO_DECODE_CLASS, | 130 | .class = VIDEO_DECODE_CLASS, |
122 | .instance = 1, | 131 | .instance = 1, |
123 | .mmio_base = GEN8_BSD2_RING_BASE, | 132 | .mmio_bases = { |
124 | .irq_shift = GEN8_VCS2_IRQ_SHIFT, | 133 | { .gen = 11, .base = GEN11_BSD2_RING_BASE }, |
134 | { .gen = 8, .base = GEN8_BSD2_RING_BASE } | ||
135 | }, | ||
125 | }, | 136 | }, |
126 | [VCS3] = { | 137 | [VCS3] = { |
127 | .hw_id = VCS3_HW, | 138 | .hw_id = VCS3_HW, |
128 | .uabi_id = I915_EXEC_BSD, | 139 | .uabi_id = I915_EXEC_BSD, |
129 | .class = VIDEO_DECODE_CLASS, | 140 | .class = VIDEO_DECODE_CLASS, |
130 | .instance = 2, | 141 | .instance = 2, |
131 | .mmio_base = GEN11_BSD3_RING_BASE, | 142 | .mmio_bases = { |
132 | .irq_shift = 0, /* not used */ | 143 | { .gen = 11, .base = GEN11_BSD3_RING_BASE } |
144 | }, | ||
133 | }, | 145 | }, |
134 | [VCS4] = { | 146 | [VCS4] = { |
135 | .hw_id = VCS4_HW, | 147 | .hw_id = VCS4_HW, |
136 | .uabi_id = I915_EXEC_BSD, | 148 | .uabi_id = I915_EXEC_BSD, |
137 | .class = VIDEO_DECODE_CLASS, | 149 | .class = VIDEO_DECODE_CLASS, |
138 | .instance = 3, | 150 | .instance = 3, |
139 | .mmio_base = GEN11_BSD4_RING_BASE, | 151 | .mmio_bases = { |
140 | .irq_shift = 0, /* not used */ | 152 | { .gen = 11, .base = GEN11_BSD4_RING_BASE } |
153 | }, | ||
141 | }, | 154 | }, |
142 | [VECS] = { | 155 | [VECS] = { |
143 | .hw_id = VECS_HW, | 156 | .hw_id = VECS_HW, |
144 | .uabi_id = I915_EXEC_VEBOX, | 157 | .uabi_id = I915_EXEC_VEBOX, |
145 | .class = VIDEO_ENHANCEMENT_CLASS, | 158 | .class = VIDEO_ENHANCEMENT_CLASS, |
146 | .instance = 0, | 159 | .instance = 0, |
147 | .mmio_base = VEBOX_RING_BASE, | 160 | .mmio_bases = { |
148 | .irq_shift = GEN8_VECS_IRQ_SHIFT, | 161 | { .gen = 11, .base = GEN11_VEBOX_RING_BASE }, |
162 | { .gen = 7, .base = VEBOX_RING_BASE } | ||
163 | }, | ||
149 | }, | 164 | }, |
150 | [VECS2] = { | 165 | [VECS2] = { |
151 | .hw_id = VECS2_HW, | 166 | .hw_id = VECS2_HW, |
152 | .uabi_id = I915_EXEC_VEBOX, | 167 | .uabi_id = I915_EXEC_VEBOX, |
153 | .class = VIDEO_ENHANCEMENT_CLASS, | 168 | .class = VIDEO_ENHANCEMENT_CLASS, |
154 | .instance = 1, | 169 | .instance = 1, |
155 | .mmio_base = GEN11_VEBOX2_RING_BASE, | 170 | .mmio_bases = { |
156 | .irq_shift = 0, /* not used */ | 171 | { .gen = 11, .base = GEN11_VEBOX2_RING_BASE } |
172 | }, | ||
157 | }, | 173 | }, |
158 | }; | 174 | }; |
159 | 175 | ||
@@ -223,16 +239,36 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) | |||
223 | } | 239 | } |
224 | } | 240 | } |
225 | 241 | ||
242 | static u32 __engine_mmio_base(struct drm_i915_private *i915, | ||
243 | const struct engine_mmio_base *bases) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; i < MAX_MMIO_BASES; i++) | ||
248 | if (INTEL_GEN(i915) >= bases[i].gen) | ||
249 | break; | ||
250 | |||
251 | GEM_BUG_ON(i == MAX_MMIO_BASES); | ||
252 | GEM_BUG_ON(!bases[i].base); | ||
253 | |||
254 | return bases[i].base; | ||
255 | } | ||
256 | |||
257 | static void __sprint_engine_name(char *name, const struct engine_info *info) | ||
258 | { | ||
259 | WARN_ON(snprintf(name, INTEL_ENGINE_CS_MAX_NAME, "%s%u", | ||
260 | intel_engine_classes[info->class].name, | ||
261 | info->instance) >= INTEL_ENGINE_CS_MAX_NAME); | ||
262 | } | ||
263 | |||
226 | static int | 264 | static int |
227 | intel_engine_setup(struct drm_i915_private *dev_priv, | 265 | intel_engine_setup(struct drm_i915_private *dev_priv, |
228 | enum intel_engine_id id) | 266 | enum intel_engine_id id) |
229 | { | 267 | { |
230 | const struct engine_info *info = &intel_engines[id]; | 268 | const struct engine_info *info = &intel_engines[id]; |
231 | const struct engine_class_info *class_info; | ||
232 | struct intel_engine_cs *engine; | 269 | struct intel_engine_cs *engine; |
233 | 270 | ||
234 | GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes)); | 271 | GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes)); |
235 | class_info = &intel_engine_classes[info->class]; | ||
236 | 272 | ||
237 | BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH)); | 273 | BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH)); |
238 | BUILD_BUG_ON(MAX_ENGINE_INSTANCE >= BIT(GEN11_ENGINE_INSTANCE_WIDTH)); | 274 | BUILD_BUG_ON(MAX_ENGINE_INSTANCE >= BIT(GEN11_ENGINE_INSTANCE_WIDTH)); |
@@ -253,35 +289,14 @@ intel_engine_setup(struct drm_i915_private *dev_priv, | |||
253 | 289 | ||
254 | engine->id = id; | 290 | engine->id = id; |
255 | engine->i915 = dev_priv; | 291 | engine->i915 = dev_priv; |
256 | WARN_ON(snprintf(engine->name, sizeof(engine->name), "%s%u", | 292 | __sprint_engine_name(engine->name, info); |
257 | class_info->name, info->instance) >= | ||
258 | sizeof(engine->name)); | ||
259 | engine->hw_id = engine->guc_id = info->hw_id; | 293 | engine->hw_id = engine->guc_id = info->hw_id; |
260 | if (INTEL_GEN(dev_priv) >= 11) { | 294 | engine->mmio_base = __engine_mmio_base(dev_priv, info->mmio_bases); |
261 | switch (engine->id) { | ||
262 | case VCS: | ||
263 | engine->mmio_base = GEN11_BSD_RING_BASE; | ||
264 | break; | ||
265 | case VCS2: | ||
266 | engine->mmio_base = GEN11_BSD2_RING_BASE; | ||
267 | break; | ||
268 | case VECS: | ||
269 | engine->mmio_base = GEN11_VEBOX_RING_BASE; | ||
270 | break; | ||
271 | default: | ||
272 | /* take the original value for all other engines */ | ||
273 | engine->mmio_base = info->mmio_base; | ||
274 | break; | ||
275 | } | ||
276 | } else { | ||
277 | engine->mmio_base = info->mmio_base; | ||
278 | } | ||
279 | engine->irq_shift = info->irq_shift; | ||
280 | engine->class = info->class; | 295 | engine->class = info->class; |
281 | engine->instance = info->instance; | 296 | engine->instance = info->instance; |
282 | 297 | ||
283 | engine->uabi_id = info->uabi_id; | 298 | engine->uabi_id = info->uabi_id; |
284 | engine->uabi_class = class_info->uabi_class; | 299 | engine->uabi_class = intel_engine_classes[info->class].uabi_class; |
285 | 300 | ||
286 | engine->context_size = __intel_engine_context_size(dev_priv, | 301 | engine->context_size = __intel_engine_context_size(dev_priv, |
287 | engine->class); | 302 | engine->class); |
@@ -441,6 +456,11 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) | |||
441 | engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; | 456 | engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; |
442 | } | 457 | } |
443 | 458 | ||
459 | static void intel_engine_init_batch_pool(struct intel_engine_cs *engine) | ||
460 | { | ||
461 | i915_gem_batch_pool_init(&engine->batch_pool, engine); | ||
462 | } | ||
463 | |||
444 | static bool csb_force_mmio(struct drm_i915_private *i915) | 464 | static bool csb_force_mmio(struct drm_i915_private *i915) |
445 | { | 465 | { |
446 | /* | 466 | /* |
@@ -455,6 +475,9 @@ static bool csb_force_mmio(struct drm_i915_private *i915) | |||
455 | if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) | 475 | if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) |
456 | return true; | 476 | return true; |
457 | 477 | ||
478 | if (IS_CANNONLAKE(i915)) | ||
479 | return true; | ||
480 | |||
458 | return false; | 481 | return false; |
459 | } | 482 | } |
460 | 483 | ||
@@ -485,11 +508,9 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine) | |||
485 | void intel_engine_setup_common(struct intel_engine_cs *engine) | 508 | void intel_engine_setup_common(struct intel_engine_cs *engine) |
486 | { | 509 | { |
487 | intel_engine_init_execlist(engine); | 510 | intel_engine_init_execlist(engine); |
488 | |||
489 | intel_engine_init_timeline(engine); | 511 | intel_engine_init_timeline(engine); |
490 | intel_engine_init_hangcheck(engine); | 512 | intel_engine_init_hangcheck(engine); |
491 | i915_gem_batch_pool_init(engine, &engine->batch_pool); | 513 | intel_engine_init_batch_pool(engine); |
492 | |||
493 | intel_engine_init_cmd_parser(engine); | 514 | intel_engine_init_cmd_parser(engine); |
494 | } | 515 | } |
495 | 516 | ||
@@ -782,10 +803,24 @@ static inline uint32_t | |||
782 | read_subslice_reg(struct drm_i915_private *dev_priv, int slice, | 803 | read_subslice_reg(struct drm_i915_private *dev_priv, int slice, |
783 | int subslice, i915_reg_t reg) | 804 | int subslice, i915_reg_t reg) |
784 | { | 805 | { |
806 | uint32_t mcr_slice_subslice_mask; | ||
807 | uint32_t mcr_slice_subslice_select; | ||
785 | uint32_t mcr; | 808 | uint32_t mcr; |
786 | uint32_t ret; | 809 | uint32_t ret; |
787 | enum forcewake_domains fw_domains; | 810 | enum forcewake_domains fw_domains; |
788 | 811 | ||
812 | if (INTEL_GEN(dev_priv) >= 11) { | ||
813 | mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK | | ||
814 | GEN11_MCR_SUBSLICE_MASK; | ||
815 | mcr_slice_subslice_select = GEN11_MCR_SLICE(slice) | | ||
816 | GEN11_MCR_SUBSLICE(subslice); | ||
817 | } else { | ||
818 | mcr_slice_subslice_mask = GEN8_MCR_SLICE_MASK | | ||
819 | GEN8_MCR_SUBSLICE_MASK; | ||
820 | mcr_slice_subslice_select = GEN8_MCR_SLICE(slice) | | ||
821 | GEN8_MCR_SUBSLICE(subslice); | ||
822 | } | ||
823 | |||
789 | fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, | 824 | fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, |
790 | FW_REG_READ); | 825 | FW_REG_READ); |
791 | fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, | 826 | fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, |
@@ -800,14 +835,14 @@ read_subslice_reg(struct drm_i915_private *dev_priv, int slice, | |||
800 | * The HW expects the slice and sublice selectors to be reset to 0 | 835 | * The HW expects the slice and sublice selectors to be reset to 0 |
801 | * after reading out the registers. | 836 | * after reading out the registers. |
802 | */ | 837 | */ |
803 | WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); | 838 | WARN_ON_ONCE(mcr & mcr_slice_subslice_mask); |
804 | mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); | 839 | mcr &= ~mcr_slice_subslice_mask; |
805 | mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); | 840 | mcr |= mcr_slice_subslice_select; |
806 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); | 841 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); |
807 | 842 | ||
808 | ret = I915_READ_FW(reg); | 843 | ret = I915_READ_FW(reg); |
809 | 844 | ||
810 | mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); | 845 | mcr &= ~mcr_slice_subslice_mask; |
811 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); | 846 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); |
812 | 847 | ||
813 | intel_uncore_forcewake_put__locked(dev_priv, fw_domains); | 848 | intel_uncore_forcewake_put__locked(dev_priv, fw_domains); |
@@ -871,640 +906,6 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine, | |||
871 | } | 906 | } |
872 | } | 907 | } |
873 | 908 | ||
874 | static int wa_add(struct drm_i915_private *dev_priv, | ||
875 | i915_reg_t addr, | ||
876 | const u32 mask, const u32 val) | ||
877 | { | ||
878 | const u32 idx = dev_priv->workarounds.count; | ||
879 | |||
880 | if (WARN_ON(idx >= I915_MAX_WA_REGS)) | ||
881 | return -ENOSPC; | ||
882 | |||
883 | dev_priv->workarounds.reg[idx].addr = addr; | ||
884 | dev_priv->workarounds.reg[idx].value = val; | ||
885 | dev_priv->workarounds.reg[idx].mask = mask; | ||
886 | |||
887 | dev_priv->workarounds.count++; | ||
888 | |||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | #define WA_REG(addr, mask, val) do { \ | ||
893 | const int r = wa_add(dev_priv, (addr), (mask), (val)); \ | ||
894 | if (r) \ | ||
895 | return r; \ | ||
896 | } while (0) | ||
897 | |||
898 | #define WA_SET_BIT_MASKED(addr, mask) \ | ||
899 | WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) | ||
900 | |||
901 | #define WA_CLR_BIT_MASKED(addr, mask) \ | ||
902 | WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) | ||
903 | |||
904 | #define WA_SET_FIELD_MASKED(addr, mask, value) \ | ||
905 | WA_REG(addr, mask, _MASKED_FIELD(mask, value)) | ||
906 | |||
907 | static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, | ||
908 | i915_reg_t reg) | ||
909 | { | ||
910 | struct drm_i915_private *dev_priv = engine->i915; | ||
911 | struct i915_workarounds *wa = &dev_priv->workarounds; | ||
912 | const uint32_t index = wa->hw_whitelist_count[engine->id]; | ||
913 | |||
914 | if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) | ||
915 | return -EINVAL; | ||
916 | |||
917 | I915_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), | ||
918 | i915_mmio_reg_offset(reg)); | ||
919 | wa->hw_whitelist_count[engine->id]++; | ||
920 | |||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | static int gen8_init_workarounds(struct intel_engine_cs *engine) | ||
925 | { | ||
926 | struct drm_i915_private *dev_priv = engine->i915; | ||
927 | |||
928 | WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); | ||
929 | |||
930 | /* WaDisableAsyncFlipPerfMode:bdw,chv */ | ||
931 | WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); | ||
932 | |||
933 | /* WaDisablePartialInstShootdown:bdw,chv */ | ||
934 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
935 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); | ||
936 | |||
937 | /* Use Force Non-Coherent whenever executing a 3D context. This is a | ||
938 | * workaround for for a possible hang in the unlikely event a TLB | ||
939 | * invalidation occurs during a PSD flush. | ||
940 | */ | ||
941 | /* WaForceEnableNonCoherent:bdw,chv */ | ||
942 | /* WaHdcDisableFetchWhenMasked:bdw,chv */ | ||
943 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
944 | HDC_DONOT_FETCH_MEM_WHEN_MASKED | | ||
945 | HDC_FORCE_NON_COHERENT); | ||
946 | |||
947 | /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: | ||
948 | * "The Hierarchical Z RAW Stall Optimization allows non-overlapping | ||
949 | * polygons in the same 8x4 pixel/sample area to be processed without | ||
950 | * stalling waiting for the earlier ones to write to Hierarchical Z | ||
951 | * buffer." | ||
952 | * | ||
953 | * This optimization is off by default for BDW and CHV; turn it on. | ||
954 | */ | ||
955 | WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); | ||
956 | |||
957 | /* Wa4x4STCOptimizationDisable:bdw,chv */ | ||
958 | WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); | ||
959 | |||
960 | /* | ||
961 | * BSpec recommends 8x4 when MSAA is used, | ||
962 | * however in practice 16x4 seems fastest. | ||
963 | * | ||
964 | * Note that PS/WM thread counts depend on the WIZ hashing | ||
965 | * disable bit, which we don't touch here, but it's good | ||
966 | * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). | ||
967 | */ | ||
968 | WA_SET_FIELD_MASKED(GEN7_GT_MODE, | ||
969 | GEN6_WIZ_HASHING_MASK, | ||
970 | GEN6_WIZ_HASHING_16x4); | ||
971 | |||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | static int bdw_init_workarounds(struct intel_engine_cs *engine) | ||
976 | { | ||
977 | struct drm_i915_private *dev_priv = engine->i915; | ||
978 | int ret; | ||
979 | |||
980 | ret = gen8_init_workarounds(engine); | ||
981 | if (ret) | ||
982 | return ret; | ||
983 | |||
984 | /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ | ||
985 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); | ||
986 | |||
987 | /* WaDisableDopClockGating:bdw | ||
988 | * | ||
989 | * Also see the related UCGTCL1 write in broadwell_init_clock_gating() | ||
990 | * to disable EUTC clock gating. | ||
991 | */ | ||
992 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, | ||
993 | DOP_CLOCK_GATING_DISABLE); | ||
994 | |||
995 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
996 | GEN8_SAMPLER_POWER_BYPASS_DIS); | ||
997 | |||
998 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
999 | /* WaForceContextSaveRestoreNonCoherent:bdw */ | ||
1000 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | | ||
1001 | /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ | ||
1002 | (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int chv_init_workarounds(struct intel_engine_cs *engine) | ||
1008 | { | ||
1009 | struct drm_i915_private *dev_priv = engine->i915; | ||
1010 | int ret; | ||
1011 | |||
1012 | ret = gen8_init_workarounds(engine); | ||
1013 | if (ret) | ||
1014 | return ret; | ||
1015 | |||
1016 | /* WaDisableThreadStallDopClockGating:chv */ | ||
1017 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); | ||
1018 | |||
1019 | /* Improve HiZ throughput on CHV. */ | ||
1020 | WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static int gen9_init_workarounds(struct intel_engine_cs *engine) | ||
1026 | { | ||
1027 | struct drm_i915_private *dev_priv = engine->i915; | ||
1028 | int ret; | ||
1029 | |||
1030 | /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ | ||
1031 | I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); | ||
1032 | |||
1033 | /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ | ||
1034 | I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | | ||
1035 | GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); | ||
1036 | |||
1037 | /* WaDisableKillLogic:bxt,skl,kbl */ | ||
1038 | if (!IS_COFFEELAKE(dev_priv)) | ||
1039 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | ||
1040 | ECOCHK_DIS_TLB); | ||
1041 | |||
1042 | if (HAS_LLC(dev_priv)) { | ||
1043 | /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl | ||
1044 | * | ||
1045 | * Must match Display Engine. See | ||
1046 | * WaCompressedResourceDisplayNewHashMode. | ||
1047 | */ | ||
1048 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1049 | GEN9_PBE_COMPRESSED_HASH_SELECTION); | ||
1050 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, | ||
1051 | GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR); | ||
1052 | |||
1053 | I915_WRITE(MMCD_MISC_CTRL, | ||
1054 | I915_READ(MMCD_MISC_CTRL) | | ||
1055 | MMCD_PCLA | | ||
1056 | MMCD_HOTSPOT_EN); | ||
1057 | } | ||
1058 | |||
1059 | /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */ | ||
1060 | /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */ | ||
1061 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
1062 | FLOW_CONTROL_ENABLE | | ||
1063 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); | ||
1064 | |||
1065 | /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ | ||
1066 | if (!IS_COFFEELAKE(dev_priv)) | ||
1067 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
1068 | GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); | ||
1069 | |||
1070 | /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */ | ||
1071 | /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */ | ||
1072 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, | ||
1073 | GEN9_ENABLE_YV12_BUGFIX | | ||
1074 | GEN9_ENABLE_GPGPU_PREEMPTION); | ||
1075 | |||
1076 | /* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk,cfl */ | ||
1077 | /* WaDisablePartialResolveInVc:skl,bxt,kbl,cfl */ | ||
1078 | WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | | ||
1079 | GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); | ||
1080 | |||
1081 | /* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk,cfl */ | ||
1082 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, | ||
1083 | GEN9_CCS_TLB_PREFETCH_ENABLE); | ||
1084 | |||
1085 | /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */ | ||
1086 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
1087 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | | ||
1088 | HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); | ||
1089 | |||
1090 | /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are | ||
1091 | * both tied to WaForceContextSaveRestoreNonCoherent | ||
1092 | * in some hsds for skl. We keep the tie for all gen9. The | ||
1093 | * documentation is a bit hazy and so we want to get common behaviour, | ||
1094 | * even though there is no clear evidence we would need both on kbl/bxt. | ||
1095 | * This area has been source of system hangs so we play it safe | ||
1096 | * and mimic the skl regardless of what bspec says. | ||
1097 | * | ||
1098 | * Use Force Non-Coherent whenever executing a 3D context. This | ||
1099 | * is a workaround for a possible hang in the unlikely event | ||
1100 | * a TLB invalidation occurs during a PSD flush. | ||
1101 | */ | ||
1102 | |||
1103 | /* WaForceEnableNonCoherent:skl,bxt,kbl,cfl */ | ||
1104 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
1105 | HDC_FORCE_NON_COHERENT); | ||
1106 | |||
1107 | /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ | ||
1108 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | ||
1109 | BDW_DISABLE_HDC_INVALIDATION); | ||
1110 | |||
1111 | /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */ | ||
1112 | if (IS_SKYLAKE(dev_priv) || | ||
1113 | IS_KABYLAKE(dev_priv) || | ||
1114 | IS_COFFEELAKE(dev_priv)) | ||
1115 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
1116 | GEN8_SAMPLER_POWER_BYPASS_DIS); | ||
1117 | |||
1118 | /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */ | ||
1119 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); | ||
1120 | |||
1121 | /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ | ||
1122 | if (IS_GEN9_LP(dev_priv)) { | ||
1123 | u32 val = I915_READ(GEN8_L3SQCREG1); | ||
1124 | |||
1125 | val &= ~L3_PRIO_CREDITS_MASK; | ||
1126 | val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); | ||
1127 | I915_WRITE(GEN8_L3SQCREG1, val); | ||
1128 | } | ||
1129 | |||
1130 | /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ | ||
1131 | I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | | ||
1132 | GEN8_LQSC_FLUSH_COHERENT_LINES)); | ||
1133 | |||
1134 | /* | ||
1135 | * Supporting preemption with fine-granularity requires changes in the | ||
1136 | * batch buffer programming. Since we can't break old userspace, we | ||
1137 | * need to set our default preemption level to safe value. Userspace is | ||
1138 | * still able to use more fine-grained preemption levels, since in | ||
1139 | * WaEnablePreemptionGranularityControlByUMD we're whitelisting the | ||
1140 | * per-ctx register. As such, WaDisable{3D,GPGPU}MidCmdPreemption are | ||
1141 | * not real HW workarounds, but merely a way to start using preemption | ||
1142 | * while maintaining old contract with userspace. | ||
1143 | */ | ||
1144 | |||
1145 | /* WaDisable3DMidCmdPreemption:skl,bxt,glk,cfl,[cnl] */ | ||
1146 | WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); | ||
1147 | |||
1148 | /* WaDisableGPGPUMidCmdPreemption:skl,bxt,blk,cfl,[cnl] */ | ||
1149 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, | ||
1150 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | ||
1151 | |||
1152 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ | ||
1153 | ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); | ||
1154 | if (ret) | ||
1155 | return ret; | ||
1156 | |||
1157 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ | ||
1158 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
1159 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
1160 | ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | ||
1161 | if (ret) | ||
1162 | return ret; | ||
1163 | |||
1164 | /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */ | ||
1165 | ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); | ||
1166 | if (ret) | ||
1167 | return ret; | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | static int skl_tune_iz_hashing(struct intel_engine_cs *engine) | ||
1173 | { | ||
1174 | struct drm_i915_private *dev_priv = engine->i915; | ||
1175 | u8 vals[3] = { 0, 0, 0 }; | ||
1176 | unsigned int i; | ||
1177 | |||
1178 | for (i = 0; i < 3; i++) { | ||
1179 | u8 ss; | ||
1180 | |||
1181 | /* | ||
1182 | * Only consider slices where one, and only one, subslice has 7 | ||
1183 | * EUs | ||
1184 | */ | ||
1185 | if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) | ||
1186 | continue; | ||
1187 | |||
1188 | /* | ||
1189 | * subslice_7eu[i] != 0 (because of the check above) and | ||
1190 | * ss_max == 4 (maximum number of subslices possible per slice) | ||
1191 | * | ||
1192 | * -> 0 <= ss <= 3; | ||
1193 | */ | ||
1194 | ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; | ||
1195 | vals[i] = 3 - ss; | ||
1196 | } | ||
1197 | |||
1198 | if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) | ||
1199 | return 0; | ||
1200 | |||
1201 | /* Tune IZ hashing. See intel_device_info_runtime_init() */ | ||
1202 | WA_SET_FIELD_MASKED(GEN7_GT_MODE, | ||
1203 | GEN9_IZ_HASHING_MASK(2) | | ||
1204 | GEN9_IZ_HASHING_MASK(1) | | ||
1205 | GEN9_IZ_HASHING_MASK(0), | ||
1206 | GEN9_IZ_HASHING(2, vals[2]) | | ||
1207 | GEN9_IZ_HASHING(1, vals[1]) | | ||
1208 | GEN9_IZ_HASHING(0, vals[0])); | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | static int skl_init_workarounds(struct intel_engine_cs *engine) | ||
1214 | { | ||
1215 | struct drm_i915_private *dev_priv = engine->i915; | ||
1216 | int ret; | ||
1217 | |||
1218 | ret = gen9_init_workarounds(engine); | ||
1219 | if (ret) | ||
1220 | return ret; | ||
1221 | |||
1222 | /* WaEnableGapsTsvCreditFix:skl */ | ||
1223 | I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | | ||
1224 | GEN9_GAPS_TSV_CREDIT_DISABLE)); | ||
1225 | |||
1226 | /* WaDisableGafsUnitClkGating:skl */ | ||
1227 | I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | | ||
1228 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); | ||
1229 | |||
1230 | /* WaInPlaceDecompressionHang:skl */ | ||
1231 | if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) | ||
1232 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
1233 | (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
1234 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | ||
1235 | |||
1236 | /* WaDisableLSQCROPERFforOCL:skl */ | ||
1237 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | ||
1238 | if (ret) | ||
1239 | return ret; | ||
1240 | |||
1241 | return skl_tune_iz_hashing(engine); | ||
1242 | } | ||
1243 | |||
1244 | static int bxt_init_workarounds(struct intel_engine_cs *engine) | ||
1245 | { | ||
1246 | struct drm_i915_private *dev_priv = engine->i915; | ||
1247 | int ret; | ||
1248 | |||
1249 | ret = gen9_init_workarounds(engine); | ||
1250 | if (ret) | ||
1251 | return ret; | ||
1252 | |||
1253 | /* WaDisableThreadStallDopClockGating:bxt */ | ||
1254 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
1255 | STALL_DOP_GATING_DISABLE); | ||
1256 | |||
1257 | /* WaDisablePooledEuLoadBalancingFix:bxt */ | ||
1258 | I915_WRITE(FF_SLICE_CS_CHICKEN2, | ||
1259 | _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); | ||
1260 | |||
1261 | /* WaToEnableHwFixForPushConstHWBug:bxt */ | ||
1262 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1263 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
1264 | |||
1265 | /* WaInPlaceDecompressionHang:bxt */ | ||
1266 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
1267 | (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
1268 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | ||
1269 | |||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | static int cnl_init_workarounds(struct intel_engine_cs *engine) | ||
1274 | { | ||
1275 | struct drm_i915_private *dev_priv = engine->i915; | ||
1276 | int ret; | ||
1277 | |||
1278 | /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ | ||
1279 | if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) | ||
1280 | I915_WRITE(GAMT_CHKN_BIT_REG, | ||
1281 | (I915_READ(GAMT_CHKN_BIT_REG) | | ||
1282 | GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT)); | ||
1283 | |||
1284 | /* WaForceContextSaveRestoreNonCoherent:cnl */ | ||
1285 | WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, | ||
1286 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT); | ||
1287 | |||
1288 | /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */ | ||
1289 | if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) | ||
1290 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5); | ||
1291 | |||
1292 | /* WaDisableReplayBufferBankArbitrationOptimization:cnl */ | ||
1293 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1294 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
1295 | |||
1296 | /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */ | ||
1297 | if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0)) | ||
1298 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1299 | GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); | ||
1300 | |||
1301 | /* WaInPlaceDecompressionHang:cnl */ | ||
1302 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
1303 | (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
1304 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | ||
1305 | |||
1306 | /* WaPushConstantDereferenceHoldDisable:cnl */ | ||
1307 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); | ||
1308 | |||
1309 | /* FtrEnableFastAnisoL1BankingFix: cnl */ | ||
1310 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX); | ||
1311 | |||
1312 | /* WaDisable3DMidCmdPreemption:cnl */ | ||
1313 | WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); | ||
1314 | |||
1315 | /* WaDisableGPGPUMidCmdPreemption:cnl */ | ||
1316 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, | ||
1317 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | ||
1318 | |||
1319 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ | ||
1320 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
1321 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
1322 | ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | ||
1323 | if (ret) | ||
1324 | return ret; | ||
1325 | |||
1326 | /* WaDisableEarlyEOT:cnl */ | ||
1327 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT); | ||
1328 | |||
1329 | return 0; | ||
1330 | } | ||
1331 | |||
1332 | static int kbl_init_workarounds(struct intel_engine_cs *engine) | ||
1333 | { | ||
1334 | struct drm_i915_private *dev_priv = engine->i915; | ||
1335 | int ret; | ||
1336 | |||
1337 | ret = gen9_init_workarounds(engine); | ||
1338 | if (ret) | ||
1339 | return ret; | ||
1340 | |||
1341 | /* WaEnableGapsTsvCreditFix:kbl */ | ||
1342 | I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | | ||
1343 | GEN9_GAPS_TSV_CREDIT_DISABLE)); | ||
1344 | |||
1345 | /* WaDisableDynamicCreditSharing:kbl */ | ||
1346 | if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) | ||
1347 | I915_WRITE(GAMT_CHKN_BIT_REG, | ||
1348 | (I915_READ(GAMT_CHKN_BIT_REG) | | ||
1349 | GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING)); | ||
1350 | |||
1351 | /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ | ||
1352 | if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) | ||
1353 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
1354 | HDC_FENCE_DEST_SLM_DISABLE); | ||
1355 | |||
1356 | /* WaToEnableHwFixForPushConstHWBug:kbl */ | ||
1357 | if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) | ||
1358 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1359 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
1360 | |||
1361 | /* WaDisableGafsUnitClkGating:kbl */ | ||
1362 | I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | | ||
1363 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); | ||
1364 | |||
1365 | /* WaDisableSbeCacheDispatchPortSharing:kbl */ | ||
1366 | WA_SET_BIT_MASKED( | ||
1367 | GEN7_HALF_SLICE_CHICKEN1, | ||
1368 | GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | ||
1369 | |||
1370 | /* WaInPlaceDecompressionHang:kbl */ | ||
1371 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
1372 | (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
1373 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | ||
1374 | |||
1375 | /* WaDisableLSQCROPERFforOCL:kbl */ | ||
1376 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | ||
1377 | if (ret) | ||
1378 | return ret; | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | static int glk_init_workarounds(struct intel_engine_cs *engine) | ||
1384 | { | ||
1385 | struct drm_i915_private *dev_priv = engine->i915; | ||
1386 | int ret; | ||
1387 | |||
1388 | ret = gen9_init_workarounds(engine); | ||
1389 | if (ret) | ||
1390 | return ret; | ||
1391 | |||
1392 | /* WA #0862: Userspace has to set "Barrier Mode" to avoid hangs. */ | ||
1393 | ret = wa_ring_whitelist_reg(engine, GEN9_SLICE_COMMON_ECO_CHICKEN1); | ||
1394 | if (ret) | ||
1395 | return ret; | ||
1396 | |||
1397 | /* WaToEnableHwFixForPushConstHWBug:glk */ | ||
1398 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1399 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int cfl_init_workarounds(struct intel_engine_cs *engine) | ||
1405 | { | ||
1406 | struct drm_i915_private *dev_priv = engine->i915; | ||
1407 | int ret; | ||
1408 | |||
1409 | ret = gen9_init_workarounds(engine); | ||
1410 | if (ret) | ||
1411 | return ret; | ||
1412 | |||
1413 | /* WaEnableGapsTsvCreditFix:cfl */ | ||
1414 | I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | | ||
1415 | GEN9_GAPS_TSV_CREDIT_DISABLE)); | ||
1416 | |||
1417 | /* WaToEnableHwFixForPushConstHWBug:cfl */ | ||
1418 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
1419 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
1420 | |||
1421 | /* WaDisableGafsUnitClkGating:cfl */ | ||
1422 | I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | | ||
1423 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); | ||
1424 | |||
1425 | /* WaDisableSbeCacheDispatchPortSharing:cfl */ | ||
1426 | WA_SET_BIT_MASKED( | ||
1427 | GEN7_HALF_SLICE_CHICKEN1, | ||
1428 | GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | ||
1429 | |||
1430 | /* WaInPlaceDecompressionHang:cfl */ | ||
1431 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
1432 | (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
1433 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1438 | int init_workarounds_ring(struct intel_engine_cs *engine) | ||
1439 | { | ||
1440 | struct drm_i915_private *dev_priv = engine->i915; | ||
1441 | int err; | ||
1442 | |||
1443 | if (GEM_WARN_ON(engine->id != RCS)) | ||
1444 | return -EINVAL; | ||
1445 | |||
1446 | dev_priv->workarounds.count = 0; | ||
1447 | dev_priv->workarounds.hw_whitelist_count[engine->id] = 0; | ||
1448 | |||
1449 | if (IS_BROADWELL(dev_priv)) | ||
1450 | err = bdw_init_workarounds(engine); | ||
1451 | else if (IS_CHERRYVIEW(dev_priv)) | ||
1452 | err = chv_init_workarounds(engine); | ||
1453 | else if (IS_SKYLAKE(dev_priv)) | ||
1454 | err = skl_init_workarounds(engine); | ||
1455 | else if (IS_BROXTON(dev_priv)) | ||
1456 | err = bxt_init_workarounds(engine); | ||
1457 | else if (IS_KABYLAKE(dev_priv)) | ||
1458 | err = kbl_init_workarounds(engine); | ||
1459 | else if (IS_GEMINILAKE(dev_priv)) | ||
1460 | err = glk_init_workarounds(engine); | ||
1461 | else if (IS_COFFEELAKE(dev_priv)) | ||
1462 | err = cfl_init_workarounds(engine); | ||
1463 | else if (IS_CANNONLAKE(dev_priv)) | ||
1464 | err = cnl_init_workarounds(engine); | ||
1465 | else | ||
1466 | err = 0; | ||
1467 | if (err) | ||
1468 | return err; | ||
1469 | |||
1470 | DRM_DEBUG_DRIVER("%s: Number of context specific w/a: %d\n", | ||
1471 | engine->name, dev_priv->workarounds.count); | ||
1472 | return 0; | ||
1473 | } | ||
1474 | |||
1475 | int intel_ring_workarounds_emit(struct i915_request *rq) | ||
1476 | { | ||
1477 | struct i915_workarounds *w = &rq->i915->workarounds; | ||
1478 | u32 *cs; | ||
1479 | int ret, i; | ||
1480 | |||
1481 | if (w->count == 0) | ||
1482 | return 0; | ||
1483 | |||
1484 | ret = rq->engine->emit_flush(rq, EMIT_BARRIER); | ||
1485 | if (ret) | ||
1486 | return ret; | ||
1487 | |||
1488 | cs = intel_ring_begin(rq, w->count * 2 + 2); | ||
1489 | if (IS_ERR(cs)) | ||
1490 | return PTR_ERR(cs); | ||
1491 | |||
1492 | *cs++ = MI_LOAD_REGISTER_IMM(w->count); | ||
1493 | for (i = 0; i < w->count; i++) { | ||
1494 | *cs++ = i915_mmio_reg_offset(w->reg[i].addr); | ||
1495 | *cs++ = w->reg[i].value; | ||
1496 | } | ||
1497 | *cs++ = MI_NOOP; | ||
1498 | |||
1499 | intel_ring_advance(rq, cs); | ||
1500 | |||
1501 | ret = rq->engine->emit_flush(rq, EMIT_BARRIER); | ||
1502 | if (ret) | ||
1503 | return ret; | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static bool ring_is_idle(struct intel_engine_cs *engine) | 909 | static bool ring_is_idle(struct intel_engine_cs *engine) |
1509 | { | 910 | { |
1510 | struct drm_i915_private *dev_priv = engine->i915; | 911 | struct drm_i915_private *dev_priv = engine->i915; |
@@ -1655,6 +1056,9 @@ void intel_engines_park(struct drm_i915_private *i915) | |||
1655 | intel_engine_dump(engine, &p, NULL); | 1056 | intel_engine_dump(engine, &p, NULL); |
1656 | } | 1057 | } |
1657 | 1058 | ||
1059 | /* Must be reset upon idling, or we may miss the busy wakeup. */ | ||
1060 | GEM_BUG_ON(engine->execlists.queue_priority != INT_MIN); | ||
1061 | |||
1658 | if (engine->park) | 1062 | if (engine->park) |
1659 | engine->park(engine); | 1063 | engine->park(engine); |
1660 | 1064 | ||
@@ -1713,13 +1117,15 @@ static void print_request(struct drm_printer *m, | |||
1713 | struct i915_request *rq, | 1117 | struct i915_request *rq, |
1714 | const char *prefix) | 1118 | const char *prefix) |
1715 | { | 1119 | { |
1120 | const char *name = rq->fence.ops->get_timeline_name(&rq->fence); | ||
1121 | |||
1716 | drm_printf(m, "%s%x%s [%llx:%x] prio=%d @ %dms: %s\n", prefix, | 1122 | drm_printf(m, "%s%x%s [%llx:%x] prio=%d @ %dms: %s\n", prefix, |
1717 | rq->global_seqno, | 1123 | rq->global_seqno, |
1718 | i915_request_completed(rq) ? "!" : "", | 1124 | i915_request_completed(rq) ? "!" : "", |
1719 | rq->fence.context, rq->fence.seqno, | 1125 | rq->fence.context, rq->fence.seqno, |
1720 | rq->priotree.priority, | 1126 | rq->priotree.priority, |
1721 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), | 1127 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), |
1722 | rq->timeline->common->name); | 1128 | name); |
1723 | } | 1129 | } |
1724 | 1130 | ||
1725 | static void hexdump(struct drm_printer *m, const void *buf, size_t len) | 1131 | static void hexdump(struct drm_printer *m, const void *buf, size_t len) |
@@ -1825,12 +1231,15 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine, | |||
1825 | ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); | 1231 | ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); |
1826 | read = GEN8_CSB_READ_PTR(ptr); | 1232 | read = GEN8_CSB_READ_PTR(ptr); |
1827 | write = GEN8_CSB_WRITE_PTR(ptr); | 1233 | write = GEN8_CSB_WRITE_PTR(ptr); |
1828 | drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n", | 1234 | drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s, tasklet queued? %s (%s)\n", |
1829 | read, execlists->csb_head, | 1235 | read, execlists->csb_head, |
1830 | write, | 1236 | write, |
1831 | intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), | 1237 | intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), |
1832 | yesno(test_bit(ENGINE_IRQ_EXECLIST, | 1238 | yesno(test_bit(ENGINE_IRQ_EXECLIST, |
1833 | &engine->irq_posted))); | 1239 | &engine->irq_posted)), |
1240 | yesno(test_bit(TASKLET_STATE_SCHED, | ||
1241 | &engine->execlists.tasklet.state)), | ||
1242 | enableddisabled(!atomic_read(&engine->execlists.tasklet.count))); | ||
1834 | if (read >= GEN8_CSB_ENTRIES) | 1243 | if (read >= GEN8_CSB_ENTRIES) |
1835 | read = 0; | 1244 | read = 0; |
1836 | if (write >= GEN8_CSB_ENTRIES) | 1245 | if (write >= GEN8_CSB_ENTRIES) |
@@ -1929,12 +1338,16 @@ void intel_engine_dump(struct intel_engine_cs *engine, | |||
1929 | rq->head, rq->postfix, rq->tail, | 1338 | rq->head, rq->postfix, rq->tail, |
1930 | rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, | 1339 | rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, |
1931 | rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); | 1340 | rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); |
1932 | drm_printf(m, "\t\tring->start: 0x%08x\n", | 1341 | drm_printf(m, "\t\tring->start: 0x%08x\n", |
1933 | i915_ggtt_offset(rq->ring->vma)); | 1342 | i915_ggtt_offset(rq->ring->vma)); |
1934 | drm_printf(m, "\t\tring->head: 0x%08x\n", | 1343 | drm_printf(m, "\t\tring->head: 0x%08x\n", |
1935 | rq->ring->head); | 1344 | rq->ring->head); |
1936 | drm_printf(m, "\t\tring->tail: 0x%08x\n", | 1345 | drm_printf(m, "\t\tring->tail: 0x%08x\n", |
1937 | rq->ring->tail); | 1346 | rq->ring->tail); |
1347 | drm_printf(m, "\t\tring->emit: 0x%08x\n", | ||
1348 | rq->ring->emit); | ||
1349 | drm_printf(m, "\t\tring->space: 0x%08x\n", | ||
1350 | rq->ring->space); | ||
1938 | } | 1351 | } |
1939 | 1352 | ||
1940 | rcu_read_unlock(); | 1353 | rcu_read_unlock(); |
@@ -2109,4 +1522,5 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) | |||
2109 | 1522 | ||
2110 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 1523 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
2111 | #include "selftests/mock_engine.c" | 1524 | #include "selftests/mock_engine.c" |
1525 | #include "selftests/intel_engine_cs.c" | ||
2112 | #endif | 1526 | #endif |
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 707d49c12638..b431b6733cc1 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c | |||
@@ -1272,6 +1272,34 @@ out: | |||
1272 | mutex_unlock(&fbc->lock); | 1272 | mutex_unlock(&fbc->lock); |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | /* | ||
1276 | * intel_fbc_reset_underrun - reset FBC fifo underrun status. | ||
1277 | * @dev_priv: i915 device instance | ||
1278 | * | ||
1279 | * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we | ||
1280 | * want to re-enable FBC after an underrun to increase test coverage. | ||
1281 | */ | ||
1282 | int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv) | ||
1283 | { | ||
1284 | int ret; | ||
1285 | |||
1286 | cancel_work_sync(&dev_priv->fbc.underrun_work); | ||
1287 | |||
1288 | ret = mutex_lock_interruptible(&dev_priv->fbc.lock); | ||
1289 | if (ret) | ||
1290 | return ret; | ||
1291 | |||
1292 | if (dev_priv->fbc.underrun_detected) { | ||
1293 | DRM_DEBUG_KMS("Re-allowing FBC after fifo underrun\n"); | ||
1294 | dev_priv->fbc.no_fbc_reason = "FIFO underrun cleared"; | ||
1295 | } | ||
1296 | |||
1297 | dev_priv->fbc.underrun_detected = false; | ||
1298 | mutex_unlock(&dev_priv->fbc.lock); | ||
1299 | |||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1275 | /** | 1303 | /** |
1276 | * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun | 1304 | * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun |
1277 | * @dev_priv: i915 device instance | 1305 | * @dev_priv: i915 device instance |
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 6490ee18727c..e9e02b58b7be 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c | |||
@@ -221,6 +221,9 @@ static int intelfb_create(struct drm_fb_helper *helper, | |||
221 | goto out_unlock; | 221 | goto out_unlock; |
222 | } | 222 | } |
223 | 223 | ||
224 | fb = &ifbdev->fb->base; | ||
225 | intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_DIRTYFB); | ||
226 | |||
224 | info = drm_fb_helper_alloc_fbi(helper); | 227 | info = drm_fb_helper_alloc_fbi(helper); |
225 | if (IS_ERR(info)) { | 228 | if (IS_ERR(info)) { |
226 | DRM_ERROR("Failed to allocate fb_info\n"); | 229 | DRM_ERROR("Failed to allocate fb_info\n"); |
@@ -230,8 +233,6 @@ static int intelfb_create(struct drm_fb_helper *helper, | |||
230 | 233 | ||
231 | info->par = helper; | 234 | info->par = helper; |
232 | 235 | ||
233 | fb = &ifbdev->fb->base; | ||
234 | |||
235 | ifbdev->helper.fb = fb; | 236 | ifbdev->helper.fb = fb; |
236 | 237 | ||
237 | strcpy(info->fix.id, "inteldrmfb"); | 238 | strcpy(info->fix.id, "inteldrmfb"); |
diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c index 3a8d3d06c26a..7fff0a0eceb4 100644 --- a/drivers/gpu/drm/i915/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c | |||
@@ -80,7 +80,7 @@ void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, | |||
80 | } | 80 | } |
81 | 81 | ||
82 | might_sleep(); | 82 | might_sleep(); |
83 | intel_psr_invalidate(dev_priv, frontbuffer_bits); | 83 | intel_psr_invalidate(dev_priv, frontbuffer_bits, origin); |
84 | intel_edp_drrs_invalidate(dev_priv, frontbuffer_bits); | 84 | intel_edp_drrs_invalidate(dev_priv, frontbuffer_bits); |
85 | intel_fbc_invalidate(dev_priv, frontbuffer_bits, origin); | 85 | intel_fbc_invalidate(dev_priv, frontbuffer_bits, origin); |
86 | } | 86 | } |
diff --git a/drivers/gpu/drm/i915/intel_gpu_commands.h b/drivers/gpu/drm/i915/intel_gpu_commands.h new file mode 100644 index 000000000000..105e2a9e874a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_gpu_commands.h | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright � 2003-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef _INTEL_GPU_COMMANDS_H_ | ||
8 | #define _INTEL_GPU_COMMANDS_H_ | ||
9 | |||
10 | /* | ||
11 | * Instruction field definitions used by the command parser | ||
12 | */ | ||
13 | #define INSTR_CLIENT_SHIFT 29 | ||
14 | #define INSTR_MI_CLIENT 0x0 | ||
15 | #define INSTR_BC_CLIENT 0x2 | ||
16 | #define INSTR_RC_CLIENT 0x3 | ||
17 | #define INSTR_SUBCLIENT_SHIFT 27 | ||
18 | #define INSTR_SUBCLIENT_MASK 0x18000000 | ||
19 | #define INSTR_MEDIA_SUBCLIENT 0x2 | ||
20 | #define INSTR_26_TO_24_MASK 0x7000000 | ||
21 | #define INSTR_26_TO_24_SHIFT 24 | ||
22 | |||
23 | /* | ||
24 | * Memory interface instructions used by the kernel | ||
25 | */ | ||
26 | #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags)) | ||
27 | /* Many MI commands use bit 22 of the header dword for GGTT vs PPGTT */ | ||
28 | #define MI_GLOBAL_GTT (1<<22) | ||
29 | |||
30 | #define MI_NOOP MI_INSTR(0, 0) | ||
31 | #define MI_USER_INTERRUPT MI_INSTR(0x02, 0) | ||
32 | #define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) | ||
33 | #define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) | ||
34 | #define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) | ||
35 | #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) | ||
36 | #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) | ||
37 | #define MI_FLUSH MI_INSTR(0x04, 0) | ||
38 | #define MI_READ_FLUSH (1 << 0) | ||
39 | #define MI_EXE_FLUSH (1 << 1) | ||
40 | #define MI_NO_WRITE_FLUSH (1 << 2) | ||
41 | #define MI_SCENE_COUNT (1 << 3) /* just increment scene count */ | ||
42 | #define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ | ||
43 | #define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */ | ||
44 | #define MI_REPORT_HEAD MI_INSTR(0x07, 0) | ||
45 | #define MI_ARB_ON_OFF MI_INSTR(0x08, 0) | ||
46 | #define MI_ARB_ENABLE (1<<0) | ||
47 | #define MI_ARB_DISABLE (0<<0) | ||
48 | #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) | ||
49 | #define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) | ||
50 | #define MI_SUSPEND_FLUSH_EN (1<<0) | ||
51 | #define MI_SET_APPID MI_INSTR(0x0e, 0) | ||
52 | #define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) | ||
53 | #define MI_OVERLAY_CONTINUE (0x0<<21) | ||
54 | #define MI_OVERLAY_ON (0x1<<21) | ||
55 | #define MI_OVERLAY_OFF (0x2<<21) | ||
56 | #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) | ||
57 | #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) | ||
58 | #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) | ||
59 | #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) | ||
60 | /* IVB has funny definitions for which plane to flip. */ | ||
61 | #define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) | ||
62 | #define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) | ||
63 | #define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) | ||
64 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) | ||
65 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) | ||
66 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) | ||
67 | /* SKL ones */ | ||
68 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_A (0 << 8) | ||
69 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_B (1 << 8) | ||
70 | #define MI_DISPLAY_FLIP_SKL_PLANE_1_C (2 << 8) | ||
71 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_A (4 << 8) | ||
72 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_B (5 << 8) | ||
73 | #define MI_DISPLAY_FLIP_SKL_PLANE_2_C (6 << 8) | ||
74 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_A (7 << 8) | ||
75 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_B (8 << 8) | ||
76 | #define MI_DISPLAY_FLIP_SKL_PLANE_3_C (9 << 8) | ||
77 | #define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6, gen7 */ | ||
78 | #define MI_SEMAPHORE_GLOBAL_GTT (1<<22) | ||
79 | #define MI_SEMAPHORE_UPDATE (1<<21) | ||
80 | #define MI_SEMAPHORE_COMPARE (1<<20) | ||
81 | #define MI_SEMAPHORE_REGISTER (1<<18) | ||
82 | #define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ | ||
83 | #define MI_SEMAPHORE_SYNC_VER (1<<16) /* RCS wait for VECS (RVESYNC) */ | ||
84 | #define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ | ||
85 | #define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ | ||
86 | #define MI_SEMAPHORE_SYNC_VEV (1<<16) /* VCS wait for VECS (VVESYNC) */ | ||
87 | #define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ | ||
88 | #define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ | ||
89 | #define MI_SEMAPHORE_SYNC_VEB (1<<16) /* BCS wait for VECS (BVESYNC) */ | ||
90 | #define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ | ||
91 | #define MI_SEMAPHORE_SYNC_BVE (0<<16) /* VECS wait for BCS (VEBSYNC) */ | ||
92 | #define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ | ||
93 | #define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ | ||
94 | #define MI_SEMAPHORE_SYNC_INVALID (3<<16) | ||
95 | #define MI_SEMAPHORE_SYNC_MASK (3<<16) | ||
96 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) | ||
97 | #define MI_MM_SPACE_GTT (1<<8) | ||
98 | #define MI_MM_SPACE_PHYSICAL (0<<8) | ||
99 | #define MI_SAVE_EXT_STATE_EN (1<<3) | ||
100 | #define MI_RESTORE_EXT_STATE_EN (1<<2) | ||
101 | #define MI_FORCE_RESTORE (1<<1) | ||
102 | #define MI_RESTORE_INHIBIT (1<<0) | ||
103 | #define HSW_MI_RS_SAVE_STATE_EN (1<<3) | ||
104 | #define HSW_MI_RS_RESTORE_STATE_EN (1<<2) | ||
105 | #define MI_SEMAPHORE_SIGNAL MI_INSTR(0x1b, 0) /* GEN8+ */ | ||
106 | #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) | ||
107 | #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ | ||
108 | #define MI_SEMAPHORE_POLL (1<<15) | ||
109 | #define MI_SEMAPHORE_SAD_GTE_SDD (1<<12) | ||
110 | #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) | ||
111 | #define MI_STORE_DWORD_IMM_GEN4 MI_INSTR(0x20, 2) | ||
112 | #define MI_MEM_VIRTUAL (1 << 22) /* 945,g33,965 */ | ||
113 | #define MI_USE_GGTT (1 << 22) /* g4x+ */ | ||
114 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) | ||
115 | #define MI_STORE_DWORD_INDEX_SHIFT 2 | ||
116 | /* | ||
117 | * Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: | ||
118 | * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw | ||
119 | * simply ignores the register load under certain conditions. | ||
120 | * - One can actually load arbitrary many arbitrary registers: Simply issue x | ||
121 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! | ||
122 | */ | ||
123 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*(x)-1) | ||
124 | #define MI_LRI_FORCE_POSTED (1<<12) | ||
125 | #define MI_STORE_REGISTER_MEM MI_INSTR(0x24, 1) | ||
126 | #define MI_STORE_REGISTER_MEM_GEN8 MI_INSTR(0x24, 2) | ||
127 | #define MI_SRM_LRM_GLOBAL_GTT (1<<22) | ||
128 | #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ | ||
129 | #define MI_FLUSH_DW_STORE_INDEX (1<<21) | ||
130 | #define MI_INVALIDATE_TLB (1<<18) | ||
131 | #define MI_FLUSH_DW_OP_STOREDW (1<<14) | ||
132 | #define MI_FLUSH_DW_OP_MASK (3<<14) | ||
133 | #define MI_FLUSH_DW_NOTIFY (1<<8) | ||
134 | #define MI_INVALIDATE_BSD (1<<7) | ||
135 | #define MI_FLUSH_DW_USE_GTT (1<<2) | ||
136 | #define MI_FLUSH_DW_USE_PPGTT (0<<2) | ||
137 | #define MI_LOAD_REGISTER_MEM MI_INSTR(0x29, 1) | ||
138 | #define MI_LOAD_REGISTER_MEM_GEN8 MI_INSTR(0x29, 2) | ||
139 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) | ||
140 | #define MI_BATCH_NON_SECURE (1) | ||
141 | /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */ | ||
142 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | ||
143 | #define MI_BATCH_PPGTT_HSW (1<<8) | ||
144 | #define MI_BATCH_NON_SECURE_HSW (1<<13) | ||
145 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) | ||
146 | #define MI_BATCH_GTT (2<<6) /* aliased with (1<<7) on gen4 */ | ||
147 | #define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1) | ||
148 | #define MI_BATCH_RESOURCE_STREAMER (1<<10) | ||
149 | |||
150 | /* | ||
151 | * 3D instructions used by the kernel | ||
152 | */ | ||
153 | #define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags)) | ||
154 | |||
155 | #define GEN9_MEDIA_POOL_STATE ((0x3 << 29) | (0x2 << 27) | (0x5 << 16) | 4) | ||
156 | #define GEN9_MEDIA_POOL_ENABLE (1 << 31) | ||
157 | #define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24)) | ||
158 | #define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
159 | #define SC_UPDATE_SCISSOR (0x1<<1) | ||
160 | #define SC_ENABLE_MASK (0x1<<0) | ||
161 | #define SC_ENABLE (0x1<<0) | ||
162 | #define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16)) | ||
163 | #define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) | ||
164 | #define SCI_YMIN_MASK (0xffff<<16) | ||
165 | #define SCI_XMIN_MASK (0xffff<<0) | ||
166 | #define SCI_YMAX_MASK (0xffff<<16) | ||
167 | #define SCI_XMAX_MASK (0xffff<<0) | ||
168 | #define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
169 | #define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) | ||
170 | #define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) | ||
171 | #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) | ||
172 | #define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) | ||
173 | #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) | ||
174 | #define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) | ||
175 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) | ||
176 | #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) | ||
177 | |||
178 | #define COLOR_BLT_CMD (2<<29 | 0x40<<22 | (5-2)) | ||
179 | #define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) | ||
180 | #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) | ||
181 | #define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) | ||
182 | #define BLT_WRITE_A (2<<20) | ||
183 | #define BLT_WRITE_RGB (1<<20) | ||
184 | #define BLT_WRITE_RGBA (BLT_WRITE_RGB | BLT_WRITE_A) | ||
185 | #define BLT_DEPTH_8 (0<<24) | ||
186 | #define BLT_DEPTH_16_565 (1<<24) | ||
187 | #define BLT_DEPTH_16_1555 (2<<24) | ||
188 | #define BLT_DEPTH_32 (3<<24) | ||
189 | #define BLT_ROP_SRC_COPY (0xcc<<16) | ||
190 | #define BLT_ROP_COLOR_COPY (0xf0<<16) | ||
191 | #define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */ | ||
192 | #define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */ | ||
193 | #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) | ||
194 | #define ASYNC_FLIP (1<<22) | ||
195 | #define DISPLAY_PLANE_A (0<<20) | ||
196 | #define DISPLAY_PLANE_B (1<<20) | ||
197 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2)) | ||
198 | #define PIPE_CONTROL_FLUSH_L3 (1<<27) | ||
199 | #define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */ | ||
200 | #define PIPE_CONTROL_MMIO_WRITE (1<<23) | ||
201 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) | ||
202 | #define PIPE_CONTROL_CS_STALL (1<<20) | ||
203 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | ||
204 | #define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) | ||
205 | #define PIPE_CONTROL_QW_WRITE (1<<14) | ||
206 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | ||
207 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | ||
208 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) | ||
209 | #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ | ||
210 | #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */ | ||
211 | #define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */ | ||
212 | #define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9) | ||
213 | #define PIPE_CONTROL_NOTIFY (1<<8) | ||
214 | #define PIPE_CONTROL_FLUSH_ENABLE (1<<7) /* gen7+ */ | ||
215 | #define PIPE_CONTROL_DC_FLUSH_ENABLE (1<<5) | ||
216 | #define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4) | ||
217 | #define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3) | ||
218 | #define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2) | ||
219 | #define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1) | ||
220 | #define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0) | ||
221 | #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ | ||
222 | |||
223 | /* | ||
224 | * Commands used only by the command parser | ||
225 | */ | ||
226 | #define MI_SET_PREDICATE MI_INSTR(0x01, 0) | ||
227 | #define MI_ARB_CHECK MI_INSTR(0x05, 0) | ||
228 | #define MI_RS_CONTROL MI_INSTR(0x06, 0) | ||
229 | #define MI_URB_ATOMIC_ALLOC MI_INSTR(0x09, 0) | ||
230 | #define MI_PREDICATE MI_INSTR(0x0C, 0) | ||
231 | #define MI_RS_CONTEXT MI_INSTR(0x0F, 0) | ||
232 | #define MI_TOPOLOGY_FILTER MI_INSTR(0x0D, 0) | ||
233 | #define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0) | ||
234 | #define MI_URB_CLEAR MI_INSTR(0x19, 0) | ||
235 | #define MI_UPDATE_GTT MI_INSTR(0x23, 0) | ||
236 | #define MI_CLFLUSH MI_INSTR(0x27, 0) | ||
237 | #define MI_REPORT_PERF_COUNT MI_INSTR(0x28, 0) | ||
238 | #define MI_REPORT_PERF_COUNT_GGTT (1<<0) | ||
239 | #define MI_LOAD_REGISTER_REG MI_INSTR(0x2A, 0) | ||
240 | #define MI_RS_STORE_DATA_IMM MI_INSTR(0x2B, 0) | ||
241 | #define MI_LOAD_URB_MEM MI_INSTR(0x2C, 0) | ||
242 | #define MI_STORE_URB_MEM MI_INSTR(0x2D, 0) | ||
243 | #define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0) | ||
244 | |||
245 | #define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16)) | ||
246 | #define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16)) | ||
247 | #define MEDIA_VFE_STATE ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16)) | ||
248 | #define MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18) | ||
249 | #define GPGPU_OBJECT ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16)) | ||
250 | #define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16)) | ||
251 | #define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \ | ||
252 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16)) | ||
253 | #define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \ | ||
254 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16)) | ||
255 | #define GFX_OP_3DSTATE_SO_DECL_LIST \ | ||
256 | ((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16)) | ||
257 | |||
258 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \ | ||
259 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16)) | ||
260 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \ | ||
261 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16)) | ||
262 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \ | ||
263 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16)) | ||
264 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \ | ||
265 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16)) | ||
266 | #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \ | ||
267 | ((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16)) | ||
268 | |||
269 | #define MFX_WAIT ((0x3<<29)|(0x1<<27)|(0x0<<16)) | ||
270 | |||
271 | #define COLOR_BLT ((0x2<<29)|(0x40<<22)) | ||
272 | #define SRC_COPY_BLT ((0x2<<29)|(0x43<<22)) | ||
273 | |||
274 | #endif /* _INTEL_GPU_COMMANDS_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index ff08ea0ebf49..a00a59a7d9ec 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c | |||
@@ -64,10 +64,12 @@ void intel_guc_init_early(struct intel_guc *guc) | |||
64 | { | 64 | { |
65 | intel_guc_fw_init_early(guc); | 65 | intel_guc_fw_init_early(guc); |
66 | intel_guc_ct_init_early(&guc->ct); | 66 | intel_guc_ct_init_early(&guc->ct); |
67 | intel_guc_log_init_early(guc); | 67 | intel_guc_log_init_early(&guc->log); |
68 | 68 | ||
69 | mutex_init(&guc->send_mutex); | 69 | mutex_init(&guc->send_mutex); |
70 | spin_lock_init(&guc->irq_lock); | ||
70 | guc->send = intel_guc_send_nop; | 71 | guc->send = intel_guc_send_nop; |
72 | guc->handler = intel_guc_to_host_event_handler_nop; | ||
71 | guc->notify = gen8_guc_raise_irq; | 73 | guc->notify = gen8_guc_raise_irq; |
72 | } | 74 | } |
73 | 75 | ||
@@ -86,9 +88,10 @@ int intel_guc_init_wq(struct intel_guc *guc) | |||
86 | * or scheduled later on resume. This way the handling of work | 88 | * or scheduled later on resume. This way the handling of work |
87 | * item can be kept same between system suspend & rpm suspend. | 89 | * item can be kept same between system suspend & rpm suspend. |
88 | */ | 90 | */ |
89 | guc->log.runtime.flush_wq = alloc_ordered_workqueue("i915-guc_log", | 91 | guc->log.relay.flush_wq = |
90 | WQ_HIGHPRI | WQ_FREEZABLE); | 92 | alloc_ordered_workqueue("i915-guc_log", |
91 | if (!guc->log.runtime.flush_wq) { | 93 | WQ_HIGHPRI | WQ_FREEZABLE); |
94 | if (!guc->log.relay.flush_wq) { | ||
92 | DRM_ERROR("Couldn't allocate workqueue for GuC log\n"); | 95 | DRM_ERROR("Couldn't allocate workqueue for GuC log\n"); |
93 | return -ENOMEM; | 96 | return -ENOMEM; |
94 | } | 97 | } |
@@ -111,7 +114,7 @@ int intel_guc_init_wq(struct intel_guc *guc) | |||
111 | guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", | 114 | guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", |
112 | WQ_HIGHPRI); | 115 | WQ_HIGHPRI); |
113 | if (!guc->preempt_wq) { | 116 | if (!guc->preempt_wq) { |
114 | destroy_workqueue(guc->log.runtime.flush_wq); | 117 | destroy_workqueue(guc->log.relay.flush_wq); |
115 | DRM_ERROR("Couldn't allocate workqueue for GuC " | 118 | DRM_ERROR("Couldn't allocate workqueue for GuC " |
116 | "preemption\n"); | 119 | "preemption\n"); |
117 | return -ENOMEM; | 120 | return -ENOMEM; |
@@ -129,7 +132,7 @@ void intel_guc_fini_wq(struct intel_guc *guc) | |||
129 | USES_GUC_SUBMISSION(dev_priv)) | 132 | USES_GUC_SUBMISSION(dev_priv)) |
130 | destroy_workqueue(guc->preempt_wq); | 133 | destroy_workqueue(guc->preempt_wq); |
131 | 134 | ||
132 | destroy_workqueue(guc->log.runtime.flush_wq); | 135 | destroy_workqueue(guc->log.relay.flush_wq); |
133 | } | 136 | } |
134 | 137 | ||
135 | static int guc_shared_data_create(struct intel_guc *guc) | 138 | static int guc_shared_data_create(struct intel_guc *guc) |
@@ -169,7 +172,7 @@ int intel_guc_init(struct intel_guc *guc) | |||
169 | return ret; | 172 | return ret; |
170 | GEM_BUG_ON(!guc->shared_data); | 173 | GEM_BUG_ON(!guc->shared_data); |
171 | 174 | ||
172 | ret = intel_guc_log_create(guc); | 175 | ret = intel_guc_log_create(&guc->log); |
173 | if (ret) | 176 | if (ret) |
174 | goto err_shared; | 177 | goto err_shared; |
175 | 178 | ||
@@ -184,7 +187,7 @@ int intel_guc_init(struct intel_guc *guc) | |||
184 | return 0; | 187 | return 0; |
185 | 188 | ||
186 | err_log: | 189 | err_log: |
187 | intel_guc_log_destroy(guc); | 190 | intel_guc_log_destroy(&guc->log); |
188 | err_shared: | 191 | err_shared: |
189 | guc_shared_data_destroy(guc); | 192 | guc_shared_data_destroy(guc); |
190 | return ret; | 193 | return ret; |
@@ -196,7 +199,7 @@ void intel_guc_fini(struct intel_guc *guc) | |||
196 | 199 | ||
197 | i915_ggtt_disable_guc(dev_priv); | 200 | i915_ggtt_disable_guc(dev_priv); |
198 | intel_guc_ads_destroy(guc); | 201 | intel_guc_ads_destroy(guc); |
199 | intel_guc_log_destroy(guc); | 202 | intel_guc_log_destroy(&guc->log); |
200 | guc_shared_data_destroy(guc); | 203 | guc_shared_data_destroy(guc); |
201 | } | 204 | } |
202 | 205 | ||
@@ -220,17 +223,23 @@ static u32 get_core_family(struct drm_i915_private *dev_priv) | |||
220 | } | 223 | } |
221 | } | 224 | } |
222 | 225 | ||
223 | static u32 get_log_verbosity_flags(void) | 226 | static u32 get_log_control_flags(void) |
224 | { | 227 | { |
225 | if (i915_modparams.guc_log_level > 0) { | 228 | u32 level = i915_modparams.guc_log_level; |
226 | u32 verbosity = i915_modparams.guc_log_level - 1; | 229 | u32 flags = 0; |
227 | 230 | ||
228 | GEM_BUG_ON(verbosity > GUC_LOG_VERBOSITY_MAX); | 231 | GEM_BUG_ON(level < 0); |
229 | return verbosity << GUC_LOG_VERBOSITY_SHIFT; | 232 | |
230 | } | 233 | if (!GUC_LOG_LEVEL_IS_ENABLED(level)) |
234 | flags |= GUC_LOG_DEFAULT_DISABLED; | ||
235 | |||
236 | if (!GUC_LOG_LEVEL_IS_VERBOSE(level)) | ||
237 | flags |= GUC_LOG_DISABLED; | ||
238 | else | ||
239 | flags |= GUC_LOG_LEVEL_TO_VERBOSITY(level) << | ||
240 | GUC_LOG_VERBOSITY_SHIFT; | ||
231 | 241 | ||
232 | GEM_BUG_ON(i915_modparams.enable_guc < 0); | 242 | return flags; |
233 | return GUC_LOG_DISABLED; | ||
234 | } | 243 | } |
235 | 244 | ||
236 | /* | 245 | /* |
@@ -265,12 +274,13 @@ void intel_guc_init_params(struct intel_guc *guc) | |||
265 | 274 | ||
266 | params[GUC_CTL_LOG_PARAMS] = guc->log.flags; | 275 | params[GUC_CTL_LOG_PARAMS] = guc->log.flags; |
267 | 276 | ||
268 | params[GUC_CTL_DEBUG] = get_log_verbosity_flags(); | 277 | params[GUC_CTL_DEBUG] = get_log_control_flags(); |
269 | 278 | ||
270 | /* If GuC submission is enabled, set up additional parameters here */ | 279 | /* If GuC submission is enabled, set up additional parameters here */ |
271 | if (USES_GUC_SUBMISSION(dev_priv)) { | 280 | if (USES_GUC_SUBMISSION(dev_priv)) { |
272 | u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; | 281 | u32 ads = intel_guc_ggtt_offset(guc, |
273 | u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); | 282 | guc->ads_vma) >> PAGE_SHIFT; |
283 | u32 pgs = intel_guc_ggtt_offset(guc, guc->stage_desc_pool); | ||
274 | u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; | 284 | u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; |
275 | 285 | ||
276 | params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; | 286 | params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; |
@@ -301,16 +311,23 @@ void intel_guc_init_params(struct intel_guc *guc) | |||
301 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_BLITTER); | 311 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_BLITTER); |
302 | } | 312 | } |
303 | 313 | ||
304 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len) | 314 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len, |
315 | u32 *response_buf, u32 response_buf_size) | ||
305 | { | 316 | { |
306 | WARN(1, "Unexpected send: action=%#x\n", *action); | 317 | WARN(1, "Unexpected send: action=%#x\n", *action); |
307 | return -ENODEV; | 318 | return -ENODEV; |
308 | } | 319 | } |
309 | 320 | ||
321 | void intel_guc_to_host_event_handler_nop(struct intel_guc *guc) | ||
322 | { | ||
323 | WARN(1, "Unexpected event: no suitable handler\n"); | ||
324 | } | ||
325 | |||
310 | /* | 326 | /* |
311 | * This function implements the MMIO based host to GuC interface. | 327 | * This function implements the MMIO based host to GuC interface. |
312 | */ | 328 | */ |
313 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) | 329 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len, |
330 | u32 *response_buf, u32 response_buf_size) | ||
314 | { | 331 | { |
315 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 332 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
316 | u32 status; | 333 | u32 status; |
@@ -320,6 +337,9 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) | |||
320 | GEM_BUG_ON(!len); | 337 | GEM_BUG_ON(!len); |
321 | GEM_BUG_ON(len > guc->send_regs.count); | 338 | GEM_BUG_ON(len > guc->send_regs.count); |
322 | 339 | ||
340 | /* We expect only action code */ | ||
341 | GEM_BUG_ON(*action & ~INTEL_GUC_MSG_CODE_MASK); | ||
342 | |||
323 | /* If CT is available, we expect to use MMIO only during init/fini */ | 343 | /* If CT is available, we expect to use MMIO only during init/fini */ |
324 | GEM_BUG_ON(HAS_GUC_CT(dev_priv) && | 344 | GEM_BUG_ON(HAS_GUC_CT(dev_priv) && |
325 | *action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER && | 345 | *action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER && |
@@ -341,29 +361,74 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) | |||
341 | */ | 361 | */ |
342 | ret = __intel_wait_for_register_fw(dev_priv, | 362 | ret = __intel_wait_for_register_fw(dev_priv, |
343 | guc_send_reg(guc, 0), | 363 | guc_send_reg(guc, 0), |
344 | INTEL_GUC_RECV_MASK, | 364 | INTEL_GUC_MSG_TYPE_MASK, |
345 | INTEL_GUC_RECV_MASK, | 365 | INTEL_GUC_MSG_TYPE_RESPONSE << |
366 | INTEL_GUC_MSG_TYPE_SHIFT, | ||
346 | 10, 10, &status); | 367 | 10, 10, &status); |
347 | if (status != INTEL_GUC_STATUS_SUCCESS) { | 368 | /* If GuC explicitly returned an error, convert it to -EIO */ |
348 | /* | 369 | if (!ret && !INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(status)) |
349 | * Either the GuC explicitly returned an error (which | 370 | ret = -EIO; |
350 | * we convert to -EIO here) or no response at all was | 371 | |
351 | * received within the timeout limit (-ETIMEDOUT) | 372 | if (ret) { |
352 | */ | 373 | DRM_DEBUG_DRIVER("INTEL_GUC_SEND: Action 0x%X failed;" |
353 | if (ret != -ETIMEDOUT) | 374 | " ret=%d status=0x%08X response=0x%08X\n", |
354 | ret = -EIO; | 375 | action[0], ret, status, |
355 | 376 | I915_READ(SOFT_SCRATCH(15))); | |
356 | DRM_WARN("INTEL_GUC_SEND: Action 0x%X failed;" | 377 | goto out; |
357 | " ret=%d status=0x%08X response=0x%08X\n", | ||
358 | action[0], ret, status, I915_READ(SOFT_SCRATCH(15))); | ||
359 | } | 378 | } |
360 | 379 | ||
380 | if (response_buf) { | ||
381 | int count = min(response_buf_size, guc->send_regs.count - 1); | ||
382 | |||
383 | for (i = 0; i < count; i++) | ||
384 | response_buf[i] = I915_READ(guc_send_reg(guc, i + 1)); | ||
385 | } | ||
386 | |||
387 | /* Use data from the GuC response as our return value */ | ||
388 | ret = INTEL_GUC_MSG_TO_DATA(status); | ||
389 | |||
390 | out: | ||
361 | intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains); | 391 | intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains); |
362 | mutex_unlock(&guc->send_mutex); | 392 | mutex_unlock(&guc->send_mutex); |
363 | 393 | ||
364 | return ret; | 394 | return ret; |
365 | } | 395 | } |
366 | 396 | ||
397 | void intel_guc_to_host_event_handler_mmio(struct intel_guc *guc) | ||
398 | { | ||
399 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
400 | u32 msg, val; | ||
401 | |||
402 | /* | ||
403 | * Sample the log buffer flush related bits & clear them out now | ||
404 | * itself from the message identity register to minimize the | ||
405 | * probability of losing a flush interrupt, when there are back | ||
406 | * to back flush interrupts. | ||
407 | * There can be a new flush interrupt, for different log buffer | ||
408 | * type (like for ISR), whilst Host is handling one (for DPC). | ||
409 | * Since same bit is used in message register for ISR & DPC, it | ||
410 | * could happen that GuC sets the bit for 2nd interrupt but Host | ||
411 | * clears out the bit on handling the 1st interrupt. | ||
412 | */ | ||
413 | spin_lock(&guc->irq_lock); | ||
414 | val = I915_READ(SOFT_SCRATCH(15)); | ||
415 | msg = val & guc->msg_enabled_mask; | ||
416 | I915_WRITE(SOFT_SCRATCH(15), val & ~msg); | ||
417 | spin_unlock(&guc->irq_lock); | ||
418 | |||
419 | intel_guc_to_host_process_recv_msg(guc, msg); | ||
420 | } | ||
421 | |||
422 | void intel_guc_to_host_process_recv_msg(struct intel_guc *guc, u32 msg) | ||
423 | { | ||
424 | /* Make sure to handle only enabled messages */ | ||
425 | msg &= guc->msg_enabled_mask; | ||
426 | |||
427 | if (msg & (INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER | | ||
428 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED)) | ||
429 | intel_guc_log_handle_flush_event(&guc->log); | ||
430 | } | ||
431 | |||
367 | int intel_guc_sample_forcewake(struct intel_guc *guc) | 432 | int intel_guc_sample_forcewake(struct intel_guc *guc) |
368 | { | 433 | { |
369 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 434 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
@@ -410,7 +475,7 @@ int intel_guc_suspend(struct intel_guc *guc) | |||
410 | u32 data[] = { | 475 | u32 data[] = { |
411 | INTEL_GUC_ACTION_ENTER_S_STATE, | 476 | INTEL_GUC_ACTION_ENTER_S_STATE, |
412 | GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */ | 477 | GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */ |
413 | guc_ggtt_offset(guc->shared_data) | 478 | intel_guc_ggtt_offset(guc, guc->shared_data) |
414 | }; | 479 | }; |
415 | 480 | ||
416 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); | 481 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
@@ -434,7 +499,7 @@ int intel_guc_reset_engine(struct intel_guc *guc, | |||
434 | data[3] = 0; | 499 | data[3] = 0; |
435 | data[4] = 0; | 500 | data[4] = 0; |
436 | data[5] = guc->execbuf_client->stage_id; | 501 | data[5] = guc->execbuf_client->stage_id; |
437 | data[6] = guc_ggtt_offset(guc->shared_data); | 502 | data[6] = intel_guc_ggtt_offset(guc, guc->shared_data); |
438 | 503 | ||
439 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); | 504 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
440 | } | 505 | } |
@@ -448,13 +513,66 @@ int intel_guc_resume(struct intel_guc *guc) | |||
448 | u32 data[] = { | 513 | u32 data[] = { |
449 | INTEL_GUC_ACTION_EXIT_S_STATE, | 514 | INTEL_GUC_ACTION_EXIT_S_STATE, |
450 | GUC_POWER_D0, | 515 | GUC_POWER_D0, |
451 | guc_ggtt_offset(guc->shared_data) | 516 | intel_guc_ggtt_offset(guc, guc->shared_data) |
452 | }; | 517 | }; |
453 | 518 | ||
454 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); | 519 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
455 | } | 520 | } |
456 | 521 | ||
457 | /** | 522 | /** |
523 | * DOC: GuC Address Space | ||
524 | * | ||
525 | * The layout of GuC address space is shown below: | ||
526 | * | ||
527 | * :: | ||
528 | * | ||
529 | * +==============> +====================+ <== GUC_GGTT_TOP | ||
530 | * ^ | | | ||
531 | * | | | | ||
532 | * | | DRAM | | ||
533 | * | | Memory | | ||
534 | * | | | | ||
535 | * GuC | | | ||
536 | * Address +========> +====================+ <== WOPCM Top | ||
537 | * Space ^ | HW contexts RSVD | | ||
538 | * | | | WOPCM | | ||
539 | * | | +==> +--------------------+ <== GuC WOPCM Top | ||
540 | * | GuC ^ | | | ||
541 | * | GGTT | | | | ||
542 | * | Pin GuC | GuC | | ||
543 | * | Bias WOPCM | WOPCM | | ||
544 | * | | Size | | | ||
545 | * | | | | | | ||
546 | * v v v | | | ||
547 | * +=====+=====+==> +====================+ <== GuC WOPCM Base | ||
548 | * | Non-GuC WOPCM | | ||
549 | * | (HuC/Reserved) | | ||
550 | * +====================+ <== WOPCM Base | ||
551 | * | ||
552 | * The lower part of GuC Address Space [0, ggtt_pin_bias) is mapped to WOPCM | ||
553 | * while upper part of GuC Address Space [ggtt_pin_bias, GUC_GGTT_TOP) is mapped | ||
554 | * to DRAM. The value of the GuC ggtt_pin_bias is determined by WOPCM size and | ||
555 | * actual GuC WOPCM size. | ||
556 | */ | ||
557 | |||
558 | /** | ||
559 | * intel_guc_init_ggtt_pin_bias() - Initialize the GuC ggtt_pin_bias value. | ||
560 | * @guc: intel_guc structure. | ||
561 | * | ||
562 | * This function will calculate and initialize the ggtt_pin_bias value based on | ||
563 | * overall WOPCM size and GuC WOPCM size. | ||
564 | */ | ||
565 | void intel_guc_init_ggtt_pin_bias(struct intel_guc *guc) | ||
566 | { | ||
567 | struct drm_i915_private *i915 = guc_to_i915(guc); | ||
568 | |||
569 | GEM_BUG_ON(!i915->wopcm.size); | ||
570 | GEM_BUG_ON(i915->wopcm.size < i915->wopcm.guc.base); | ||
571 | |||
572 | guc->ggtt_pin_bias = i915->wopcm.size - i915->wopcm.guc.base; | ||
573 | } | ||
574 | |||
575 | /** | ||
458 | * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage | 576 | * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage |
459 | * @guc: the guc | 577 | * @guc: the guc |
460 | * @size: size of area to allocate (both virtual space and memory) | 578 | * @size: size of area to allocate (both virtual space and memory) |
@@ -462,7 +580,7 @@ int intel_guc_resume(struct intel_guc *guc) | |||
462 | * This is a wrapper to create an object for use with the GuC. In order to | 580 | * This is a wrapper to create an object for use with the GuC. In order to |
463 | * use it inside the GuC, an object needs to be pinned lifetime, so we allocate | 581 | * use it inside the GuC, an object needs to be pinned lifetime, so we allocate |
464 | * both some backing storage and a range inside the Global GTT. We must pin | 582 | * both some backing storage and a range inside the Global GTT. We must pin |
465 | * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because that | 583 | * it in the GGTT somewhere other than than [0, GUC ggtt_pin_bias) because that |
466 | * range is reserved inside GuC. | 584 | * range is reserved inside GuC. |
467 | * | 585 | * |
468 | * Return: A i915_vma if successful, otherwise an ERR_PTR. | 586 | * Return: A i915_vma if successful, otherwise an ERR_PTR. |
@@ -483,7 +601,7 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) | |||
483 | goto err; | 601 | goto err; |
484 | 602 | ||
485 | ret = i915_vma_pin(vma, 0, PAGE_SIZE, | 603 | ret = i915_vma_pin(vma, 0, PAGE_SIZE, |
486 | PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); | 604 | PIN_GLOBAL | PIN_OFFSET_BIAS | guc->ggtt_pin_bias); |
487 | if (ret) { | 605 | if (ret) { |
488 | vma = ERR_PTR(ret); | 606 | vma = ERR_PTR(ret); |
489 | goto err; | 607 | goto err; |
@@ -495,14 +613,3 @@ err: | |||
495 | i915_gem_object_put(obj); | 613 | i915_gem_object_put(obj); |
496 | return vma; | 614 | return vma; |
497 | } | 615 | } |
498 | |||
499 | u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv) | ||
500 | { | ||
501 | u32 wopcm_size = GUC_WOPCM_TOP; | ||
502 | |||
503 | /* On BXT, the top of WOPCM is reserved for RC6 context */ | ||
504 | if (IS_GEN9_LP(dev_priv)) | ||
505 | wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED; | ||
506 | |||
507 | return wopcm_size; | ||
508 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index b9424ac644ac..f1265e122d30 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h | |||
@@ -49,11 +49,16 @@ struct intel_guc { | |||
49 | struct intel_guc_log log; | 49 | struct intel_guc_log log; |
50 | struct intel_guc_ct ct; | 50 | struct intel_guc_ct ct; |
51 | 51 | ||
52 | /* Offset where Non-WOPCM memory starts. */ | ||
53 | u32 ggtt_pin_bias; | ||
54 | |||
52 | /* Log snapshot if GuC errors during load */ | 55 | /* Log snapshot if GuC errors during load */ |
53 | struct drm_i915_gem_object *load_err_log; | 56 | struct drm_i915_gem_object *load_err_log; |
54 | 57 | ||
55 | /* intel_guc_recv interrupt related state */ | 58 | /* intel_guc_recv interrupt related state */ |
59 | spinlock_t irq_lock; | ||
56 | bool interrupts_enabled; | 60 | bool interrupts_enabled; |
61 | unsigned int msg_enabled_mask; | ||
57 | 62 | ||
58 | struct i915_vma *ads_vma; | 63 | struct i915_vma *ads_vma; |
59 | struct i915_vma *stage_desc_pool; | 64 | struct i915_vma *stage_desc_pool; |
@@ -83,7 +88,11 @@ struct intel_guc { | |||
83 | struct mutex send_mutex; | 88 | struct mutex send_mutex; |
84 | 89 | ||
85 | /* GuC's FW specific send function */ | 90 | /* GuC's FW specific send function */ |
86 | int (*send)(struct intel_guc *guc, const u32 *data, u32 len); | 91 | int (*send)(struct intel_guc *guc, const u32 *data, u32 len, |
92 | u32 *response_buf, u32 response_buf_size); | ||
93 | |||
94 | /* GuC's FW specific event handler function */ | ||
95 | void (*handler)(struct intel_guc *guc); | ||
87 | 96 | ||
88 | /* GuC's FW specific notify function */ | 97 | /* GuC's FW specific notify function */ |
89 | void (*notify)(struct intel_guc *guc); | 98 | void (*notify)(struct intel_guc *guc); |
@@ -92,7 +101,14 @@ struct intel_guc { | |||
92 | static | 101 | static |
93 | inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | 102 | inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) |
94 | { | 103 | { |
95 | return guc->send(guc, action, len); | 104 | return guc->send(guc, action, len, NULL, 0); |
105 | } | ||
106 | |||
107 | static inline int | ||
108 | intel_guc_send_and_receive(struct intel_guc *guc, const u32 *action, u32 len, | ||
109 | u32 *response_buf, u32 response_buf_size) | ||
110 | { | ||
111 | return guc->send(guc, action, len, response_buf, response_buf_size); | ||
96 | } | 112 | } |
97 | 113 | ||
98 | static inline void intel_guc_notify(struct intel_guc *guc) | 114 | static inline void intel_guc_notify(struct intel_guc *guc) |
@@ -100,17 +116,33 @@ static inline void intel_guc_notify(struct intel_guc *guc) | |||
100 | guc->notify(guc); | 116 | guc->notify(guc); |
101 | } | 117 | } |
102 | 118 | ||
103 | /* | 119 | static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) |
104 | * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), | 120 | { |
105 | * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is | 121 | guc->handler(guc); |
106 | * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects | 122 | } |
107 | * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. | 123 | |
124 | /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ | ||
125 | #define GUC_GGTT_TOP 0xFEE00000 | ||
126 | |||
127 | /** | ||
128 | * intel_guc_ggtt_offset() - Get and validate the GGTT offset of @vma | ||
129 | * @guc: intel_guc structure. | ||
130 | * @vma: i915 graphics virtual memory area. | ||
131 | * | ||
132 | * GuC does not allow any gfx GGTT address that falls into range | ||
133 | * [0, GuC ggtt_pin_bias), which is reserved for Boot ROM, SRAM and WOPCM. | ||
134 | * Currently, in order to exclude [0, GuC ggtt_pin_bias) address space from | ||
135 | * GGTT, all gfx objects used by GuC are allocated with intel_guc_allocate_vma() | ||
136 | * and pinned with PIN_OFFSET_BIAS along with the value of GuC ggtt_pin_bias. | ||
137 | * | ||
138 | * Return: GGTT offset of the @vma. | ||
108 | */ | 139 | */ |
109 | static inline u32 guc_ggtt_offset(struct i915_vma *vma) | 140 | static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc, |
141 | struct i915_vma *vma) | ||
110 | { | 142 | { |
111 | u32 offset = i915_ggtt_offset(vma); | 143 | u32 offset = i915_ggtt_offset(vma); |
112 | 144 | ||
113 | GEM_BUG_ON(offset < GUC_WOPCM_TOP); | 145 | GEM_BUG_ON(offset < guc->ggtt_pin_bias); |
114 | GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); | 146 | GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); |
115 | 147 | ||
116 | return offset; | 148 | return offset; |
@@ -119,17 +151,43 @@ static inline u32 guc_ggtt_offset(struct i915_vma *vma) | |||
119 | void intel_guc_init_early(struct intel_guc *guc); | 151 | void intel_guc_init_early(struct intel_guc *guc); |
120 | void intel_guc_init_send_regs(struct intel_guc *guc); | 152 | void intel_guc_init_send_regs(struct intel_guc *guc); |
121 | void intel_guc_init_params(struct intel_guc *guc); | 153 | void intel_guc_init_params(struct intel_guc *guc); |
154 | void intel_guc_init_ggtt_pin_bias(struct intel_guc *guc); | ||
122 | int intel_guc_init_wq(struct intel_guc *guc); | 155 | int intel_guc_init_wq(struct intel_guc *guc); |
123 | void intel_guc_fini_wq(struct intel_guc *guc); | 156 | void intel_guc_fini_wq(struct intel_guc *guc); |
124 | int intel_guc_init(struct intel_guc *guc); | 157 | int intel_guc_init(struct intel_guc *guc); |
125 | void intel_guc_fini(struct intel_guc *guc); | 158 | void intel_guc_fini(struct intel_guc *guc); |
126 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); | 159 | int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len, |
127 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); | 160 | u32 *response_buf, u32 response_buf_size); |
161 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len, | ||
162 | u32 *response_buf, u32 response_buf_size); | ||
163 | void intel_guc_to_host_event_handler(struct intel_guc *guc); | ||
164 | void intel_guc_to_host_event_handler_nop(struct intel_guc *guc); | ||
165 | void intel_guc_to_host_event_handler_mmio(struct intel_guc *guc); | ||
166 | void intel_guc_to_host_process_recv_msg(struct intel_guc *guc, u32 msg); | ||
128 | int intel_guc_sample_forcewake(struct intel_guc *guc); | 167 | int intel_guc_sample_forcewake(struct intel_guc *guc); |
129 | int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); | 168 | int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); |
130 | int intel_guc_suspend(struct intel_guc *guc); | 169 | int intel_guc_suspend(struct intel_guc *guc); |
131 | int intel_guc_resume(struct intel_guc *guc); | 170 | int intel_guc_resume(struct intel_guc *guc); |
132 | struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); | 171 | struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); |
133 | u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); | 172 | |
173 | static inline int intel_guc_sanitize(struct intel_guc *guc) | ||
174 | { | ||
175 | intel_uc_fw_sanitize(&guc->fw); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static inline void intel_guc_enable_msg(struct intel_guc *guc, u32 mask) | ||
180 | { | ||
181 | spin_lock_irq(&guc->irq_lock); | ||
182 | guc->msg_enabled_mask |= mask; | ||
183 | spin_unlock_irq(&guc->irq_lock); | ||
184 | } | ||
185 | |||
186 | static inline void intel_guc_disable_msg(struct intel_guc *guc, u32 mask) | ||
187 | { | ||
188 | spin_lock_irq(&guc->irq_lock); | ||
189 | guc->msg_enabled_mask &= ~mask; | ||
190 | spin_unlock_irq(&guc->irq_lock); | ||
191 | } | ||
134 | 192 | ||
135 | #endif | 193 | #endif |
diff --git a/drivers/gpu/drm/i915/intel_guc_ads.c b/drivers/gpu/drm/i915/intel_guc_ads.c index ac627534667d..334cb5202e1c 100644 --- a/drivers/gpu/drm/i915/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/intel_guc_ads.c | |||
@@ -75,7 +75,7 @@ static void guc_policies_init(struct guc_policies *policies) | |||
75 | int intel_guc_ads_create(struct intel_guc *guc) | 75 | int intel_guc_ads_create(struct intel_guc *guc) |
76 | { | 76 | { |
77 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 77 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
78 | struct i915_vma *vma; | 78 | struct i915_vma *vma, *kernel_ctx_vma; |
79 | struct page *page; | 79 | struct page *page; |
80 | /* The ads obj includes the struct itself and buffers passed to GuC */ | 80 | /* The ads obj includes the struct itself and buffers passed to GuC */ |
81 | struct { | 81 | struct { |
@@ -121,9 +121,9 @@ int intel_guc_ads_create(struct intel_guc *guc) | |||
121 | * to find it. Note that we have to skip our header (1 page), | 121 | * to find it. Note that we have to skip our header (1 page), |
122 | * because our GuC shared data is there. | 122 | * because our GuC shared data is there. |
123 | */ | 123 | */ |
124 | kernel_ctx_vma = dev_priv->kernel_context->engine[RCS].state; | ||
124 | blob->ads.golden_context_lrca = | 125 | blob->ads.golden_context_lrca = |
125 | guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + | 126 | intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset; |
126 | skipped_offset; | ||
127 | 127 | ||
128 | /* | 128 | /* |
129 | * The GuC expects us to exclude the portion of the context image that | 129 | * The GuC expects us to exclude the portion of the context image that |
@@ -135,7 +135,7 @@ int intel_guc_ads_create(struct intel_guc *guc) | |||
135 | blob->ads.eng_state_size[engine->guc_id] = | 135 | blob->ads.eng_state_size[engine->guc_id] = |
136 | engine->context_size - skipped_size; | 136 | engine->context_size - skipped_size; |
137 | 137 | ||
138 | base = guc_ggtt_offset(vma); | 138 | base = intel_guc_ggtt_offset(guc, vma); |
139 | blob->ads.scheduler_policies = base + ptr_offset(blob, policies); | 139 | blob->ads.scheduler_policies = base + ptr_offset(blob, policies); |
140 | blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer); | 140 | blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer); |
141 | blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); | 141 | blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); |
diff --git a/drivers/gpu/drm/i915/intel_guc_ct.c b/drivers/gpu/drm/i915/intel_guc_ct.c index 24ad55752396..371b6005954a 100644 --- a/drivers/gpu/drm/i915/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/intel_guc_ct.c | |||
@@ -24,14 +24,49 @@ | |||
24 | #include "i915_drv.h" | 24 | #include "i915_drv.h" |
25 | #include "intel_guc_ct.h" | 25 | #include "intel_guc_ct.h" |
26 | 26 | ||
27 | #ifdef CONFIG_DRM_I915_DEBUG_GUC | ||
28 | #define CT_DEBUG_DRIVER(...) DRM_DEBUG_DRIVER(__VA_ARGS__) | ||
29 | #else | ||
30 | #define CT_DEBUG_DRIVER(...) do { } while (0) | ||
31 | #endif | ||
32 | |||
33 | struct ct_request { | ||
34 | struct list_head link; | ||
35 | u32 fence; | ||
36 | u32 status; | ||
37 | u32 response_len; | ||
38 | u32 *response_buf; | ||
39 | }; | ||
40 | |||
41 | struct ct_incoming_request { | ||
42 | struct list_head link; | ||
43 | u32 msg[]; | ||
44 | }; | ||
45 | |||
27 | enum { CTB_SEND = 0, CTB_RECV = 1 }; | 46 | enum { CTB_SEND = 0, CTB_RECV = 1 }; |
28 | 47 | ||
29 | enum { CTB_OWNER_HOST = 0 }; | 48 | enum { CTB_OWNER_HOST = 0 }; |
30 | 49 | ||
50 | static void ct_incoming_request_worker_func(struct work_struct *w); | ||
51 | |||
52 | /** | ||
53 | * intel_guc_ct_init_early - Initialize CT state without requiring device access | ||
54 | * @ct: pointer to CT struct | ||
55 | */ | ||
31 | void intel_guc_ct_init_early(struct intel_guc_ct *ct) | 56 | void intel_guc_ct_init_early(struct intel_guc_ct *ct) |
32 | { | 57 | { |
33 | /* we're using static channel owners */ | 58 | /* we're using static channel owners */ |
34 | ct->host_channel.owner = CTB_OWNER_HOST; | 59 | ct->host_channel.owner = CTB_OWNER_HOST; |
60 | |||
61 | spin_lock_init(&ct->lock); | ||
62 | INIT_LIST_HEAD(&ct->pending_requests); | ||
63 | INIT_LIST_HEAD(&ct->incoming_requests); | ||
64 | INIT_WORK(&ct->worker, ct_incoming_request_worker_func); | ||
65 | } | ||
66 | |||
67 | static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct) | ||
68 | { | ||
69 | return container_of(ct, struct intel_guc, ct); | ||
35 | } | 70 | } |
36 | 71 | ||
37 | static inline const char *guc_ct_buffer_type_to_str(u32 type) | 72 | static inline const char *guc_ct_buffer_type_to_str(u32 type) |
@@ -49,8 +84,8 @@ static inline const char *guc_ct_buffer_type_to_str(u32 type) | |||
49 | static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, | 84 | static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, |
50 | u32 cmds_addr, u32 size, u32 owner) | 85 | u32 cmds_addr, u32 size, u32 owner) |
51 | { | 86 | { |
52 | DRM_DEBUG_DRIVER("CT: desc %p init addr=%#x size=%u owner=%u\n", | 87 | CT_DEBUG_DRIVER("CT: desc %p init addr=%#x size=%u owner=%u\n", |
53 | desc, cmds_addr, size, owner); | 88 | desc, cmds_addr, size, owner); |
54 | memset(desc, 0, sizeof(*desc)); | 89 | memset(desc, 0, sizeof(*desc)); |
55 | desc->addr = cmds_addr; | 90 | desc->addr = cmds_addr; |
56 | desc->size = size; | 91 | desc->size = size; |
@@ -59,8 +94,8 @@ static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, | |||
59 | 94 | ||
60 | static void guc_ct_buffer_desc_reset(struct guc_ct_buffer_desc *desc) | 95 | static void guc_ct_buffer_desc_reset(struct guc_ct_buffer_desc *desc) |
61 | { | 96 | { |
62 | DRM_DEBUG_DRIVER("CT: desc %p reset head=%u tail=%u\n", | 97 | CT_DEBUG_DRIVER("CT: desc %p reset head=%u tail=%u\n", |
63 | desc, desc->head, desc->tail); | 98 | desc, desc->head, desc->tail); |
64 | desc->head = 0; | 99 | desc->head = 0; |
65 | desc->tail = 0; | 100 | desc->tail = 0; |
66 | desc->is_in_error = 0; | 101 | desc->is_in_error = 0; |
@@ -79,7 +114,7 @@ static int guc_action_register_ct_buffer(struct intel_guc *guc, | |||
79 | int err; | 114 | int err; |
80 | 115 | ||
81 | /* Can't use generic send(), CT registration must go over MMIO */ | 116 | /* Can't use generic send(), CT registration must go over MMIO */ |
82 | err = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action)); | 117 | err = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); |
83 | if (err) | 118 | if (err) |
84 | DRM_ERROR("CT: register %s buffer failed; err=%d\n", | 119 | DRM_ERROR("CT: register %s buffer failed; err=%d\n", |
85 | guc_ct_buffer_type_to_str(type), err); | 120 | guc_ct_buffer_type_to_str(type), err); |
@@ -98,7 +133,7 @@ static int guc_action_deregister_ct_buffer(struct intel_guc *guc, | |||
98 | int err; | 133 | int err; |
99 | 134 | ||
100 | /* Can't use generic send(), CT deregistration must go over MMIO */ | 135 | /* Can't use generic send(), CT deregistration must go over MMIO */ |
101 | err = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action)); | 136 | err = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); |
102 | if (err) | 137 | if (err) |
103 | DRM_ERROR("CT: deregister %s buffer failed; owner=%d err=%d\n", | 138 | DRM_ERROR("CT: deregister %s buffer failed; owner=%d err=%d\n", |
104 | guc_ct_buffer_type_to_str(type), owner, err); | 139 | guc_ct_buffer_type_to_str(type), owner, err); |
@@ -156,7 +191,8 @@ static int ctch_init(struct intel_guc *guc, | |||
156 | err = PTR_ERR(blob); | 191 | err = PTR_ERR(blob); |
157 | goto err_vma; | 192 | goto err_vma; |
158 | } | 193 | } |
159 | DRM_DEBUG_DRIVER("CT: vma base=%#x\n", guc_ggtt_offset(ctch->vma)); | 194 | CT_DEBUG_DRIVER("CT: vma base=%#x\n", |
195 | intel_guc_ggtt_offset(guc, ctch->vma)); | ||
160 | 196 | ||
161 | /* store pointers to desc and cmds */ | 197 | /* store pointers to desc and cmds */ |
162 | for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) { | 198 | for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) { |
@@ -170,8 +206,8 @@ static int ctch_init(struct intel_guc *guc, | |||
170 | err_vma: | 206 | err_vma: |
171 | i915_vma_unpin_and_release(&ctch->vma); | 207 | i915_vma_unpin_and_release(&ctch->vma); |
172 | err_out: | 208 | err_out: |
173 | DRM_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", | 209 | CT_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", |
174 | ctch->owner, err); | 210 | ctch->owner, err); |
175 | return err; | 211 | return err; |
176 | } | 212 | } |
177 | 213 | ||
@@ -191,8 +227,8 @@ static int ctch_open(struct intel_guc *guc, | |||
191 | int err; | 227 | int err; |
192 | int i; | 228 | int i; |
193 | 229 | ||
194 | DRM_DEBUG_DRIVER("CT: channel %d reopen=%s\n", | 230 | CT_DEBUG_DRIVER("CT: channel %d reopen=%s\n", |
195 | ctch->owner, yesno(ctch_is_open(ctch))); | 231 | ctch->owner, yesno(ctch_is_open(ctch))); |
196 | 232 | ||
197 | if (!ctch->vma) { | 233 | if (!ctch->vma) { |
198 | err = ctch_init(guc, ctch); | 234 | err = ctch_init(guc, ctch); |
@@ -202,7 +238,7 @@ static int ctch_open(struct intel_guc *guc, | |||
202 | } | 238 | } |
203 | 239 | ||
204 | /* vma should be already allocated and map'ed */ | 240 | /* vma should be already allocated and map'ed */ |
205 | base = guc_ggtt_offset(ctch->vma); | 241 | base = intel_guc_ggtt_offset(guc, ctch->vma); |
206 | 242 | ||
207 | /* (re)initialize descriptors | 243 | /* (re)initialize descriptors |
208 | * cmds buffers are in the second half of the blob page | 244 | * cmds buffers are in the second half of the blob page |
@@ -263,10 +299,29 @@ static u32 ctch_get_next_fence(struct intel_guc_ct_channel *ctch) | |||
263 | return ++ctch->next_fence; | 299 | return ++ctch->next_fence; |
264 | } | 300 | } |
265 | 301 | ||
302 | /** | ||
303 | * DOC: CTB Host to GuC request | ||
304 | * | ||
305 | * Format of the CTB Host to GuC request message is as follows:: | ||
306 | * | ||
307 | * +------------+---------+---------+---------+---------+ | ||
308 | * | msg[0] | [1] | [2] | ... | [n-1] | | ||
309 | * +------------+---------+---------+---------+---------+ | ||
310 | * | MESSAGE | MESSAGE PAYLOAD | | ||
311 | * + HEADER +---------+---------+---------+---------+ | ||
312 | * | | 0 | 1 | ... | n | | ||
313 | * +============+=========+=========+=========+=========+ | ||
314 | * | len >= 1 | FENCE | request specific data | | ||
315 | * +------+-----+---------+---------+---------+---------+ | ||
316 | * | ||
317 | * ^-----------------len-------------------^ | ||
318 | */ | ||
319 | |||
266 | static int ctb_write(struct intel_guc_ct_buffer *ctb, | 320 | static int ctb_write(struct intel_guc_ct_buffer *ctb, |
267 | const u32 *action, | 321 | const u32 *action, |
268 | u32 len /* in dwords */, | 322 | u32 len /* in dwords */, |
269 | u32 fence) | 323 | u32 fence, |
324 | bool want_response) | ||
270 | { | 325 | { |
271 | struct guc_ct_buffer_desc *desc = ctb->desc; | 326 | struct guc_ct_buffer_desc *desc = ctb->desc; |
272 | u32 head = desc->head / 4; /* in dwords */ | 327 | u32 head = desc->head / 4; /* in dwords */ |
@@ -295,15 +350,21 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb, | |||
295 | if (unlikely(used + len + 1 >= size)) | 350 | if (unlikely(used + len + 1 >= size)) |
296 | return -ENOSPC; | 351 | return -ENOSPC; |
297 | 352 | ||
298 | /* Write the message. The format is the following: | 353 | /* |
354 | * Write the message. The format is the following: | ||
299 | * DW0: header (including action code) | 355 | * DW0: header (including action code) |
300 | * DW1: fence | 356 | * DW1: fence |
301 | * DW2+: action data | 357 | * DW2+: action data |
302 | */ | 358 | */ |
303 | header = (len << GUC_CT_MSG_LEN_SHIFT) | | 359 | header = (len << GUC_CT_MSG_LEN_SHIFT) | |
304 | (GUC_CT_MSG_WRITE_FENCE_TO_DESC) | | 360 | (GUC_CT_MSG_WRITE_FENCE_TO_DESC) | |
361 | (want_response ? GUC_CT_MSG_SEND_STATUS : 0) | | ||
305 | (action[0] << GUC_CT_MSG_ACTION_SHIFT); | 362 | (action[0] << GUC_CT_MSG_ACTION_SHIFT); |
306 | 363 | ||
364 | CT_DEBUG_DRIVER("CT: writing %*ph %*ph %*ph\n", | ||
365 | 4, &header, 4, &fence, | ||
366 | 4 * (len - 1), &action[1]); | ||
367 | |||
307 | cmds[tail] = header; | 368 | cmds[tail] = header; |
308 | tail = (tail + 1) % size; | 369 | tail = (tail + 1) % size; |
309 | 370 | ||
@@ -322,16 +383,25 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb, | |||
322 | return 0; | 383 | return 0; |
323 | } | 384 | } |
324 | 385 | ||
325 | /* Wait for the response from the GuC. | 386 | /** |
387 | * wait_for_ctb_desc_update - Wait for the CT buffer descriptor update. | ||
388 | * @desc: buffer descriptor | ||
326 | * @fence: response fence | 389 | * @fence: response fence |
327 | * @status: placeholder for status | 390 | * @status: placeholder for status |
328 | * return: 0 response received (status is valid) | 391 | * |
329 | * -ETIMEDOUT no response within hardcoded timeout | 392 | * Guc will update CT buffer descriptor with new fence and status |
330 | * -EPROTO no response, ct buffer was in error | 393 | * after processing the command identified by the fence. Wait for |
394 | * specified fence and then read from the descriptor status of the | ||
395 | * command. | ||
396 | * | ||
397 | * Return: | ||
398 | * * 0 response received (status is valid) | ||
399 | * * -ETIMEDOUT no response within hardcoded timeout | ||
400 | * * -EPROTO no response, CT buffer is in error | ||
331 | */ | 401 | */ |
332 | static int wait_for_response(struct guc_ct_buffer_desc *desc, | 402 | static int wait_for_ctb_desc_update(struct guc_ct_buffer_desc *desc, |
333 | u32 fence, | 403 | u32 fence, |
334 | u32 *status) | 404 | u32 *status) |
335 | { | 405 | { |
336 | int err; | 406 | int err; |
337 | 407 | ||
@@ -363,71 +433,440 @@ static int wait_for_response(struct guc_ct_buffer_desc *desc, | |||
363 | return err; | 433 | return err; |
364 | } | 434 | } |
365 | 435 | ||
366 | static int ctch_send(struct intel_guc *guc, | 436 | /** |
437 | * wait_for_ct_request_update - Wait for CT request state update. | ||
438 | * @req: pointer to pending request | ||
439 | * @status: placeholder for status | ||
440 | * | ||
441 | * For each sent request, Guc shall send bac CT response message. | ||
442 | * Our message handler will update status of tracked request once | ||
443 | * response message with given fence is received. Wait here and | ||
444 | * check for valid response status value. | ||
445 | * | ||
446 | * Return: | ||
447 | * * 0 response received (status is valid) | ||
448 | * * -ETIMEDOUT no response within hardcoded timeout | ||
449 | */ | ||
450 | static int wait_for_ct_request_update(struct ct_request *req, u32 *status) | ||
451 | { | ||
452 | int err; | ||
453 | |||
454 | /* | ||
455 | * Fast commands should complete in less than 10us, so sample quickly | ||
456 | * up to that length of time, then switch to a slower sleep-wait loop. | ||
457 | * No GuC command should ever take longer than 10ms. | ||
458 | */ | ||
459 | #define done INTEL_GUC_MSG_IS_RESPONSE(READ_ONCE(req->status)) | ||
460 | err = wait_for_us(done, 10); | ||
461 | if (err) | ||
462 | err = wait_for(done, 10); | ||
463 | #undef done | ||
464 | |||
465 | if (unlikely(err)) | ||
466 | DRM_ERROR("CT: fence %u err %d\n", req->fence, err); | ||
467 | |||
468 | *status = req->status; | ||
469 | return err; | ||
470 | } | ||
471 | |||
472 | static int ctch_send(struct intel_guc_ct *ct, | ||
367 | struct intel_guc_ct_channel *ctch, | 473 | struct intel_guc_ct_channel *ctch, |
368 | const u32 *action, | 474 | const u32 *action, |
369 | u32 len, | 475 | u32 len, |
476 | u32 *response_buf, | ||
477 | u32 response_buf_size, | ||
370 | u32 *status) | 478 | u32 *status) |
371 | { | 479 | { |
372 | struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_SEND]; | 480 | struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_SEND]; |
373 | struct guc_ct_buffer_desc *desc = ctb->desc; | 481 | struct guc_ct_buffer_desc *desc = ctb->desc; |
482 | struct ct_request request; | ||
483 | unsigned long flags; | ||
374 | u32 fence; | 484 | u32 fence; |
375 | int err; | 485 | int err; |
376 | 486 | ||
377 | GEM_BUG_ON(!ctch_is_open(ctch)); | 487 | GEM_BUG_ON(!ctch_is_open(ctch)); |
378 | GEM_BUG_ON(!len); | 488 | GEM_BUG_ON(!len); |
379 | GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK); | 489 | GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK); |
490 | GEM_BUG_ON(!response_buf && response_buf_size); | ||
380 | 491 | ||
381 | fence = ctch_get_next_fence(ctch); | 492 | fence = ctch_get_next_fence(ctch); |
382 | err = ctb_write(ctb, action, len, fence); | 493 | request.fence = fence; |
494 | request.status = 0; | ||
495 | request.response_len = response_buf_size; | ||
496 | request.response_buf = response_buf; | ||
497 | |||
498 | spin_lock_irqsave(&ct->lock, flags); | ||
499 | list_add_tail(&request.link, &ct->pending_requests); | ||
500 | spin_unlock_irqrestore(&ct->lock, flags); | ||
501 | |||
502 | err = ctb_write(ctb, action, len, fence, !!response_buf); | ||
383 | if (unlikely(err)) | 503 | if (unlikely(err)) |
384 | return err; | 504 | goto unlink; |
385 | 505 | ||
386 | intel_guc_notify(guc); | 506 | intel_guc_notify(ct_to_guc(ct)); |
387 | 507 | ||
388 | err = wait_for_response(desc, fence, status); | 508 | if (response_buf) |
509 | err = wait_for_ct_request_update(&request, status); | ||
510 | else | ||
511 | err = wait_for_ctb_desc_update(desc, fence, status); | ||
389 | if (unlikely(err)) | 512 | if (unlikely(err)) |
390 | return err; | 513 | goto unlink; |
391 | if (*status != INTEL_GUC_STATUS_SUCCESS) | 514 | |
392 | return -EIO; | 515 | if (!INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(*status)) { |
393 | return 0; | 516 | err = -EIO; |
517 | goto unlink; | ||
518 | } | ||
519 | |||
520 | if (response_buf) { | ||
521 | /* There shall be no data in the status */ | ||
522 | WARN_ON(INTEL_GUC_MSG_TO_DATA(request.status)); | ||
523 | /* Return actual response len */ | ||
524 | err = request.response_len; | ||
525 | } else { | ||
526 | /* There shall be no response payload */ | ||
527 | WARN_ON(request.response_len); | ||
528 | /* Return data decoded from the status dword */ | ||
529 | err = INTEL_GUC_MSG_TO_DATA(*status); | ||
530 | } | ||
531 | |||
532 | unlink: | ||
533 | spin_lock_irqsave(&ct->lock, flags); | ||
534 | list_del(&request.link); | ||
535 | spin_unlock_irqrestore(&ct->lock, flags); | ||
536 | |||
537 | return err; | ||
394 | } | 538 | } |
395 | 539 | ||
396 | /* | 540 | /* |
397 | * Command Transport (CT) buffer based GuC send function. | 541 | * Command Transport (CT) buffer based GuC send function. |
398 | */ | 542 | */ |
399 | static int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len) | 543 | static int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len, |
544 | u32 *response_buf, u32 response_buf_size) | ||
400 | { | 545 | { |
401 | struct intel_guc_ct_channel *ctch = &guc->ct.host_channel; | 546 | struct intel_guc_ct *ct = &guc->ct; |
547 | struct intel_guc_ct_channel *ctch = &ct->host_channel; | ||
402 | u32 status = ~0; /* undefined */ | 548 | u32 status = ~0; /* undefined */ |
403 | int err; | 549 | int ret; |
404 | 550 | ||
405 | mutex_lock(&guc->send_mutex); | 551 | mutex_lock(&guc->send_mutex); |
406 | 552 | ||
407 | err = ctch_send(guc, ctch, action, len, &status); | 553 | ret = ctch_send(ct, ctch, action, len, response_buf, response_buf_size, |
408 | if (unlikely(err)) { | 554 | &status); |
555 | if (unlikely(ret < 0)) { | ||
409 | DRM_ERROR("CT: send action %#X failed; err=%d status=%#X\n", | 556 | DRM_ERROR("CT: send action %#X failed; err=%d status=%#X\n", |
410 | action[0], err, status); | 557 | action[0], ret, status); |
558 | } else if (unlikely(ret)) { | ||
559 | CT_DEBUG_DRIVER("CT: send action %#x returned %d (%#x)\n", | ||
560 | action[0], ret, ret); | ||
411 | } | 561 | } |
412 | 562 | ||
413 | mutex_unlock(&guc->send_mutex); | 563 | mutex_unlock(&guc->send_mutex); |
414 | return err; | 564 | return ret; |
565 | } | ||
566 | |||
567 | static inline unsigned int ct_header_get_len(u32 header) | ||
568 | { | ||
569 | return (header >> GUC_CT_MSG_LEN_SHIFT) & GUC_CT_MSG_LEN_MASK; | ||
570 | } | ||
571 | |||
572 | static inline unsigned int ct_header_get_action(u32 header) | ||
573 | { | ||
574 | return (header >> GUC_CT_MSG_ACTION_SHIFT) & GUC_CT_MSG_ACTION_MASK; | ||
575 | } | ||
576 | |||
577 | static inline bool ct_header_is_response(u32 header) | ||
578 | { | ||
579 | return ct_header_get_action(header) == INTEL_GUC_ACTION_DEFAULT; | ||
580 | } | ||
581 | |||
582 | static int ctb_read(struct intel_guc_ct_buffer *ctb, u32 *data) | ||
583 | { | ||
584 | struct guc_ct_buffer_desc *desc = ctb->desc; | ||
585 | u32 head = desc->head / 4; /* in dwords */ | ||
586 | u32 tail = desc->tail / 4; /* in dwords */ | ||
587 | u32 size = desc->size / 4; /* in dwords */ | ||
588 | u32 *cmds = ctb->cmds; | ||
589 | s32 available; /* in dwords */ | ||
590 | unsigned int len; | ||
591 | unsigned int i; | ||
592 | |||
593 | GEM_BUG_ON(desc->size % 4); | ||
594 | GEM_BUG_ON(desc->head % 4); | ||
595 | GEM_BUG_ON(desc->tail % 4); | ||
596 | GEM_BUG_ON(tail >= size); | ||
597 | GEM_BUG_ON(head >= size); | ||
598 | |||
599 | /* tail == head condition indicates empty */ | ||
600 | available = tail - head; | ||
601 | if (unlikely(available == 0)) | ||
602 | return -ENODATA; | ||
603 | |||
604 | /* beware of buffer wrap case */ | ||
605 | if (unlikely(available < 0)) | ||
606 | available += size; | ||
607 | CT_DEBUG_DRIVER("CT: available %d (%u:%u)\n", available, head, tail); | ||
608 | GEM_BUG_ON(available < 0); | ||
609 | |||
610 | data[0] = cmds[head]; | ||
611 | head = (head + 1) % size; | ||
612 | |||
613 | /* message len with header */ | ||
614 | len = ct_header_get_len(data[0]) + 1; | ||
615 | if (unlikely(len > (u32)available)) { | ||
616 | DRM_ERROR("CT: incomplete message %*ph %*ph %*ph\n", | ||
617 | 4, data, | ||
618 | 4 * (head + available - 1 > size ? | ||
619 | size - head : available - 1), &cmds[head], | ||
620 | 4 * (head + available - 1 > size ? | ||
621 | available - 1 - size + head : 0), &cmds[0]); | ||
622 | return -EPROTO; | ||
623 | } | ||
624 | |||
625 | for (i = 1; i < len; i++) { | ||
626 | data[i] = cmds[head]; | ||
627 | head = (head + 1) % size; | ||
628 | } | ||
629 | CT_DEBUG_DRIVER("CT: received %*ph\n", 4 * len, data); | ||
630 | |||
631 | desc->head = head * 4; | ||
632 | return 0; | ||
415 | } | 633 | } |
416 | 634 | ||
417 | /** | 635 | /** |
418 | * Enable buffer based command transport | 636 | * DOC: CTB GuC to Host response |
637 | * | ||
638 | * Format of the CTB GuC to Host response message is as follows:: | ||
639 | * | ||
640 | * +------------+---------+---------+---------+---------+---------+ | ||
641 | * | msg[0] | [1] | [2] | [3] | ... | [n-1] | | ||
642 | * +------------+---------+---------+---------+---------+---------+ | ||
643 | * | MESSAGE | MESSAGE PAYLOAD | | ||
644 | * + HEADER +---------+---------+---------+---------+---------+ | ||
645 | * | | 0 | 1 | 2 | ... | n | | ||
646 | * +============+=========+=========+=========+=========+=========+ | ||
647 | * | len >= 2 | FENCE | STATUS | response specific data | | ||
648 | * +------+-----+---------+---------+---------+---------+---------+ | ||
649 | * | ||
650 | * ^-----------------------len-----------------------^ | ||
651 | */ | ||
652 | |||
653 | static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg) | ||
654 | { | ||
655 | u32 header = msg[0]; | ||
656 | u32 len = ct_header_get_len(header); | ||
657 | u32 msglen = len + 1; /* total message length including header */ | ||
658 | u32 fence; | ||
659 | u32 status; | ||
660 | u32 datalen; | ||
661 | struct ct_request *req; | ||
662 | bool found = false; | ||
663 | |||
664 | GEM_BUG_ON(!ct_header_is_response(header)); | ||
665 | GEM_BUG_ON(!in_irq()); | ||
666 | |||
667 | /* Response payload shall at least include fence and status */ | ||
668 | if (unlikely(len < 2)) { | ||
669 | DRM_ERROR("CT: corrupted response %*ph\n", 4 * msglen, msg); | ||
670 | return -EPROTO; | ||
671 | } | ||
672 | |||
673 | fence = msg[1]; | ||
674 | status = msg[2]; | ||
675 | datalen = len - 2; | ||
676 | |||
677 | /* Format of the status follows RESPONSE message */ | ||
678 | if (unlikely(!INTEL_GUC_MSG_IS_RESPONSE(status))) { | ||
679 | DRM_ERROR("CT: corrupted response %*ph\n", 4 * msglen, msg); | ||
680 | return -EPROTO; | ||
681 | } | ||
682 | |||
683 | CT_DEBUG_DRIVER("CT: response fence %u status %#x\n", fence, status); | ||
684 | |||
685 | spin_lock(&ct->lock); | ||
686 | list_for_each_entry(req, &ct->pending_requests, link) { | ||
687 | if (unlikely(fence != req->fence)) { | ||
688 | CT_DEBUG_DRIVER("CT: request %u awaits response\n", | ||
689 | req->fence); | ||
690 | continue; | ||
691 | } | ||
692 | if (unlikely(datalen > req->response_len)) { | ||
693 | DRM_ERROR("CT: response %u too long %*ph\n", | ||
694 | req->fence, 4 * msglen, msg); | ||
695 | datalen = 0; | ||
696 | } | ||
697 | if (datalen) | ||
698 | memcpy(req->response_buf, msg + 3, 4 * datalen); | ||
699 | req->response_len = datalen; | ||
700 | WRITE_ONCE(req->status, status); | ||
701 | found = true; | ||
702 | break; | ||
703 | } | ||
704 | spin_unlock(&ct->lock); | ||
705 | |||
706 | if (!found) | ||
707 | DRM_ERROR("CT: unsolicited response %*ph\n", 4 * msglen, msg); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static void ct_process_request(struct intel_guc_ct *ct, | ||
712 | u32 action, u32 len, const u32 *payload) | ||
713 | { | ||
714 | struct intel_guc *guc = ct_to_guc(ct); | ||
715 | |||
716 | CT_DEBUG_DRIVER("CT: request %x %*ph\n", action, 4 * len, payload); | ||
717 | |||
718 | switch (action) { | ||
719 | case INTEL_GUC_ACTION_DEFAULT: | ||
720 | if (unlikely(len < 1)) | ||
721 | goto fail_unexpected; | ||
722 | intel_guc_to_host_process_recv_msg(guc, *payload); | ||
723 | break; | ||
724 | |||
725 | default: | ||
726 | fail_unexpected: | ||
727 | DRM_ERROR("CT: unexpected request %x %*ph\n", | ||
728 | action, 4 * len, payload); | ||
729 | break; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | static bool ct_process_incoming_requests(struct intel_guc_ct *ct) | ||
734 | { | ||
735 | unsigned long flags; | ||
736 | struct ct_incoming_request *request; | ||
737 | u32 header; | ||
738 | u32 *payload; | ||
739 | bool done; | ||
740 | |||
741 | spin_lock_irqsave(&ct->lock, flags); | ||
742 | request = list_first_entry_or_null(&ct->incoming_requests, | ||
743 | struct ct_incoming_request, link); | ||
744 | if (request) | ||
745 | list_del(&request->link); | ||
746 | done = !!list_empty(&ct->incoming_requests); | ||
747 | spin_unlock_irqrestore(&ct->lock, flags); | ||
748 | |||
749 | if (!request) | ||
750 | return true; | ||
751 | |||
752 | header = request->msg[0]; | ||
753 | payload = &request->msg[1]; | ||
754 | ct_process_request(ct, | ||
755 | ct_header_get_action(header), | ||
756 | ct_header_get_len(header), | ||
757 | payload); | ||
758 | |||
759 | kfree(request); | ||
760 | return done; | ||
761 | } | ||
762 | |||
763 | static void ct_incoming_request_worker_func(struct work_struct *w) | ||
764 | { | ||
765 | struct intel_guc_ct *ct = container_of(w, struct intel_guc_ct, worker); | ||
766 | bool done; | ||
767 | |||
768 | done = ct_process_incoming_requests(ct); | ||
769 | if (!done) | ||
770 | queue_work(system_unbound_wq, &ct->worker); | ||
771 | } | ||
772 | |||
773 | /** | ||
774 | * DOC: CTB GuC to Host request | ||
775 | * | ||
776 | * Format of the CTB GuC to Host request message is as follows:: | ||
777 | * | ||
778 | * +------------+---------+---------+---------+---------+---------+ | ||
779 | * | msg[0] | [1] | [2] | [3] | ... | [n-1] | | ||
780 | * +------------+---------+---------+---------+---------+---------+ | ||
781 | * | MESSAGE | MESSAGE PAYLOAD | | ||
782 | * + HEADER +---------+---------+---------+---------+---------+ | ||
783 | * | | 0 | 1 | 2 | ... | n | | ||
784 | * +============+=========+=========+=========+=========+=========+ | ||
785 | * | len | request specific data | | ||
786 | * +------+-----+---------+---------+---------+---------+---------+ | ||
787 | * | ||
788 | * ^-----------------------len-----------------------^ | ||
789 | */ | ||
790 | |||
791 | static int ct_handle_request(struct intel_guc_ct *ct, const u32 *msg) | ||
792 | { | ||
793 | u32 header = msg[0]; | ||
794 | u32 len = ct_header_get_len(header); | ||
795 | u32 msglen = len + 1; /* total message length including header */ | ||
796 | struct ct_incoming_request *request; | ||
797 | unsigned long flags; | ||
798 | |||
799 | GEM_BUG_ON(ct_header_is_response(header)); | ||
800 | |||
801 | request = kmalloc(sizeof(*request) + 4 * msglen, GFP_ATOMIC); | ||
802 | if (unlikely(!request)) { | ||
803 | DRM_ERROR("CT: dropping request %*ph\n", 4 * msglen, msg); | ||
804 | return 0; /* XXX: -ENOMEM ? */ | ||
805 | } | ||
806 | memcpy(request->msg, msg, 4 * msglen); | ||
807 | |||
808 | spin_lock_irqsave(&ct->lock, flags); | ||
809 | list_add_tail(&request->link, &ct->incoming_requests); | ||
810 | spin_unlock_irqrestore(&ct->lock, flags); | ||
811 | |||
812 | queue_work(system_unbound_wq, &ct->worker); | ||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static void ct_process_host_channel(struct intel_guc_ct *ct) | ||
817 | { | ||
818 | struct intel_guc_ct_channel *ctch = &ct->host_channel; | ||
819 | struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_RECV]; | ||
820 | u32 msg[GUC_CT_MSG_LEN_MASK + 1]; /* one extra dw for the header */ | ||
821 | int err = 0; | ||
822 | |||
823 | if (!ctch_is_open(ctch)) | ||
824 | return; | ||
825 | |||
826 | do { | ||
827 | err = ctb_read(ctb, msg); | ||
828 | if (err) | ||
829 | break; | ||
830 | |||
831 | if (ct_header_is_response(msg[0])) | ||
832 | err = ct_handle_response(ct, msg); | ||
833 | else | ||
834 | err = ct_handle_request(ct, msg); | ||
835 | } while (!err); | ||
836 | |||
837 | if (GEM_WARN_ON(err == -EPROTO)) { | ||
838 | DRM_ERROR("CT: corrupted message detected!\n"); | ||
839 | ctb->desc->is_in_error = 1; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * When we're communicating with the GuC over CT, GuC uses events | ||
845 | * to notify us about new messages being posted on the RECV buffer. | ||
846 | */ | ||
847 | static void intel_guc_to_host_event_handler_ct(struct intel_guc *guc) | ||
848 | { | ||
849 | struct intel_guc_ct *ct = &guc->ct; | ||
850 | |||
851 | ct_process_host_channel(ct); | ||
852 | } | ||
853 | |||
854 | /** | ||
855 | * intel_guc_ct_enable - Enable buffer based command transport. | ||
856 | * @ct: pointer to CT struct | ||
857 | * | ||
419 | * Shall only be called for platforms with HAS_GUC_CT. | 858 | * Shall only be called for platforms with HAS_GUC_CT. |
420 | * @guc: the guc | 859 | * |
421 | * return: 0 on success | 860 | * Return: 0 on success, a negative errno code on failure. |
422 | * non-zero on failure | ||
423 | */ | 861 | */ |
424 | int intel_guc_enable_ct(struct intel_guc *guc) | 862 | int intel_guc_ct_enable(struct intel_guc_ct *ct) |
425 | { | 863 | { |
426 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 864 | struct intel_guc *guc = ct_to_guc(ct); |
427 | struct intel_guc_ct_channel *ctch = &guc->ct.host_channel; | 865 | struct drm_i915_private *i915 = guc_to_i915(guc); |
866 | struct intel_guc_ct_channel *ctch = &ct->host_channel; | ||
428 | int err; | 867 | int err; |
429 | 868 | ||
430 | GEM_BUG_ON(!HAS_GUC_CT(dev_priv)); | 869 | GEM_BUG_ON(!HAS_GUC_CT(i915)); |
431 | 870 | ||
432 | err = ctch_open(guc, ctch); | 871 | err = ctch_open(guc, ctch); |
433 | if (unlikely(err)) | 872 | if (unlikely(err)) |
@@ -435,21 +874,24 @@ int intel_guc_enable_ct(struct intel_guc *guc) | |||
435 | 874 | ||
436 | /* Switch into cmd transport buffer based send() */ | 875 | /* Switch into cmd transport buffer based send() */ |
437 | guc->send = intel_guc_send_ct; | 876 | guc->send = intel_guc_send_ct; |
877 | guc->handler = intel_guc_to_host_event_handler_ct; | ||
438 | DRM_INFO("CT: %s\n", enableddisabled(true)); | 878 | DRM_INFO("CT: %s\n", enableddisabled(true)); |
439 | return 0; | 879 | return 0; |
440 | } | 880 | } |
441 | 881 | ||
442 | /** | 882 | /** |
443 | * Disable buffer based command transport. | 883 | * intel_guc_ct_disable - Disable buffer based command transport. |
884 | * @ct: pointer to CT struct | ||
885 | * | ||
444 | * Shall only be called for platforms with HAS_GUC_CT. | 886 | * Shall only be called for platforms with HAS_GUC_CT. |
445 | * @guc: the guc | ||
446 | */ | 887 | */ |
447 | void intel_guc_disable_ct(struct intel_guc *guc) | 888 | void intel_guc_ct_disable(struct intel_guc_ct *ct) |
448 | { | 889 | { |
449 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 890 | struct intel_guc *guc = ct_to_guc(ct); |
450 | struct intel_guc_ct_channel *ctch = &guc->ct.host_channel; | 891 | struct drm_i915_private *i915 = guc_to_i915(guc); |
892 | struct intel_guc_ct_channel *ctch = &ct->host_channel; | ||
451 | 893 | ||
452 | GEM_BUG_ON(!HAS_GUC_CT(dev_priv)); | 894 | GEM_BUG_ON(!HAS_GUC_CT(i915)); |
453 | 895 | ||
454 | if (!ctch_is_open(ctch)) | 896 | if (!ctch_is_open(ctch)) |
455 | return; | 897 | return; |
@@ -458,5 +900,6 @@ void intel_guc_disable_ct(struct intel_guc *guc) | |||
458 | 900 | ||
459 | /* Disable send */ | 901 | /* Disable send */ |
460 | guc->send = intel_guc_send_nop; | 902 | guc->send = intel_guc_send_nop; |
903 | guc->handler = intel_guc_to_host_event_handler_nop; | ||
461 | DRM_INFO("CT: %s\n", enableddisabled(false)); | 904 | DRM_INFO("CT: %s\n", enableddisabled(false)); |
462 | } | 905 | } |
diff --git a/drivers/gpu/drm/i915/intel_guc_ct.h b/drivers/gpu/drm/i915/intel_guc_ct.h index 6d97f36fcc62..d774895ab143 100644 --- a/drivers/gpu/drm/i915/intel_guc_ct.h +++ b/drivers/gpu/drm/i915/intel_guc_ct.h | |||
@@ -75,12 +75,22 @@ struct intel_guc_ct_channel { | |||
75 | struct intel_guc_ct { | 75 | struct intel_guc_ct { |
76 | struct intel_guc_ct_channel host_channel; | 76 | struct intel_guc_ct_channel host_channel; |
77 | /* other channels are tbd */ | 77 | /* other channels are tbd */ |
78 | |||
79 | /** @lock: protects pending requests list */ | ||
80 | spinlock_t lock; | ||
81 | |||
82 | /** @pending_requests: list of requests waiting for response */ | ||
83 | struct list_head pending_requests; | ||
84 | |||
85 | /** @incoming_requests: list of incoming requests */ | ||
86 | struct list_head incoming_requests; | ||
87 | |||
88 | /** @worker: worker for handling incoming requests */ | ||
89 | struct work_struct worker; | ||
78 | }; | 90 | }; |
79 | 91 | ||
80 | void intel_guc_ct_init_early(struct intel_guc_ct *ct); | 92 | void intel_guc_ct_init_early(struct intel_guc_ct *ct); |
81 | 93 | int intel_guc_ct_enable(struct intel_guc_ct *ct); | |
82 | /* XXX: move to intel_uc.h ? don't fit there either */ | 94 | void intel_guc_ct_disable(struct intel_guc_ct *ct); |
83 | int intel_guc_enable_ct(struct intel_guc *guc); | ||
84 | void intel_guc_disable_ct(struct intel_guc *guc); | ||
85 | 95 | ||
86 | #endif /* _INTEL_GUC_CT_H_ */ | 96 | #endif /* _INTEL_GUC_CT_H_ */ |
diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index d07f2b985f1c..a9e6fcce467c 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c | |||
@@ -165,7 +165,7 @@ static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma) | |||
165 | I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size); | 165 | I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size); |
166 | 166 | ||
167 | /* Set the source address for the new blob */ | 167 | /* Set the source address for the new blob */ |
168 | offset = guc_ggtt_offset(vma) + guc_fw->header_offset; | 168 | offset = intel_guc_ggtt_offset(guc, vma) + guc_fw->header_offset; |
169 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); | 169 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); |
170 | I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); | 170 | I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); |
171 | 171 | ||
@@ -275,9 +275,8 @@ static int guc_fw_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) | |||
275 | * Called from intel_uc_init_hw() during driver load, resume from sleep and | 275 | * Called from intel_uc_init_hw() during driver load, resume from sleep and |
276 | * after a GPU reset. | 276 | * after a GPU reset. |
277 | * | 277 | * |
278 | * The firmware image should have already been fetched into memory by the | 278 | * The firmware image should have already been fetched into memory, so only |
279 | * earlier call to intel_uc_init_fw(), so here we need to only check that | 279 | * check that fetch succeeded, and then transfer the image to the h/w. |
280 | * fetch succeeded, and then transfer the image to the h/w. | ||
281 | * | 280 | * |
282 | * Return: non-zero code on error | 281 | * Return: non-zero code on error |
283 | */ | 282 | */ |
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 6a10aa6f04d3..d73673f5d30c 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h | |||
@@ -127,7 +127,7 @@ | |||
127 | #define GUC_PROFILE_ENABLED (1 << 7) | 127 | #define GUC_PROFILE_ENABLED (1 << 7) |
128 | #define GUC_WQ_TRACK_ENABLED (1 << 8) | 128 | #define GUC_WQ_TRACK_ENABLED (1 << 8) |
129 | #define GUC_ADS_ENABLED (1 << 9) | 129 | #define GUC_ADS_ENABLED (1 << 9) |
130 | #define GUC_DEBUG_RESERVED (1 << 10) | 130 | #define GUC_LOG_DEFAULT_DISABLED (1 << 10) |
131 | #define GUC_ADS_ADDR_SHIFT 11 | 131 | #define GUC_ADS_ADDR_SHIFT 11 |
132 | #define GUC_ADS_ADDR_MASK 0xfffff800 | 132 | #define GUC_ADS_ADDR_MASK 0xfffff800 |
133 | 133 | ||
@@ -327,6 +327,58 @@ struct guc_stage_desc { | |||
327 | u64 desc_private; | 327 | u64 desc_private; |
328 | } __packed; | 328 | } __packed; |
329 | 329 | ||
330 | /** | ||
331 | * DOC: CTB based communication | ||
332 | * | ||
333 | * The CTB (command transport buffer) communication between Host and GuC | ||
334 | * is based on u32 data stream written to the shared buffer. One buffer can | ||
335 | * be used to transmit data only in one direction (one-directional channel). | ||
336 | * | ||
337 | * Current status of the each buffer is stored in the buffer descriptor. | ||
338 | * Buffer descriptor holds tail and head fields that represents active data | ||
339 | * stream. The tail field is updated by the data producer (sender), and head | ||
340 | * field is updated by the data consumer (receiver):: | ||
341 | * | ||
342 | * +------------+ | ||
343 | * | DESCRIPTOR | +=================+============+========+ | ||
344 | * +============+ | | MESSAGE(s) | | | ||
345 | * | address |--------->+=================+============+========+ | ||
346 | * +------------+ | ||
347 | * | head | ^-----head--------^ | ||
348 | * +------------+ | ||
349 | * | tail | ^---------tail-----------------^ | ||
350 | * +------------+ | ||
351 | * | size | ^---------------size--------------------^ | ||
352 | * +------------+ | ||
353 | * | ||
354 | * Each message in data stream starts with the single u32 treated as a header, | ||
355 | * followed by optional set of u32 data that makes message specific payload:: | ||
356 | * | ||
357 | * +------------+---------+---------+---------+ | ||
358 | * | MESSAGE | | ||
359 | * +------------+---------+---------+---------+ | ||
360 | * | msg[0] | [1] | ... | [n-1] | | ||
361 | * +------------+---------+---------+---------+ | ||
362 | * | MESSAGE | MESSAGE PAYLOAD | | ||
363 | * + HEADER +---------+---------+---------+ | ||
364 | * | | 0 | ... | n | | ||
365 | * +======+=====+=========+=========+=========+ | ||
366 | * | 31:16| code| | | | | ||
367 | * +------+-----+ | | | | ||
368 | * | 15:5|flags| | | | | ||
369 | * +------+-----+ | | | | ||
370 | * | 4:0| len| | | | | ||
371 | * +------+-----+---------+---------+---------+ | ||
372 | * | ||
373 | * ^-------------len-------------^ | ||
374 | * | ||
375 | * The message header consists of: | ||
376 | * | ||
377 | * - **len**, indicates length of the message payload (in u32) | ||
378 | * - **code**, indicates message code | ||
379 | * - **flags**, holds various bits to control message handling | ||
380 | */ | ||
381 | |||
330 | /* | 382 | /* |
331 | * Describes single command transport buffer. | 383 | * Describes single command transport buffer. |
332 | * Used by both guc-master and clients. | 384 | * Used by both guc-master and clients. |
@@ -534,16 +586,6 @@ struct guc_log_buffer_state { | |||
534 | u32 version; | 586 | u32 version; |
535 | } __packed; | 587 | } __packed; |
536 | 588 | ||
537 | union guc_log_control { | ||
538 | struct { | ||
539 | u32 logging_enabled:1; | ||
540 | u32 reserved1:3; | ||
541 | u32 verbosity:4; | ||
542 | u32 reserved2:24; | ||
543 | }; | ||
544 | u32 value; | ||
545 | } __packed; | ||
546 | |||
547 | struct guc_ctx_report { | 589 | struct guc_ctx_report { |
548 | u32 report_return_status; | 590 | u32 report_return_status; |
549 | u32 reserved1[64]; | 591 | u32 reserved1[64]; |
@@ -570,7 +612,68 @@ struct guc_shared_ctx_data { | |||
570 | struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM]; | 612 | struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM]; |
571 | } __packed; | 613 | } __packed; |
572 | 614 | ||
573 | /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */ | 615 | /** |
616 | * DOC: MMIO based communication | ||
617 | * | ||
618 | * The MMIO based communication between Host and GuC uses software scratch | ||
619 | * registers, where first register holds data treated as message header, | ||
620 | * and other registers are used to hold message payload. | ||
621 | * | ||
622 | * For Gen9+, GuC uses software scratch registers 0xC180-0xC1B8 | ||
623 | * | ||
624 | * +-----------+---------+---------+---------+ | ||
625 | * | MMIO[0] | MMIO[1] | ... | MMIO[n] | | ||
626 | * +-----------+---------+---------+---------+ | ||
627 | * | header | optional payload | | ||
628 | * +======+====+=========+=========+=========+ | ||
629 | * | 31:28|type| | | | | ||
630 | * +------+----+ | | | | ||
631 | * | 27:16|data| | | | | ||
632 | * +------+----+ | | | | ||
633 | * | 15:0|code| | | | | ||
634 | * +------+----+---------+---------+---------+ | ||
635 | * | ||
636 | * The message header consists of: | ||
637 | * | ||
638 | * - **type**, indicates message type | ||
639 | * - **code**, indicates message code, is specific for **type** | ||
640 | * - **data**, indicates message data, optional, depends on **code** | ||
641 | * | ||
642 | * The following message **types** are supported: | ||
643 | * | ||
644 | * - **REQUEST**, indicates Host-to-GuC request, requested GuC action code | ||
645 | * must be priovided in **code** field. Optional action specific parameters | ||
646 | * can be provided in remaining payload registers or **data** field. | ||
647 | * | ||
648 | * - **RESPONSE**, indicates GuC-to-Host response from earlier GuC request, | ||
649 | * action response status will be provided in **code** field. Optional | ||
650 | * response data can be returned in remaining payload registers or **data** | ||
651 | * field. | ||
652 | */ | ||
653 | |||
654 | #define INTEL_GUC_MSG_TYPE_SHIFT 28 | ||
655 | #define INTEL_GUC_MSG_TYPE_MASK (0xF << INTEL_GUC_MSG_TYPE_SHIFT) | ||
656 | #define INTEL_GUC_MSG_DATA_SHIFT 16 | ||
657 | #define INTEL_GUC_MSG_DATA_MASK (0xFFF << INTEL_GUC_MSG_DATA_SHIFT) | ||
658 | #define INTEL_GUC_MSG_CODE_SHIFT 0 | ||
659 | #define INTEL_GUC_MSG_CODE_MASK (0xFFFF << INTEL_GUC_MSG_CODE_SHIFT) | ||
660 | |||
661 | #define __INTEL_GUC_MSG_GET(T, m) \ | ||
662 | (((m) & INTEL_GUC_MSG_ ## T ## _MASK) >> INTEL_GUC_MSG_ ## T ## _SHIFT) | ||
663 | #define INTEL_GUC_MSG_TO_TYPE(m) __INTEL_GUC_MSG_GET(TYPE, m) | ||
664 | #define INTEL_GUC_MSG_TO_DATA(m) __INTEL_GUC_MSG_GET(DATA, m) | ||
665 | #define INTEL_GUC_MSG_TO_CODE(m) __INTEL_GUC_MSG_GET(CODE, m) | ||
666 | |||
667 | enum intel_guc_msg_type { | ||
668 | INTEL_GUC_MSG_TYPE_REQUEST = 0x0, | ||
669 | INTEL_GUC_MSG_TYPE_RESPONSE = 0xF, | ||
670 | }; | ||
671 | |||
672 | #define __INTEL_GUC_MSG_TYPE_IS(T, m) \ | ||
673 | (INTEL_GUC_MSG_TO_TYPE(m) == INTEL_GUC_MSG_TYPE_ ## T) | ||
674 | #define INTEL_GUC_MSG_IS_REQUEST(m) __INTEL_GUC_MSG_TYPE_IS(REQUEST, m) | ||
675 | #define INTEL_GUC_MSG_IS_RESPONSE(m) __INTEL_GUC_MSG_TYPE_IS(RESPONSE, m) | ||
676 | |||
574 | enum intel_guc_action { | 677 | enum intel_guc_action { |
575 | INTEL_GUC_ACTION_DEFAULT = 0x0, | 678 | INTEL_GUC_ACTION_DEFAULT = 0x0, |
576 | INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2, | 679 | INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2, |
@@ -602,24 +705,22 @@ enum intel_guc_report_status { | |||
602 | INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4, | 705 | INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4, |
603 | }; | 706 | }; |
604 | 707 | ||
605 | /* | 708 | #define GUC_LOG_CONTROL_LOGGING_ENABLED (1 << 0) |
606 | * The GuC sends its response to a command by overwriting the | 709 | #define GUC_LOG_CONTROL_VERBOSITY_SHIFT 4 |
607 | * command in SS0. The response is distinguishable from a command | 710 | #define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT) |
608 | * by the fact that all the MASK bits are set. The remaining bits | 711 | #define GUC_LOG_CONTROL_DEFAULT_LOGGING (1 << 8) |
609 | * give more detail. | 712 | |
610 | */ | 713 | enum intel_guc_response_status { |
611 | #define INTEL_GUC_RECV_MASK ((u32)0xF0000000) | 714 | INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0, |
612 | #define INTEL_GUC_RECV_IS_RESPONSE(x) ((u32)(x) >= INTEL_GUC_RECV_MASK) | 715 | INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, |
613 | #define INTEL_GUC_RECV_STATUS(x) (INTEL_GUC_RECV_MASK | (x)) | ||
614 | |||
615 | /* GUC will return status back to SOFT_SCRATCH_O_REG */ | ||
616 | enum intel_guc_status { | ||
617 | INTEL_GUC_STATUS_SUCCESS = INTEL_GUC_RECV_STATUS(0x0), | ||
618 | INTEL_GUC_STATUS_ALLOCATE_DOORBELL_FAIL = INTEL_GUC_RECV_STATUS(0x10), | ||
619 | INTEL_GUC_STATUS_DEALLOCATE_DOORBELL_FAIL = INTEL_GUC_RECV_STATUS(0x20), | ||
620 | INTEL_GUC_STATUS_GENERIC_FAIL = INTEL_GUC_RECV_STATUS(0x0000F000) | ||
621 | }; | 716 | }; |
622 | 717 | ||
718 | #define INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(m) \ | ||
719 | (typecheck(u32, (m)) && \ | ||
720 | ((m) & (INTEL_GUC_MSG_TYPE_MASK | INTEL_GUC_MSG_CODE_MASK)) == \ | ||
721 | ((INTEL_GUC_MSG_TYPE_RESPONSE << INTEL_GUC_MSG_TYPE_SHIFT) | \ | ||
722 | (INTEL_GUC_RESPONSE_STATUS_SUCCESS << INTEL_GUC_MSG_CODE_SHIFT))) | ||
723 | |||
623 | /* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */ | 724 | /* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */ |
624 | enum intel_guc_recv_message { | 725 | enum intel_guc_recv_message { |
625 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1), | 726 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1), |
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c index c0c2e7d1c7d7..401e1704d61e 100644 --- a/drivers/gpu/drm/i915/intel_guc_log.c +++ b/drivers/gpu/drm/i915/intel_guc_log.c | |||
@@ -23,12 +23,11 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
26 | #include <linux/relay.h> | ||
27 | 26 | ||
28 | #include "intel_guc_log.h" | 27 | #include "intel_guc_log.h" |
29 | #include "i915_drv.h" | 28 | #include "i915_drv.h" |
30 | 29 | ||
31 | static void guc_log_capture_logs(struct intel_guc *guc); | 30 | static void guc_log_capture_logs(struct intel_guc_log *log); |
32 | 31 | ||
33 | /** | 32 | /** |
34 | * DOC: GuC firmware log | 33 | * DOC: GuC firmware log |
@@ -39,7 +38,7 @@ static void guc_log_capture_logs(struct intel_guc *guc); | |||
39 | * registers value. | 38 | * registers value. |
40 | */ | 39 | */ |
41 | 40 | ||
42 | static int guc_log_flush_complete(struct intel_guc *guc) | 41 | static int guc_action_flush_log_complete(struct intel_guc *guc) |
43 | { | 42 | { |
44 | u32 action[] = { | 43 | u32 action[] = { |
45 | INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE | 44 | INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE |
@@ -48,7 +47,7 @@ static int guc_log_flush_complete(struct intel_guc *guc) | |||
48 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 47 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
49 | } | 48 | } |
50 | 49 | ||
51 | static int guc_log_flush(struct intel_guc *guc) | 50 | static int guc_action_flush_log(struct intel_guc *guc) |
52 | { | 51 | { |
53 | u32 action[] = { | 52 | u32 action[] = { |
54 | INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH, | 53 | INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH, |
@@ -58,22 +57,40 @@ static int guc_log_flush(struct intel_guc *guc) | |||
58 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 57 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
59 | } | 58 | } |
60 | 59 | ||
61 | static int guc_log_control(struct intel_guc *guc, bool enable, u32 verbosity) | 60 | static int guc_action_control_log(struct intel_guc *guc, bool enable, |
61 | bool default_logging, u32 verbosity) | ||
62 | { | 62 | { |
63 | union guc_log_control control_val = { | ||
64 | { | ||
65 | .logging_enabled = enable, | ||
66 | .verbosity = verbosity, | ||
67 | }, | ||
68 | }; | ||
69 | u32 action[] = { | 63 | u32 action[] = { |
70 | INTEL_GUC_ACTION_UK_LOG_ENABLE_LOGGING, | 64 | INTEL_GUC_ACTION_UK_LOG_ENABLE_LOGGING, |
71 | control_val.value | 65 | (enable ? GUC_LOG_CONTROL_LOGGING_ENABLED : 0) | |
66 | (verbosity << GUC_LOG_CONTROL_VERBOSITY_SHIFT) | | ||
67 | (default_logging ? GUC_LOG_CONTROL_DEFAULT_LOGGING : 0) | ||
72 | }; | 68 | }; |
73 | 69 | ||
70 | GEM_BUG_ON(verbosity > GUC_LOG_VERBOSITY_MAX); | ||
71 | |||
74 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 72 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
75 | } | 73 | } |
76 | 74 | ||
75 | static inline struct intel_guc *log_to_guc(struct intel_guc_log *log) | ||
76 | { | ||
77 | return container_of(log, struct intel_guc, log); | ||
78 | } | ||
79 | |||
80 | static void guc_log_enable_flush_events(struct intel_guc_log *log) | ||
81 | { | ||
82 | intel_guc_enable_msg(log_to_guc(log), | ||
83 | INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER | | ||
84 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED); | ||
85 | } | ||
86 | |||
87 | static void guc_log_disable_flush_events(struct intel_guc_log *log) | ||
88 | { | ||
89 | intel_guc_disable_msg(log_to_guc(log), | ||
90 | INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER | | ||
91 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED); | ||
92 | } | ||
93 | |||
77 | /* | 94 | /* |
78 | * Sub buffer switch callback. Called whenever relay has to switch to a new | 95 | * Sub buffer switch callback. Called whenever relay has to switch to a new |
79 | * sub buffer, relay stays on the same sub buffer if 0 is returned. | 96 | * sub buffer, relay stays on the same sub buffer if 0 is returned. |
@@ -121,14 +138,7 @@ static struct dentry *create_buf_file_callback(const char *filename, | |||
121 | if (!parent) | 138 | if (!parent) |
122 | return NULL; | 139 | return NULL; |
123 | 140 | ||
124 | /* | 141 | buf_file = debugfs_create_file(filename, mode, |
125 | * Not using the channel filename passed as an argument, since for each | ||
126 | * channel relay appends the corresponding CPU number to the filename | ||
127 | * passed in relay_open(). This should be fine as relay just needs a | ||
128 | * dentry of the file associated with the channel buffer and that file's | ||
129 | * name need not be same as the filename passed as an argument. | ||
130 | */ | ||
131 | buf_file = debugfs_create_file("guc_log", mode, | ||
132 | parent, buf, &relay_file_operations); | 142 | parent, buf, &relay_file_operations); |
133 | return buf_file; | 143 | return buf_file; |
134 | } | 144 | } |
@@ -149,59 +159,7 @@ static struct rchan_callbacks relay_callbacks = { | |||
149 | .remove_buf_file = remove_buf_file_callback, | 159 | .remove_buf_file = remove_buf_file_callback, |
150 | }; | 160 | }; |
151 | 161 | ||
152 | static int guc_log_relay_file_create(struct intel_guc *guc) | 162 | static void guc_move_to_next_buf(struct intel_guc_log *log) |
153 | { | ||
154 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
155 | struct dentry *log_dir; | ||
156 | int ret; | ||
157 | |||
158 | if (!i915_modparams.guc_log_level) | ||
159 | return 0; | ||
160 | |||
161 | mutex_lock(&guc->log.runtime.relay_lock); | ||
162 | |||
163 | /* For now create the log file in /sys/kernel/debug/dri/0 dir */ | ||
164 | log_dir = dev_priv->drm.primary->debugfs_root; | ||
165 | |||
166 | /* | ||
167 | * If /sys/kernel/debug/dri/0 location do not exist, then debugfs is | ||
168 | * not mounted and so can't create the relay file. | ||
169 | * The relay API seems to fit well with debugfs only, for availing relay | ||
170 | * there are 3 requirements which can be met for debugfs file only in a | ||
171 | * straightforward/clean manner :- | ||
172 | * i) Need the associated dentry pointer of the file, while opening the | ||
173 | * relay channel. | ||
174 | * ii) Should be able to use 'relay_file_operations' fops for the file. | ||
175 | * iii) Set the 'i_private' field of file's inode to the pointer of | ||
176 | * relay channel buffer. | ||
177 | */ | ||
178 | if (!log_dir) { | ||
179 | DRM_ERROR("Debugfs dir not available yet for GuC log file\n"); | ||
180 | ret = -ENODEV; | ||
181 | goto out_unlock; | ||
182 | } | ||
183 | |||
184 | ret = relay_late_setup_files(guc->log.runtime.relay_chan, "guc_log", log_dir); | ||
185 | if (ret < 0 && ret != -EEXIST) { | ||
186 | DRM_ERROR("Couldn't associate relay chan with file %d\n", ret); | ||
187 | goto out_unlock; | ||
188 | } | ||
189 | |||
190 | ret = 0; | ||
191 | |||
192 | out_unlock: | ||
193 | mutex_unlock(&guc->log.runtime.relay_lock); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | static bool guc_log_has_relay(struct intel_guc *guc) | ||
198 | { | ||
199 | lockdep_assert_held(&guc->log.runtime.relay_lock); | ||
200 | |||
201 | return guc->log.runtime.relay_chan != NULL; | ||
202 | } | ||
203 | |||
204 | static void guc_move_to_next_buf(struct intel_guc *guc) | ||
205 | { | 163 | { |
206 | /* | 164 | /* |
207 | * Make sure the updates made in the sub buffer are visible when | 165 | * Make sure the updates made in the sub buffer are visible when |
@@ -209,21 +167,15 @@ static void guc_move_to_next_buf(struct intel_guc *guc) | |||
209 | */ | 167 | */ |
210 | smp_wmb(); | 168 | smp_wmb(); |
211 | 169 | ||
212 | if (!guc_log_has_relay(guc)) | ||
213 | return; | ||
214 | |||
215 | /* All data has been written, so now move the offset of sub buffer. */ | 170 | /* All data has been written, so now move the offset of sub buffer. */ |
216 | relay_reserve(guc->log.runtime.relay_chan, guc->log.vma->obj->base.size); | 171 | relay_reserve(log->relay.channel, log->vma->obj->base.size); |
217 | 172 | ||
218 | /* Switch to the next sub buffer */ | 173 | /* Switch to the next sub buffer */ |
219 | relay_flush(guc->log.runtime.relay_chan); | 174 | relay_flush(log->relay.channel); |
220 | } | 175 | } |
221 | 176 | ||
222 | static void *guc_get_write_buffer(struct intel_guc *guc) | 177 | static void *guc_get_write_buffer(struct intel_guc_log *log) |
223 | { | 178 | { |
224 | if (!guc_log_has_relay(guc)) | ||
225 | return NULL; | ||
226 | |||
227 | /* | 179 | /* |
228 | * Just get the base address of a new sub buffer and copy data into it | 180 | * Just get the base address of a new sub buffer and copy data into it |
229 | * ourselves. NULL will be returned in no-overwrite mode, if all sub | 181 | * ourselves. NULL will be returned in no-overwrite mode, if all sub |
@@ -233,25 +185,25 @@ static void *guc_get_write_buffer(struct intel_guc *guc) | |||
233 | * done without using relay_reserve() along with relay_write(). So its | 185 | * done without using relay_reserve() along with relay_write(). So its |
234 | * better to use relay_reserve() alone. | 186 | * better to use relay_reserve() alone. |
235 | */ | 187 | */ |
236 | return relay_reserve(guc->log.runtime.relay_chan, 0); | 188 | return relay_reserve(log->relay.channel, 0); |
237 | } | 189 | } |
238 | 190 | ||
239 | static bool guc_check_log_buf_overflow(struct intel_guc *guc, | 191 | static bool guc_check_log_buf_overflow(struct intel_guc_log *log, |
240 | enum guc_log_buffer_type type, | 192 | enum guc_log_buffer_type type, |
241 | unsigned int full_cnt) | 193 | unsigned int full_cnt) |
242 | { | 194 | { |
243 | unsigned int prev_full_cnt = guc->log.prev_overflow_count[type]; | 195 | unsigned int prev_full_cnt = log->stats[type].sampled_overflow; |
244 | bool overflow = false; | 196 | bool overflow = false; |
245 | 197 | ||
246 | if (full_cnt != prev_full_cnt) { | 198 | if (full_cnt != prev_full_cnt) { |
247 | overflow = true; | 199 | overflow = true; |
248 | 200 | ||
249 | guc->log.prev_overflow_count[type] = full_cnt; | 201 | log->stats[type].overflow = full_cnt; |
250 | guc->log.total_overflow_count[type] += full_cnt - prev_full_cnt; | 202 | log->stats[type].sampled_overflow += full_cnt - prev_full_cnt; |
251 | 203 | ||
252 | if (full_cnt < prev_full_cnt) { | 204 | if (full_cnt < prev_full_cnt) { |
253 | /* buffer_full_cnt is a 4 bit counter */ | 205 | /* buffer_full_cnt is a 4 bit counter */ |
254 | guc->log.total_overflow_count[type] += 16; | 206 | log->stats[type].sampled_overflow += 16; |
255 | } | 207 | } |
256 | DRM_ERROR_RATELIMITED("GuC log buffer overflow\n"); | 208 | DRM_ERROR_RATELIMITED("GuC log buffer overflow\n"); |
257 | } | 209 | } |
@@ -275,7 +227,7 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) | |||
275 | return 0; | 227 | return 0; |
276 | } | 228 | } |
277 | 229 | ||
278 | static void guc_read_update_log_buffer(struct intel_guc *guc) | 230 | static void guc_read_update_log_buffer(struct intel_guc_log *log) |
279 | { | 231 | { |
280 | unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; | 232 | unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; |
281 | struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; | 233 | struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; |
@@ -284,16 +236,16 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
284 | void *src_data, *dst_data; | 236 | void *src_data, *dst_data; |
285 | bool new_overflow; | 237 | bool new_overflow; |
286 | 238 | ||
287 | if (WARN_ON(!guc->log.runtime.buf_addr)) | 239 | mutex_lock(&log->relay.lock); |
288 | return; | ||
289 | 240 | ||
290 | /* Get the pointer to shared GuC log buffer */ | 241 | if (WARN_ON(!intel_guc_log_relay_enabled(log))) |
291 | log_buf_state = src_data = guc->log.runtime.buf_addr; | 242 | goto out_unlock; |
292 | 243 | ||
293 | mutex_lock(&guc->log.runtime.relay_lock); | 244 | /* Get the pointer to shared GuC log buffer */ |
245 | log_buf_state = src_data = log->relay.buf_addr; | ||
294 | 246 | ||
295 | /* Get the pointer to local buffer to store the logs */ | 247 | /* Get the pointer to local buffer to store the logs */ |
296 | log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc); | 248 | log_buf_snapshot_state = dst_data = guc_get_write_buffer(log); |
297 | 249 | ||
298 | if (unlikely(!log_buf_snapshot_state)) { | 250 | if (unlikely(!log_buf_snapshot_state)) { |
299 | /* | 251 | /* |
@@ -301,10 +253,9 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
301 | * getting consumed by User at a slow rate. | 253 | * getting consumed by User at a slow rate. |
302 | */ | 254 | */ |
303 | DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); | 255 | DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); |
304 | guc->log.capture_miss_count++; | 256 | log->relay.full_count++; |
305 | mutex_unlock(&guc->log.runtime.relay_lock); | ||
306 | 257 | ||
307 | return; | 258 | goto out_unlock; |
308 | } | 259 | } |
309 | 260 | ||
310 | /* Actual logs are present from the 2nd page */ | 261 | /* Actual logs are present from the 2nd page */ |
@@ -325,8 +276,8 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
325 | full_cnt = log_buf_state_local.buffer_full_cnt; | 276 | full_cnt = log_buf_state_local.buffer_full_cnt; |
326 | 277 | ||
327 | /* Bookkeeping stuff */ | 278 | /* Bookkeeping stuff */ |
328 | guc->log.flush_count[type] += log_buf_state_local.flush_to_file; | 279 | log->stats[type].flush += log_buf_state_local.flush_to_file; |
329 | new_overflow = guc_check_log_buf_overflow(guc, type, full_cnt); | 280 | new_overflow = guc_check_log_buf_overflow(log, type, full_cnt); |
330 | 281 | ||
331 | /* Update the state of shared log buffer */ | 282 | /* Update the state of shared log buffer */ |
332 | log_buf_state->read_ptr = write_offset; | 283 | log_buf_state->read_ptr = write_offset; |
@@ -373,38 +324,35 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
373 | dst_data += buffer_size; | 324 | dst_data += buffer_size; |
374 | } | 325 | } |
375 | 326 | ||
376 | guc_move_to_next_buf(guc); | 327 | guc_move_to_next_buf(log); |
377 | 328 | ||
378 | mutex_unlock(&guc->log.runtime.relay_lock); | 329 | out_unlock: |
330 | mutex_unlock(&log->relay.lock); | ||
379 | } | 331 | } |
380 | 332 | ||
381 | static void capture_logs_work(struct work_struct *work) | 333 | static void capture_logs_work(struct work_struct *work) |
382 | { | 334 | { |
383 | struct intel_guc *guc = | 335 | struct intel_guc_log *log = |
384 | container_of(work, struct intel_guc, log.runtime.flush_work); | 336 | container_of(work, struct intel_guc_log, relay.flush_work); |
385 | |||
386 | guc_log_capture_logs(guc); | ||
387 | } | ||
388 | 337 | ||
389 | static bool guc_log_has_runtime(struct intel_guc *guc) | 338 | guc_log_capture_logs(log); |
390 | { | ||
391 | return guc->log.runtime.buf_addr != NULL; | ||
392 | } | 339 | } |
393 | 340 | ||
394 | static int guc_log_runtime_create(struct intel_guc *guc) | 341 | static int guc_log_map(struct intel_guc_log *log) |
395 | { | 342 | { |
343 | struct intel_guc *guc = log_to_guc(log); | ||
396 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 344 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
397 | void *vaddr; | 345 | void *vaddr; |
398 | int ret; | 346 | int ret; |
399 | 347 | ||
400 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 348 | lockdep_assert_held(&log->relay.lock); |
401 | 349 | ||
402 | if (!guc->log.vma) | 350 | if (!log->vma) |
403 | return -ENODEV; | 351 | return -ENODEV; |
404 | 352 | ||
405 | GEM_BUG_ON(guc_log_has_runtime(guc)); | 353 | mutex_lock(&dev_priv->drm.struct_mutex); |
406 | 354 | ret = i915_gem_object_set_to_wc_domain(log->vma->obj, true); | |
407 | ret = i915_gem_object_set_to_wc_domain(guc->log.vma->obj, true); | 355 | mutex_unlock(&dev_priv->drm.struct_mutex); |
408 | if (ret) | 356 | if (ret) |
409 | return ret; | 357 | return ret; |
410 | 358 | ||
@@ -413,49 +361,40 @@ static int guc_log_runtime_create(struct intel_guc *guc) | |||
413 | * buffer pages, so that we can directly get the data | 361 | * buffer pages, so that we can directly get the data |
414 | * (up-to-date) from memory. | 362 | * (up-to-date) from memory. |
415 | */ | 363 | */ |
416 | vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC); | 364 | vaddr = i915_gem_object_pin_map(log->vma->obj, I915_MAP_WC); |
417 | if (IS_ERR(vaddr)) { | 365 | if (IS_ERR(vaddr)) { |
418 | DRM_ERROR("Couldn't map log buffer pages %d\n", ret); | 366 | DRM_ERROR("Couldn't map log buffer pages %d\n", ret); |
419 | return PTR_ERR(vaddr); | 367 | return PTR_ERR(vaddr); |
420 | } | 368 | } |
421 | 369 | ||
422 | guc->log.runtime.buf_addr = vaddr; | 370 | log->relay.buf_addr = vaddr; |
423 | 371 | ||
424 | return 0; | 372 | return 0; |
425 | } | 373 | } |
426 | 374 | ||
427 | static void guc_log_runtime_destroy(struct intel_guc *guc) | 375 | static void guc_log_unmap(struct intel_guc_log *log) |
428 | { | 376 | { |
429 | /* | 377 | lockdep_assert_held(&log->relay.lock); |
430 | * It's possible that the runtime stuff was never allocated because | ||
431 | * GuC log was disabled at the boot time. | ||
432 | */ | ||
433 | if (!guc_log_has_runtime(guc)) | ||
434 | return; | ||
435 | 378 | ||
436 | i915_gem_object_unpin_map(guc->log.vma->obj); | 379 | i915_gem_object_unpin_map(log->vma->obj); |
437 | guc->log.runtime.buf_addr = NULL; | 380 | log->relay.buf_addr = NULL; |
438 | } | 381 | } |
439 | 382 | ||
440 | void intel_guc_log_init_early(struct intel_guc *guc) | 383 | void intel_guc_log_init_early(struct intel_guc_log *log) |
441 | { | 384 | { |
442 | mutex_init(&guc->log.runtime.relay_lock); | 385 | mutex_init(&log->relay.lock); |
443 | INIT_WORK(&guc->log.runtime.flush_work, capture_logs_work); | 386 | INIT_WORK(&log->relay.flush_work, capture_logs_work); |
444 | } | 387 | } |
445 | 388 | ||
446 | int intel_guc_log_relay_create(struct intel_guc *guc) | 389 | static int guc_log_relay_create(struct intel_guc_log *log) |
447 | { | 390 | { |
391 | struct intel_guc *guc = log_to_guc(log); | ||
448 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 392 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
449 | struct rchan *guc_log_relay_chan; | 393 | struct rchan *guc_log_relay_chan; |
450 | size_t n_subbufs, subbuf_size; | 394 | size_t n_subbufs, subbuf_size; |
451 | int ret; | 395 | int ret; |
452 | 396 | ||
453 | if (!i915_modparams.guc_log_level) | 397 | lockdep_assert_held(&log->relay.lock); |
454 | return 0; | ||
455 | |||
456 | mutex_lock(&guc->log.runtime.relay_lock); | ||
457 | |||
458 | GEM_BUG_ON(guc_log_has_relay(guc)); | ||
459 | 398 | ||
460 | /* Keep the size of sub buffers same as shared log buffer */ | 399 | /* Keep the size of sub buffers same as shared log buffer */ |
461 | subbuf_size = GUC_LOG_SIZE; | 400 | subbuf_size = GUC_LOG_SIZE; |
@@ -468,157 +407,56 @@ int intel_guc_log_relay_create(struct intel_guc *guc) | |||
468 | */ | 407 | */ |
469 | n_subbufs = 8; | 408 | n_subbufs = 8; |
470 | 409 | ||
471 | /* | 410 | guc_log_relay_chan = relay_open("guc_log", |
472 | * Create a relay channel, so that we have buffers for storing | 411 | dev_priv->drm.primary->debugfs_root, |
473 | * the GuC firmware logs, the channel will be linked with a file | 412 | subbuf_size, n_subbufs, |
474 | * later on when debugfs is registered. | 413 | &relay_callbacks, dev_priv); |
475 | */ | ||
476 | guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, | ||
477 | n_subbufs, &relay_callbacks, dev_priv); | ||
478 | if (!guc_log_relay_chan) { | 414 | if (!guc_log_relay_chan) { |
479 | DRM_ERROR("Couldn't create relay chan for GuC logging\n"); | 415 | DRM_ERROR("Couldn't create relay chan for GuC logging\n"); |
480 | 416 | ||
481 | ret = -ENOMEM; | 417 | ret = -ENOMEM; |
482 | goto err; | 418 | return ret; |
483 | } | 419 | } |
484 | 420 | ||
485 | GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); | 421 | GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); |
486 | guc->log.runtime.relay_chan = guc_log_relay_chan; | 422 | log->relay.channel = guc_log_relay_chan; |
487 | |||
488 | mutex_unlock(&guc->log.runtime.relay_lock); | ||
489 | 423 | ||
490 | return 0; | 424 | return 0; |
491 | |||
492 | err: | ||
493 | mutex_unlock(&guc->log.runtime.relay_lock); | ||
494 | /* logging will be off */ | ||
495 | i915_modparams.guc_log_level = 0; | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | void intel_guc_log_relay_destroy(struct intel_guc *guc) | ||
500 | { | ||
501 | mutex_lock(&guc->log.runtime.relay_lock); | ||
502 | |||
503 | /* | ||
504 | * It's possible that the relay was never allocated because | ||
505 | * GuC log was disabled at the boot time. | ||
506 | */ | ||
507 | if (!guc_log_has_relay(guc)) | ||
508 | goto out_unlock; | ||
509 | |||
510 | relay_close(guc->log.runtime.relay_chan); | ||
511 | guc->log.runtime.relay_chan = NULL; | ||
512 | |||
513 | out_unlock: | ||
514 | mutex_unlock(&guc->log.runtime.relay_lock); | ||
515 | } | 425 | } |
516 | 426 | ||
517 | static int guc_log_late_setup(struct intel_guc *guc) | 427 | static void guc_log_relay_destroy(struct intel_guc_log *log) |
518 | { | 428 | { |
519 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 429 | lockdep_assert_held(&log->relay.lock); |
520 | int ret; | ||
521 | |||
522 | if (!guc_log_has_runtime(guc)) { | ||
523 | /* | ||
524 | * If log was disabled at boot time, then setup needed to handle | ||
525 | * log buffer flush interrupts would not have been done yet, so | ||
526 | * do that now. | ||
527 | */ | ||
528 | ret = intel_guc_log_relay_create(guc); | ||
529 | if (ret) | ||
530 | goto err; | ||
531 | |||
532 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
533 | intel_runtime_pm_get(dev_priv); | ||
534 | ret = guc_log_runtime_create(guc); | ||
535 | intel_runtime_pm_put(dev_priv); | ||
536 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
537 | |||
538 | if (ret) | ||
539 | goto err_relay; | ||
540 | } | ||
541 | |||
542 | ret = guc_log_relay_file_create(guc); | ||
543 | if (ret) | ||
544 | goto err_runtime; | ||
545 | |||
546 | return 0; | ||
547 | 430 | ||
548 | err_runtime: | 431 | relay_close(log->relay.channel); |
549 | mutex_lock(&dev_priv->drm.struct_mutex); | 432 | log->relay.channel = NULL; |
550 | guc_log_runtime_destroy(guc); | ||
551 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
552 | err_relay: | ||
553 | intel_guc_log_relay_destroy(guc); | ||
554 | err: | ||
555 | /* logging will remain off */ | ||
556 | i915_modparams.guc_log_level = 0; | ||
557 | return ret; | ||
558 | } | 433 | } |
559 | 434 | ||
560 | static void guc_log_capture_logs(struct intel_guc *guc) | 435 | static void guc_log_capture_logs(struct intel_guc_log *log) |
561 | { | 436 | { |
437 | struct intel_guc *guc = log_to_guc(log); | ||
562 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 438 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
563 | 439 | ||
564 | guc_read_update_log_buffer(guc); | 440 | guc_read_update_log_buffer(log); |
565 | 441 | ||
566 | /* | 442 | /* |
567 | * Generally device is expected to be active only at this | 443 | * Generally device is expected to be active only at this |
568 | * time, so get/put should be really quick. | 444 | * time, so get/put should be really quick. |
569 | */ | 445 | */ |
570 | intel_runtime_pm_get(dev_priv); | 446 | intel_runtime_pm_get(dev_priv); |
571 | guc_log_flush_complete(guc); | 447 | guc_action_flush_log_complete(guc); |
572 | intel_runtime_pm_put(dev_priv); | ||
573 | } | ||
574 | |||
575 | static void guc_flush_logs(struct intel_guc *guc) | ||
576 | { | ||
577 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
578 | |||
579 | if (!USES_GUC_SUBMISSION(dev_priv) || !i915_modparams.guc_log_level) | ||
580 | return; | ||
581 | |||
582 | /* First disable the interrupts, will be renabled afterwards */ | ||
583 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
584 | intel_runtime_pm_get(dev_priv); | ||
585 | gen9_disable_guc_interrupts(dev_priv); | ||
586 | intel_runtime_pm_put(dev_priv); | ||
587 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
588 | |||
589 | /* | ||
590 | * Before initiating the forceful flush, wait for any pending/ongoing | ||
591 | * flush to complete otherwise forceful flush may not actually happen. | ||
592 | */ | ||
593 | flush_work(&guc->log.runtime.flush_work); | ||
594 | |||
595 | /* Ask GuC to update the log buffer state */ | ||
596 | intel_runtime_pm_get(dev_priv); | ||
597 | guc_log_flush(guc); | ||
598 | intel_runtime_pm_put(dev_priv); | 448 | intel_runtime_pm_put(dev_priv); |
599 | |||
600 | /* GuC would have updated log buffer by now, so capture it */ | ||
601 | guc_log_capture_logs(guc); | ||
602 | } | 449 | } |
603 | 450 | ||
604 | int intel_guc_log_create(struct intel_guc *guc) | 451 | int intel_guc_log_create(struct intel_guc_log *log) |
605 | { | 452 | { |
453 | struct intel_guc *guc = log_to_guc(log); | ||
606 | struct i915_vma *vma; | 454 | struct i915_vma *vma; |
607 | unsigned long offset; | 455 | unsigned long offset; |
608 | u32 flags; | 456 | u32 flags; |
609 | int ret; | 457 | int ret; |
610 | 458 | ||
611 | GEM_BUG_ON(guc->log.vma); | 459 | GEM_BUG_ON(log->vma); |
612 | |||
613 | /* | ||
614 | * We require SSE 4.1 for fast reads from the GuC log buffer and | ||
615 | * it should be present on the chipsets supporting GuC based | ||
616 | * submisssions. | ||
617 | */ | ||
618 | if (WARN_ON(!i915_has_memcpy_from_wc())) { | ||
619 | ret = -EINVAL; | ||
620 | goto err; | ||
621 | } | ||
622 | 460 | ||
623 | vma = intel_guc_allocate_vma(guc, GUC_LOG_SIZE); | 461 | vma = intel_guc_allocate_vma(guc, GUC_LOG_SIZE); |
624 | if (IS_ERR(vma)) { | 462 | if (IS_ERR(vma)) { |
@@ -626,13 +464,7 @@ int intel_guc_log_create(struct intel_guc *guc) | |||
626 | goto err; | 464 | goto err; |
627 | } | 465 | } |
628 | 466 | ||
629 | guc->log.vma = vma; | 467 | log->vma = vma; |
630 | |||
631 | if (i915_modparams.guc_log_level) { | ||
632 | ret = guc_log_runtime_create(guc); | ||
633 | if (ret < 0) | ||
634 | goto err_vma; | ||
635 | } | ||
636 | 468 | ||
637 | /* each allocated unit is a page */ | 469 | /* each allocated unit is a page */ |
638 | flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | | 470 | flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | |
@@ -640,117 +472,159 @@ int intel_guc_log_create(struct intel_guc *guc) | |||
640 | (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | | 472 | (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | |
641 | (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); | 473 | (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); |
642 | 474 | ||
643 | offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */ | 475 | offset = intel_guc_ggtt_offset(guc, vma) >> PAGE_SHIFT; |
644 | guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; | 476 | log->flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; |
645 | 477 | ||
646 | return 0; | 478 | return 0; |
647 | 479 | ||
648 | err_vma: | ||
649 | i915_vma_unpin_and_release(&guc->log.vma); | ||
650 | err: | 480 | err: |
651 | /* logging will be off */ | 481 | /* logging will be off */ |
652 | i915_modparams.guc_log_level = 0; | 482 | i915_modparams.guc_log_level = 0; |
653 | return ret; | 483 | return ret; |
654 | } | 484 | } |
655 | 485 | ||
656 | void intel_guc_log_destroy(struct intel_guc *guc) | 486 | void intel_guc_log_destroy(struct intel_guc_log *log) |
487 | { | ||
488 | i915_vma_unpin_and_release(&log->vma); | ||
489 | } | ||
490 | |||
491 | int intel_guc_log_level_get(struct intel_guc_log *log) | ||
657 | { | 492 | { |
658 | guc_log_runtime_destroy(guc); | 493 | GEM_BUG_ON(!log->vma); |
659 | i915_vma_unpin_and_release(&guc->log.vma); | 494 | GEM_BUG_ON(i915_modparams.guc_log_level < 0); |
495 | |||
496 | return i915_modparams.guc_log_level; | ||
660 | } | 497 | } |
661 | 498 | ||
662 | int intel_guc_log_control(struct intel_guc *guc, u64 control_val) | 499 | int intel_guc_log_level_set(struct intel_guc_log *log, u64 val) |
663 | { | 500 | { |
501 | struct intel_guc *guc = log_to_guc(log); | ||
664 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 502 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
665 | bool enable_logging = control_val > 0; | ||
666 | u32 verbosity; | ||
667 | int ret; | 503 | int ret; |
668 | 504 | ||
669 | if (!guc->log.vma) | 505 | BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0); |
670 | return -ENODEV; | 506 | GEM_BUG_ON(!log->vma); |
507 | GEM_BUG_ON(i915_modparams.guc_log_level < 0); | ||
671 | 508 | ||
672 | BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN); | 509 | /* |
673 | if (control_val > 1 + GUC_LOG_VERBOSITY_MAX) | 510 | * GuC is recognizing log levels starting from 0 to max, we're using 0 |
511 | * as indication that logging should be disabled. | ||
512 | */ | ||
513 | if (val < GUC_LOG_LEVEL_DISABLED || val > GUC_LOG_LEVEL_MAX) | ||
674 | return -EINVAL; | 514 | return -EINVAL; |
675 | 515 | ||
676 | /* This combination doesn't make sense & won't have any effect */ | 516 | mutex_lock(&dev_priv->drm.struct_mutex); |
677 | if (!enable_logging && !i915_modparams.guc_log_level) | ||
678 | return 0; | ||
679 | 517 | ||
680 | verbosity = enable_logging ? control_val - 1 : 0; | 518 | if (i915_modparams.guc_log_level == val) { |
519 | ret = 0; | ||
520 | goto out_unlock; | ||
521 | } | ||
681 | 522 | ||
682 | ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex); | ||
683 | if (ret) | ||
684 | return ret; | ||
685 | intel_runtime_pm_get(dev_priv); | 523 | intel_runtime_pm_get(dev_priv); |
686 | ret = guc_log_control(guc, enable_logging, verbosity); | 524 | ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(val), |
525 | GUC_LOG_LEVEL_IS_ENABLED(val), | ||
526 | GUC_LOG_LEVEL_TO_VERBOSITY(val)); | ||
687 | intel_runtime_pm_put(dev_priv); | 527 | intel_runtime_pm_put(dev_priv); |
528 | if (ret) { | ||
529 | DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret); | ||
530 | goto out_unlock; | ||
531 | } | ||
532 | |||
533 | i915_modparams.guc_log_level = val; | ||
534 | |||
535 | out_unlock: | ||
688 | mutex_unlock(&dev_priv->drm.struct_mutex); | 536 | mutex_unlock(&dev_priv->drm.struct_mutex); |
689 | 537 | ||
690 | if (ret < 0) { | 538 | return ret; |
691 | DRM_DEBUG_DRIVER("guc_logging_control action failed %d\n", ret); | 539 | } |
692 | return ret; | ||
693 | } | ||
694 | 540 | ||
695 | if (enable_logging) { | 541 | bool intel_guc_log_relay_enabled(const struct intel_guc_log *log) |
696 | i915_modparams.guc_log_level = 1 + verbosity; | 542 | { |
543 | return log->relay.buf_addr; | ||
544 | } | ||
697 | 545 | ||
698 | /* | 546 | int intel_guc_log_relay_open(struct intel_guc_log *log) |
699 | * If log was disabled at boot time, then the relay channel file | 547 | { |
700 | * wouldn't have been created by now and interrupts also would | 548 | int ret; |
701 | * not have been enabled. Try again now, just in case. | ||
702 | */ | ||
703 | ret = guc_log_late_setup(guc); | ||
704 | if (ret < 0) { | ||
705 | DRM_DEBUG_DRIVER("GuC log late setup failed %d\n", ret); | ||
706 | return ret; | ||
707 | } | ||
708 | 549 | ||
709 | /* GuC logging is currently the only user of Guc2Host interrupts */ | 550 | mutex_lock(&log->relay.lock); |
710 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
711 | intel_runtime_pm_get(dev_priv); | ||
712 | gen9_enable_guc_interrupts(dev_priv); | ||
713 | intel_runtime_pm_put(dev_priv); | ||
714 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
715 | } else { | ||
716 | /* | ||
717 | * Once logging is disabled, GuC won't generate logs & send an | ||
718 | * interrupt. But there could be some data in the log buffer | ||
719 | * which is yet to be captured. So request GuC to update the log | ||
720 | * buffer state and then collect the left over logs. | ||
721 | */ | ||
722 | guc_flush_logs(guc); | ||
723 | 551 | ||
724 | /* As logging is disabled, update log level to reflect that */ | 552 | if (intel_guc_log_relay_enabled(log)) { |
725 | i915_modparams.guc_log_level = 0; | 553 | ret = -EEXIST; |
554 | goto out_unlock; | ||
726 | } | 555 | } |
727 | 556 | ||
728 | return ret; | 557 | /* |
729 | } | 558 | * We require SSE 4.1 for fast reads from the GuC log buffer and |
559 | * it should be present on the chipsets supporting GuC based | ||
560 | * submisssions. | ||
561 | */ | ||
562 | if (!i915_has_memcpy_from_wc()) { | ||
563 | ret = -ENXIO; | ||
564 | goto out_unlock; | ||
565 | } | ||
730 | 566 | ||
731 | void i915_guc_log_register(struct drm_i915_private *dev_priv) | 567 | ret = guc_log_relay_create(log); |
732 | { | 568 | if (ret) |
733 | if (!USES_GUC_SUBMISSION(dev_priv) || !i915_modparams.guc_log_level) | 569 | goto out_unlock; |
734 | return; | 570 | |
571 | ret = guc_log_map(log); | ||
572 | if (ret) | ||
573 | goto out_relay; | ||
735 | 574 | ||
736 | guc_log_late_setup(&dev_priv->guc); | 575 | mutex_unlock(&log->relay.lock); |
576 | |||
577 | guc_log_enable_flush_events(log); | ||
578 | |||
579 | /* | ||
580 | * When GuC is logging without us relaying to userspace, we're ignoring | ||
581 | * the flush notification. This means that we need to unconditionally | ||
582 | * flush on relay enabling, since GuC only notifies us once. | ||
583 | */ | ||
584 | queue_work(log->relay.flush_wq, &log->relay.flush_work); | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | out_relay: | ||
589 | guc_log_relay_destroy(log); | ||
590 | out_unlock: | ||
591 | mutex_unlock(&log->relay.lock); | ||
592 | |||
593 | return ret; | ||
737 | } | 594 | } |
738 | 595 | ||
739 | void i915_guc_log_unregister(struct drm_i915_private *dev_priv) | 596 | void intel_guc_log_relay_flush(struct intel_guc_log *log) |
740 | { | 597 | { |
741 | struct intel_guc *guc = &dev_priv->guc; | 598 | struct intel_guc *guc = log_to_guc(log); |
599 | struct drm_i915_private *i915 = guc_to_i915(guc); | ||
600 | |||
601 | /* | ||
602 | * Before initiating the forceful flush, wait for any pending/ongoing | ||
603 | * flush to complete otherwise forceful flush may not actually happen. | ||
604 | */ | ||
605 | flush_work(&log->relay.flush_work); | ||
742 | 606 | ||
743 | if (!USES_GUC_SUBMISSION(dev_priv)) | 607 | intel_runtime_pm_get(i915); |
744 | return; | 608 | guc_action_flush_log(guc); |
609 | intel_runtime_pm_put(i915); | ||
745 | 610 | ||
746 | mutex_lock(&dev_priv->drm.struct_mutex); | 611 | /* GuC would have updated log buffer by now, so capture it */ |
747 | /* GuC logging is currently the only user of Guc2Host interrupts */ | 612 | guc_log_capture_logs(log); |
748 | intel_runtime_pm_get(dev_priv); | 613 | } |
749 | gen9_disable_guc_interrupts(dev_priv); | ||
750 | intel_runtime_pm_put(dev_priv); | ||
751 | 614 | ||
752 | guc_log_runtime_destroy(guc); | 615 | void intel_guc_log_relay_close(struct intel_guc_log *log) |
753 | mutex_unlock(&dev_priv->drm.struct_mutex); | 616 | { |
617 | guc_log_disable_flush_events(log); | ||
618 | flush_work(&log->relay.flush_work); | ||
619 | |||
620 | mutex_lock(&log->relay.lock); | ||
621 | GEM_BUG_ON(!intel_guc_log_relay_enabled(log)); | ||
622 | guc_log_unmap(log); | ||
623 | guc_log_relay_destroy(log); | ||
624 | mutex_unlock(&log->relay.lock); | ||
625 | } | ||
754 | 626 | ||
755 | intel_guc_log_relay_destroy(guc); | 627 | void intel_guc_log_handle_flush_event(struct intel_guc_log *log) |
628 | { | ||
629 | queue_work(log->relay.flush_wq, &log->relay.flush_work); | ||
756 | } | 630 | } |
diff --git a/drivers/gpu/drm/i915/intel_guc_log.h b/drivers/gpu/drm/i915/intel_guc_log.h index dab0e949567a..fa80535a6f9d 100644 --- a/drivers/gpu/drm/i915/intel_guc_log.h +++ b/drivers/gpu/drm/i915/intel_guc_log.h | |||
@@ -25,11 +25,12 @@ | |||
25 | #ifndef _INTEL_GUC_LOG_H_ | 25 | #ifndef _INTEL_GUC_LOG_H_ |
26 | #define _INTEL_GUC_LOG_H_ | 26 | #define _INTEL_GUC_LOG_H_ |
27 | 27 | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/relay.h> | ||
28 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
29 | 31 | ||
30 | #include "intel_guc_fwif.h" | 32 | #include "intel_guc_fwif.h" |
31 | 33 | ||
32 | struct drm_i915_private; | ||
33 | struct intel_guc; | 34 | struct intel_guc; |
34 | 35 | ||
35 | /* | 36 | /* |
@@ -39,33 +40,53 @@ struct intel_guc; | |||
39 | #define GUC_LOG_SIZE ((1 + GUC_LOG_DPC_PAGES + 1 + GUC_LOG_ISR_PAGES + \ | 40 | #define GUC_LOG_SIZE ((1 + GUC_LOG_DPC_PAGES + 1 + GUC_LOG_ISR_PAGES + \ |
40 | 1 + GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT) | 41 | 1 + GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT) |
41 | 42 | ||
43 | /* | ||
44 | * While we're using plain log level in i915, GuC controls are much more... | ||
45 | * "elaborate"? We have a couple of bits for verbosity, separate bit for actual | ||
46 | * log enabling, and separate bit for default logging - which "conveniently" | ||
47 | * ignores the enable bit. | ||
48 | */ | ||
49 | #define GUC_LOG_LEVEL_DISABLED 0 | ||
50 | #define GUC_LOG_LEVEL_NON_VERBOSE 1 | ||
51 | #define GUC_LOG_LEVEL_IS_ENABLED(x) ((x) > GUC_LOG_LEVEL_DISABLED) | ||
52 | #define GUC_LOG_LEVEL_IS_VERBOSE(x) ((x) > GUC_LOG_LEVEL_NON_VERBOSE) | ||
53 | #define GUC_LOG_LEVEL_TO_VERBOSITY(x) ({ \ | ||
54 | typeof(x) _x = (x); \ | ||
55 | GUC_LOG_LEVEL_IS_VERBOSE(_x) ? _x - 2 : 0; \ | ||
56 | }) | ||
57 | #define GUC_VERBOSITY_TO_LOG_LEVEL(x) ((x) + 2) | ||
58 | #define GUC_LOG_LEVEL_MAX GUC_VERBOSITY_TO_LOG_LEVEL(GUC_LOG_VERBOSITY_MAX) | ||
59 | |||
42 | struct intel_guc_log { | 60 | struct intel_guc_log { |
43 | u32 flags; | 61 | u32 flags; |
44 | struct i915_vma *vma; | 62 | struct i915_vma *vma; |
45 | /* The runtime stuff gets created only when GuC logging gets enabled */ | ||
46 | struct { | 63 | struct { |
47 | void *buf_addr; | 64 | void *buf_addr; |
48 | struct workqueue_struct *flush_wq; | 65 | struct workqueue_struct *flush_wq; |
49 | struct work_struct flush_work; | 66 | struct work_struct flush_work; |
50 | struct rchan *relay_chan; | 67 | struct rchan *channel; |
51 | /* To serialize the access to relay_chan */ | 68 | struct mutex lock; |
52 | struct mutex relay_lock; | 69 | u32 full_count; |
53 | } runtime; | 70 | } relay; |
54 | /* logging related stats */ | 71 | /* logging related stats */ |
55 | u32 capture_miss_count; | 72 | struct { |
56 | u32 flush_interrupt_count; | 73 | u32 sampled_overflow; |
57 | u32 prev_overflow_count[GUC_MAX_LOG_BUFFER]; | 74 | u32 overflow; |
58 | u32 total_overflow_count[GUC_MAX_LOG_BUFFER]; | 75 | u32 flush; |
59 | u32 flush_count[GUC_MAX_LOG_BUFFER]; | 76 | } stats[GUC_MAX_LOG_BUFFER]; |
60 | }; | 77 | }; |
61 | 78 | ||
62 | int intel_guc_log_create(struct intel_guc *guc); | 79 | void intel_guc_log_init_early(struct intel_guc_log *log); |
63 | void intel_guc_log_destroy(struct intel_guc *guc); | 80 | int intel_guc_log_create(struct intel_guc_log *log); |
64 | void intel_guc_log_init_early(struct intel_guc *guc); | 81 | void intel_guc_log_destroy(struct intel_guc_log *log); |
65 | int intel_guc_log_relay_create(struct intel_guc *guc); | 82 | |
66 | void intel_guc_log_relay_destroy(struct intel_guc *guc); | 83 | int intel_guc_log_level_get(struct intel_guc_log *log); |
67 | int intel_guc_log_control(struct intel_guc *guc, u64 control_val); | 84 | int intel_guc_log_level_set(struct intel_guc_log *log, u64 control_val); |
68 | void i915_guc_log_register(struct drm_i915_private *dev_priv); | 85 | bool intel_guc_log_relay_enabled(const struct intel_guc_log *log); |
69 | void i915_guc_log_unregister(struct drm_i915_private *dev_priv); | 86 | int intel_guc_log_relay_open(struct intel_guc_log *log); |
87 | void intel_guc_log_relay_flush(struct intel_guc_log *log); | ||
88 | void intel_guc_log_relay_close(struct intel_guc_log *log); | ||
89 | |||
90 | void intel_guc_log_handle_flush_event(struct intel_guc_log *log); | ||
70 | 91 | ||
71 | #endif | 92 | #endif |
diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h index 19a9247c5664..d86084742a4a 100644 --- a/drivers/gpu/drm/i915/intel_guc_reg.h +++ b/drivers/gpu/drm/i915/intel_guc_reg.h | |||
@@ -66,22 +66,20 @@ | |||
66 | #define UOS_MOVE (1<<4) | 66 | #define UOS_MOVE (1<<4) |
67 | #define START_DMA (1<<0) | 67 | #define START_DMA (1<<0) |
68 | #define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) | 68 | #define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) |
69 | #define GUC_WOPCM_OFFSET_VALID (1<<0) | ||
69 | #define HUC_LOADING_AGENT_VCR (0<<1) | 70 | #define HUC_LOADING_AGENT_VCR (0<<1) |
70 | #define HUC_LOADING_AGENT_GUC (1<<1) | 71 | #define HUC_LOADING_AGENT_GUC (1<<1) |
71 | #define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ | 72 | #define GUC_WOPCM_OFFSET_SHIFT 14 |
73 | #define GUC_WOPCM_OFFSET_MASK (0x3ffff << GUC_WOPCM_OFFSET_SHIFT) | ||
72 | #define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) | 74 | #define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) |
73 | 75 | ||
74 | #define HUC_STATUS2 _MMIO(0xD3B0) | 76 | #define HUC_STATUS2 _MMIO(0xD3B0) |
75 | #define HUC_FW_VERIFIED (1<<7) | 77 | #define HUC_FW_VERIFIED (1<<7) |
76 | 78 | ||
77 | /* Defines WOPCM space available to GuC firmware */ | ||
78 | #define GUC_WOPCM_SIZE _MMIO(0xc050) | 79 | #define GUC_WOPCM_SIZE _MMIO(0xc050) |
79 | /* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ | 80 | #define GUC_WOPCM_SIZE_LOCKED (1<<0) |
80 | #define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ | 81 | #define GUC_WOPCM_SIZE_SHIFT 12 |
81 | #define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ | 82 | #define GUC_WOPCM_SIZE_MASK (0xfffff << GUC_WOPCM_SIZE_SHIFT) |
82 | |||
83 | /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ | ||
84 | #define GUC_GGTT_TOP 0xFEE00000 | ||
85 | 83 | ||
86 | #define GEN8_GT_PM_CONFIG _MMIO(0x138140) | 84 | #define GEN8_GT_PM_CONFIG _MMIO(0x138140) |
87 | #define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) | 85 | #define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) |
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 8a8ad2fe158d..97121230656c 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c | |||
@@ -231,8 +231,8 @@ static int create_doorbell(struct intel_guc_client *client) | |||
231 | if (ret) { | 231 | if (ret) { |
232 | __destroy_doorbell(client); | 232 | __destroy_doorbell(client); |
233 | __update_doorbell_desc(client, GUC_DOORBELL_INVALID); | 233 | __update_doorbell_desc(client, GUC_DOORBELL_INVALID); |
234 | DRM_ERROR("Couldn't create client %u doorbell: %d\n", | 234 | DRM_DEBUG_DRIVER("Couldn't create client %u doorbell: %d\n", |
235 | client->stage_id, ret); | 235 | client->stage_id, ret); |
236 | return ret; | 236 | return ret; |
237 | } | 237 | } |
238 | 238 | ||
@@ -386,8 +386,8 @@ static void guc_stage_desc_init(struct intel_guc *guc, | |||
386 | lrc->context_desc = lower_32_bits(ce->lrc_desc); | 386 | lrc->context_desc = lower_32_bits(ce->lrc_desc); |
387 | 387 | ||
388 | /* The state page is after PPHWSP */ | 388 | /* The state page is after PPHWSP */ |
389 | lrc->ring_lrca = | 389 | lrc->ring_lrca = intel_guc_ggtt_offset(guc, ce->state) + |
390 | guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; | 390 | LRC_STATE_PN * PAGE_SIZE; |
391 | 391 | ||
392 | /* XXX: In direct submission, the GuC wants the HW context id | 392 | /* XXX: In direct submission, the GuC wants the HW context id |
393 | * here. In proxy submission, it wants the stage id | 393 | * here. In proxy submission, it wants the stage id |
@@ -395,7 +395,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, | |||
395 | lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | | 395 | lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | |
396 | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); | 396 | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); |
397 | 397 | ||
398 | lrc->ring_begin = guc_ggtt_offset(ce->ring->vma); | 398 | lrc->ring_begin = intel_guc_ggtt_offset(guc, ce->ring->vma); |
399 | lrc->ring_end = lrc->ring_begin + ce->ring->size - 1; | 399 | lrc->ring_end = lrc->ring_begin + ce->ring->size - 1; |
400 | lrc->ring_next_free_location = lrc->ring_begin; | 400 | lrc->ring_next_free_location = lrc->ring_begin; |
401 | lrc->ring_current_tail_pointer_value = 0; | 401 | lrc->ring_current_tail_pointer_value = 0; |
@@ -411,7 +411,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, | |||
411 | * The doorbell, process descriptor, and workqueue are all parts | 411 | * The doorbell, process descriptor, and workqueue are all parts |
412 | * of the client object, which the GuC will reference via the GGTT | 412 | * of the client object, which the GuC will reference via the GGTT |
413 | */ | 413 | */ |
414 | gfx_addr = guc_ggtt_offset(client->vma); | 414 | gfx_addr = intel_guc_ggtt_offset(guc, client->vma); |
415 | desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + | 415 | desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + |
416 | client->doorbell_offset; | 416 | client->doorbell_offset; |
417 | desc->db_trigger_cpu = ptr_to_u64(__get_doorbell(client)); | 417 | desc->db_trigger_cpu = ptr_to_u64(__get_doorbell(client)); |
@@ -584,7 +584,7 @@ static void inject_preempt_context(struct work_struct *work) | |||
584 | data[3] = engine->guc_id; | 584 | data[3] = engine->guc_id; |
585 | data[4] = guc->execbuf_client->priority; | 585 | data[4] = guc->execbuf_client->priority; |
586 | data[5] = guc->execbuf_client->stage_id; | 586 | data[5] = guc->execbuf_client->stage_id; |
587 | data[6] = guc_ggtt_offset(guc->shared_data); | 587 | data[6] = intel_guc_ggtt_offset(guc, guc->shared_data); |
588 | 588 | ||
589 | if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { | 589 | if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { |
590 | execlists_clear_active(&engine->execlists, | 590 | execlists_clear_active(&engine->execlists, |
@@ -657,6 +657,16 @@ static void port_assign(struct execlist_port *port, struct i915_request *rq) | |||
657 | port_set(port, i915_request_get(rq)); | 657 | port_set(port, i915_request_get(rq)); |
658 | } | 658 | } |
659 | 659 | ||
660 | static inline int rq_prio(const struct i915_request *rq) | ||
661 | { | ||
662 | return rq->priotree.priority; | ||
663 | } | ||
664 | |||
665 | static inline int port_prio(const struct execlist_port *port) | ||
666 | { | ||
667 | return rq_prio(port_request(port)); | ||
668 | } | ||
669 | |||
660 | static void guc_dequeue(struct intel_engine_cs *engine) | 670 | static void guc_dequeue(struct intel_engine_cs *engine) |
661 | { | 671 | { |
662 | struct intel_engine_execlists * const execlists = &engine->execlists; | 672 | struct intel_engine_execlists * const execlists = &engine->execlists; |
@@ -672,12 +682,12 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
672 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); | 682 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
673 | 683 | ||
674 | if (port_isset(port)) { | 684 | if (port_isset(port)) { |
675 | if (engine->i915->preempt_context) { | 685 | if (intel_engine_has_preemption(engine)) { |
676 | struct guc_preempt_work *preempt_work = | 686 | struct guc_preempt_work *preempt_work = |
677 | &engine->i915->guc.preempt_work[engine->id]; | 687 | &engine->i915->guc.preempt_work[engine->id]; |
688 | int prio = execlists->queue_priority; | ||
678 | 689 | ||
679 | if (execlists->queue_priority > | 690 | if (__execlists_need_preempt(prio, port_prio(port))) { |
680 | max(port_request(port)->priotree.priority, 0)) { | ||
681 | execlists_set_active(execlists, | 691 | execlists_set_active(execlists, |
682 | EXECLISTS_ACTIVE_PREEMPT); | 692 | EXECLISTS_ACTIVE_PREEMPT); |
683 | queue_work(engine->i915->guc.preempt_wq, | 693 | queue_work(engine->i915->guc.preempt_wq, |
@@ -728,7 +738,7 @@ done: | |||
728 | execlists->first = rb; | 738 | execlists->first = rb; |
729 | if (submit) { | 739 | if (submit) { |
730 | port_assign(port, last); | 740 | port_assign(port, last); |
731 | execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | 741 | execlists_user_begin(execlists, execlists->port); |
732 | guc_submit(engine); | 742 | guc_submit(engine); |
733 | } | 743 | } |
734 | 744 | ||
@@ -748,17 +758,20 @@ static void guc_submission_tasklet(unsigned long data) | |||
748 | struct execlist_port *port = execlists->port; | 758 | struct execlist_port *port = execlists->port; |
749 | struct i915_request *rq; | 759 | struct i915_request *rq; |
750 | 760 | ||
751 | rq = port_request(&port[0]); | 761 | rq = port_request(port); |
752 | while (rq && i915_request_completed(rq)) { | 762 | while (rq && i915_request_completed(rq)) { |
753 | trace_i915_request_out(rq); | 763 | trace_i915_request_out(rq); |
754 | i915_request_put(rq); | 764 | i915_request_put(rq); |
755 | 765 | ||
756 | execlists_port_complete(execlists, port); | 766 | port = execlists_port_complete(execlists, port); |
757 | 767 | if (port_isset(port)) { | |
758 | rq = port_request(&port[0]); | 768 | execlists_user_begin(execlists, port); |
769 | rq = port_request(port); | ||
770 | } else { | ||
771 | execlists_user_end(execlists); | ||
772 | rq = NULL; | ||
773 | } | ||
759 | } | 774 | } |
760 | if (!rq) | ||
761 | execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); | ||
762 | 775 | ||
763 | if (execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT) && | 776 | if (execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT) && |
764 | intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) == | 777 | intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) == |
diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index c8ea510629fa..fd0ffb8328d0 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c | |||
@@ -246,9 +246,8 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) | |||
246 | */ | 246 | */ |
247 | tmp = I915_READ_CTL(engine); | 247 | tmp = I915_READ_CTL(engine); |
248 | if (tmp & RING_WAIT) { | 248 | if (tmp & RING_WAIT) { |
249 | i915_handle_error(dev_priv, BIT(engine->id), | 249 | i915_handle_error(dev_priv, BIT(engine->id), 0, |
250 | "Kicking stuck wait on %s", | 250 | "stuck wait on %s", engine->name); |
251 | engine->name); | ||
252 | I915_WRITE_CTL(engine, tmp); | 251 | I915_WRITE_CTL(engine, tmp); |
253 | return ENGINE_WAIT_KICK; | 252 | return ENGINE_WAIT_KICK; |
254 | } | 253 | } |
@@ -258,8 +257,8 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) | |||
258 | default: | 257 | default: |
259 | return ENGINE_DEAD; | 258 | return ENGINE_DEAD; |
260 | case 1: | 259 | case 1: |
261 | i915_handle_error(dev_priv, ALL_ENGINES, | 260 | i915_handle_error(dev_priv, ALL_ENGINES, 0, |
262 | "Kicking stuck semaphore on %s", | 261 | "stuck semaphore on %s", |
263 | engine->name); | 262 | engine->name); |
264 | I915_WRITE_CTL(engine, tmp); | 263 | I915_WRITE_CTL(engine, tmp); |
265 | return ENGINE_WAIT_KICK; | 264 | return ENGINE_WAIT_KICK; |
@@ -386,13 +385,13 @@ static void hangcheck_declare_hang(struct drm_i915_private *i915, | |||
386 | if (stuck != hung) | 385 | if (stuck != hung) |
387 | hung &= ~stuck; | 386 | hung &= ~stuck; |
388 | len = scnprintf(msg, sizeof(msg), | 387 | len = scnprintf(msg, sizeof(msg), |
389 | "%s on ", stuck == hung ? "No progress" : "Hang"); | 388 | "%s on ", stuck == hung ? "no progress" : "hang"); |
390 | for_each_engine_masked(engine, i915, hung, tmp) | 389 | for_each_engine_masked(engine, i915, hung, tmp) |
391 | len += scnprintf(msg + len, sizeof(msg) - len, | 390 | len += scnprintf(msg + len, sizeof(msg) - len, |
392 | "%s, ", engine->name); | 391 | "%s, ", engine->name); |
393 | msg[len-2] = '\0'; | 392 | msg[len-2] = '\0'; |
394 | 393 | ||
395 | return i915_handle_error(i915, hung, "%s", msg); | 394 | return i915_handle_error(i915, hung, I915_ERROR_CAPTURE, "%s", msg); |
396 | } | 395 | } |
397 | 396 | ||
398 | /* | 397 | /* |
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index 14ca5d3057a7..2db5da550a1c 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c | |||
@@ -37,6 +37,43 @@ static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, | |||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | static bool hdcp_key_loadable(struct drm_i915_private *dev_priv) | ||
41 | { | ||
42 | struct i915_power_domains *power_domains = &dev_priv->power_domains; | ||
43 | struct i915_power_well *power_well; | ||
44 | enum i915_power_well_id id; | ||
45 | bool enabled = false; | ||
46 | |||
47 | /* | ||
48 | * On HSW and BDW, Display HW loads the Key as soon as Display resumes. | ||
49 | * On all BXT+, SW can load the keys only when the PW#1 is turned on. | ||
50 | */ | ||
51 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||
52 | id = HSW_DISP_PW_GLOBAL; | ||
53 | else | ||
54 | id = SKL_DISP_PW_1; | ||
55 | |||
56 | mutex_lock(&power_domains->lock); | ||
57 | |||
58 | /* PG1 (power well #1) needs to be enabled */ | ||
59 | for_each_power_well(dev_priv, power_well) { | ||
60 | if (power_well->id == id) { | ||
61 | enabled = power_well->ops->is_enabled(dev_priv, | ||
62 | power_well); | ||
63 | break; | ||
64 | } | ||
65 | } | ||
66 | mutex_unlock(&power_domains->lock); | ||
67 | |||
68 | /* | ||
69 | * Another req for hdcp key loadability is enabled state of pll for | ||
70 | * cdclk. Without active crtc we wont land here. So we are assuming that | ||
71 | * cdclk is already on. | ||
72 | */ | ||
73 | |||
74 | return enabled; | ||
75 | } | ||
76 | |||
40 | static void intel_hdcp_clear_keys(struct drm_i915_private *dev_priv) | 77 | static void intel_hdcp_clear_keys(struct drm_i915_private *dev_priv) |
41 | { | 78 | { |
42 | I915_WRITE(HDCP_KEY_CONF, HDCP_CLEAR_KEYS_TRIGGER); | 79 | I915_WRITE(HDCP_KEY_CONF, HDCP_CLEAR_KEYS_TRIGGER); |
@@ -142,53 +179,17 @@ bool intel_hdcp_is_ksv_valid(u8 *ksv) | |||
142 | return true; | 179 | return true; |
143 | } | 180 | } |
144 | 181 | ||
145 | /* Implements Part 2 of the HDCP authorization procedure */ | ||
146 | static | 182 | static |
147 | int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, | 183 | int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, |
148 | const struct intel_hdcp_shim *shim) | 184 | const struct intel_hdcp_shim *shim, |
185 | u8 *ksv_fifo, u8 num_downstream, u8 *bstatus) | ||
149 | { | 186 | { |
150 | struct drm_i915_private *dev_priv; | 187 | struct drm_i915_private *dev_priv; |
151 | u32 vprime, sha_text, sha_leftovers, rep_ctl; | 188 | u32 vprime, sha_text, sha_leftovers, rep_ctl; |
152 | u8 bstatus[2], num_downstream, *ksv_fifo; | ||
153 | int ret, i, j, sha_idx; | 189 | int ret, i, j, sha_idx; |
154 | 190 | ||
155 | dev_priv = intel_dig_port->base.base.dev->dev_private; | 191 | dev_priv = intel_dig_port->base.base.dev->dev_private; |
156 | 192 | ||
157 | ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim); | ||
158 | if (ret) { | ||
159 | DRM_ERROR("KSV list failed to become ready (%d)\n", ret); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | ret = shim->read_bstatus(intel_dig_port, bstatus); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) || | ||
168 | DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) { | ||
169 | DRM_ERROR("Max Topology Limit Exceeded\n"); | ||
170 | return -EPERM; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * When repeater reports 0 device count, HDCP1.4 spec allows disabling | ||
175 | * the HDCP encryption. That implies that repeater can't have its own | ||
176 | * display. As there is no consumption of encrypted content in the | ||
177 | * repeater with 0 downstream devices, we are failing the | ||
178 | * authentication. | ||
179 | */ | ||
180 | num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]); | ||
181 | if (num_downstream == 0) | ||
182 | return -EINVAL; | ||
183 | |||
184 | ksv_fifo = kzalloc(num_downstream * DRM_HDCP_KSV_LEN, GFP_KERNEL); | ||
185 | if (!ksv_fifo) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | ret = shim->read_ksv_fifo(intel_dig_port, num_downstream, ksv_fifo); | ||
189 | if (ret) | ||
190 | return ret; | ||
191 | |||
192 | /* Process V' values from the receiver */ | 193 | /* Process V' values from the receiver */ |
193 | for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++) { | 194 | for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++) { |
194 | ret = shim->read_v_prime_part(intel_dig_port, i, &vprime); | 195 | ret = shim->read_v_prime_part(intel_dig_port, i, &vprime); |
@@ -353,7 +354,8 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, | |||
353 | return ret; | 354 | return ret; |
354 | sha_idx += sizeof(sha_text); | 355 | sha_idx += sizeof(sha_text); |
355 | } else { | 356 | } else { |
356 | DRM_ERROR("Invalid number of leftovers %d\n", sha_leftovers); | 357 | DRM_DEBUG_KMS("Invalid number of leftovers %d\n", |
358 | sha_leftovers); | ||
357 | return -EINVAL; | 359 | return -EINVAL; |
358 | } | 360 | } |
359 | 361 | ||
@@ -381,17 +383,83 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, | |||
381 | if (intel_wait_for_register(dev_priv, HDCP_REP_CTL, | 383 | if (intel_wait_for_register(dev_priv, HDCP_REP_CTL, |
382 | HDCP_SHA1_COMPLETE, | 384 | HDCP_SHA1_COMPLETE, |
383 | HDCP_SHA1_COMPLETE, 1)) { | 385 | HDCP_SHA1_COMPLETE, 1)) { |
384 | DRM_ERROR("Timed out waiting for SHA1 complete\n"); | 386 | DRM_DEBUG_KMS("Timed out waiting for SHA1 complete\n"); |
385 | return -ETIMEDOUT; | 387 | return -ETIMEDOUT; |
386 | } | 388 | } |
387 | if (!(I915_READ(HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) { | 389 | if (!(I915_READ(HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) { |
388 | DRM_ERROR("SHA-1 mismatch, HDCP failed\n"); | 390 | DRM_DEBUG_KMS("SHA-1 mismatch, HDCP failed\n"); |
389 | return -ENXIO; | 391 | return -ENXIO; |
390 | } | 392 | } |
391 | 393 | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* Implements Part 2 of the HDCP authorization procedure */ | ||
398 | static | ||
399 | int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, | ||
400 | const struct intel_hdcp_shim *shim) | ||
401 | { | ||
402 | u8 bstatus[2], num_downstream, *ksv_fifo; | ||
403 | int ret, i, tries = 3; | ||
404 | |||
405 | ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim); | ||
406 | if (ret) { | ||
407 | DRM_ERROR("KSV list failed to become ready (%d)\n", ret); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | ret = shim->read_bstatus(intel_dig_port, bstatus); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) || | ||
416 | DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) { | ||
417 | DRM_ERROR("Max Topology Limit Exceeded\n"); | ||
418 | return -EPERM; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * When repeater reports 0 device count, HDCP1.4 spec allows disabling | ||
423 | * the HDCP encryption. That implies that repeater can't have its own | ||
424 | * display. As there is no consumption of encrypted content in the | ||
425 | * repeater with 0 downstream devices, we are failing the | ||
426 | * authentication. | ||
427 | */ | ||
428 | num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]); | ||
429 | if (num_downstream == 0) | ||
430 | return -EINVAL; | ||
431 | |||
432 | ksv_fifo = kzalloc(num_downstream * DRM_HDCP_KSV_LEN, GFP_KERNEL); | ||
433 | if (!ksv_fifo) | ||
434 | return -ENOMEM; | ||
435 | |||
436 | ret = shim->read_ksv_fifo(intel_dig_port, num_downstream, ksv_fifo); | ||
437 | if (ret) | ||
438 | goto err; | ||
439 | |||
440 | /* | ||
441 | * When V prime mismatches, DP Spec mandates re-read of | ||
442 | * V prime atleast twice. | ||
443 | */ | ||
444 | for (i = 0; i < tries; i++) { | ||
445 | ret = intel_hdcp_validate_v_prime(intel_dig_port, shim, | ||
446 | ksv_fifo, num_downstream, | ||
447 | bstatus); | ||
448 | if (!ret) | ||
449 | break; | ||
450 | } | ||
451 | |||
452 | if (i == tries) { | ||
453 | DRM_ERROR("V Prime validation failed.(%d)\n", ret); | ||
454 | goto err; | ||
455 | } | ||
456 | |||
392 | DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n", | 457 | DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n", |
393 | num_downstream); | 458 | num_downstream); |
394 | return 0; | 459 | ret = 0; |
460 | err: | ||
461 | kfree(ksv_fifo); | ||
462 | return ret; | ||
395 | } | 463 | } |
396 | 464 | ||
397 | /* Implements Part 1 of the HDCP authorization procedure */ | 465 | /* Implements Part 1 of the HDCP authorization procedure */ |
@@ -506,15 +574,26 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port, | |||
506 | */ | 574 | */ |
507 | wait_remaining_ms_from_jiffies(r0_prime_gen_start, 300); | 575 | wait_remaining_ms_from_jiffies(r0_prime_gen_start, 300); |
508 | 576 | ||
509 | ri.reg = 0; | 577 | tries = 3; |
510 | ret = shim->read_ri_prime(intel_dig_port, ri.shim); | ||
511 | if (ret) | ||
512 | return ret; | ||
513 | I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); | ||
514 | 578 | ||
515 | /* Wait for Ri prime match */ | 579 | /* |
516 | if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & | 580 | * DP HDCP Spec mandates the two more reattempt to read R0, incase |
517 | (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) { | 581 | * of R0 mismatch. |
582 | */ | ||
583 | for (i = 0; i < tries; i++) { | ||
584 | ri.reg = 0; | ||
585 | ret = shim->read_ri_prime(intel_dig_port, ri.shim); | ||
586 | if (ret) | ||
587 | return ret; | ||
588 | I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); | ||
589 | |||
590 | /* Wait for Ri prime match */ | ||
591 | if (!wait_for(I915_READ(PORT_HDCP_STATUS(port)) & | ||
592 | (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | if (i == tries) { | ||
518 | DRM_ERROR("Timed out waiting for Ri prime match (%x)\n", | 597 | DRM_ERROR("Timed out waiting for Ri prime match (%x)\n", |
519 | I915_READ(PORT_HDCP_STATUS(port))); | 598 | I915_READ(PORT_HDCP_STATUS(port))); |
520 | return -ETIMEDOUT; | 599 | return -ETIMEDOUT; |
@@ -580,8 +659,8 @@ static int _intel_hdcp_enable(struct intel_connector *connector) | |||
580 | DRM_DEBUG_KMS("[%s:%d] HDCP is being enabled...\n", | 659 | DRM_DEBUG_KMS("[%s:%d] HDCP is being enabled...\n", |
581 | connector->base.name, connector->base.base.id); | 660 | connector->base.name, connector->base.base.id); |
582 | 661 | ||
583 | if (!(I915_READ(SKL_FUSE_STATUS) & SKL_FUSE_PG_DIST_STATUS(1))) { | 662 | if (!hdcp_key_loadable(dev_priv)) { |
584 | DRM_ERROR("PG1 is disabled, cannot load keys\n"); | 663 | DRM_ERROR("HDCP key Load is not possible\n"); |
585 | return -ENXIO; | 664 | return -ENXIO; |
586 | } | 665 | } |
587 | 666 | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 1baef4ac7ecb..ee929f31f7db 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -2082,41 +2082,33 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c | |||
2082 | * it enables scrambling. This should be called before enabling the HDMI | 2082 | * it enables scrambling. This should be called before enabling the HDMI |
2083 | * 2.0 port, as the sink can choose to disable the scrambling if it doesn't | 2083 | * 2.0 port, as the sink can choose to disable the scrambling if it doesn't |
2084 | * detect a scrambled clock within 100 ms. | 2084 | * detect a scrambled clock within 100 ms. |
2085 | * | ||
2086 | * Returns: | ||
2087 | * True on success, false on failure. | ||
2085 | */ | 2088 | */ |
2086 | void intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, | 2089 | bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, |
2087 | struct drm_connector *connector, | 2090 | struct drm_connector *connector, |
2088 | bool high_tmds_clock_ratio, | 2091 | bool high_tmds_clock_ratio, |
2089 | bool scrambling) | 2092 | bool scrambling) |
2090 | { | 2093 | { |
2094 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
2091 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | 2095 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
2092 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
2093 | struct drm_scrambling *sink_scrambling = | 2096 | struct drm_scrambling *sink_scrambling = |
2094 | &connector->display_info.hdmi.scdc.scrambling; | 2097 | &connector->display_info.hdmi.scdc.scrambling; |
2095 | struct i2c_adapter *adptr = intel_gmbus_get_adapter(dev_priv, | 2098 | struct i2c_adapter *adapter = |
2096 | intel_hdmi->ddc_bus); | 2099 | intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
2097 | bool ret; | ||
2098 | 2100 | ||
2099 | if (!sink_scrambling->supported) | 2101 | if (!sink_scrambling->supported) |
2100 | return; | 2102 | return true; |
2101 | |||
2102 | DRM_DEBUG_KMS("Setting sink scrambling for enc:%s connector:%s\n", | ||
2103 | encoder->base.name, connector->name); | ||
2104 | 2103 | ||
2105 | /* Set TMDS bit clock ratio to 1/40 or 1/10 */ | 2104 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n", |
2106 | ret = drm_scdc_set_high_tmds_clock_ratio(adptr, high_tmds_clock_ratio); | 2105 | connector->base.id, connector->name, |
2107 | if (!ret) { | 2106 | yesno(scrambling), high_tmds_clock_ratio ? 40 : 10); |
2108 | DRM_ERROR("Set TMDS ratio failed\n"); | ||
2109 | return; | ||
2110 | } | ||
2111 | |||
2112 | /* Enable/disable sink scrambling */ | ||
2113 | ret = drm_scdc_set_scrambling(adptr, scrambling); | ||
2114 | if (!ret) { | ||
2115 | DRM_ERROR("Set sink scrambling failed\n"); | ||
2116 | return; | ||
2117 | } | ||
2118 | 2107 | ||
2119 | DRM_DEBUG_KMS("sink scrambling handled\n"); | 2108 | /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */ |
2109 | return drm_scdc_set_high_tmds_clock_ratio(adapter, | ||
2110 | high_tmds_clock_ratio) && | ||
2111 | drm_scdc_set_scrambling(adapter, scrambling); | ||
2120 | } | 2112 | } |
2121 | 2113 | ||
2122 | static u8 chv_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) | 2114 | static u8 chv_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) |
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index 0e3d3e89d66a..43aa92beff2a 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c | |||
@@ -100,6 +100,8 @@ enum port intel_hpd_pin_to_port(struct drm_i915_private *dev_priv, | |||
100 | if (IS_CNL_WITH_PORT_F(dev_priv)) | 100 | if (IS_CNL_WITH_PORT_F(dev_priv)) |
101 | return PORT_F; | 101 | return PORT_F; |
102 | return PORT_E; | 102 | return PORT_E; |
103 | case HPD_PORT_F: | ||
104 | return PORT_F; | ||
103 | default: | 105 | default: |
104 | return PORT_NONE; /* no port for this pin */ | 106 | return PORT_NONE; /* no port for this pin */ |
105 | } | 107 | } |
@@ -132,6 +134,7 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, | |||
132 | case PORT_F: | 134 | case PORT_F: |
133 | if (IS_CNL_WITH_PORT_F(dev_priv)) | 135 | if (IS_CNL_WITH_PORT_F(dev_priv)) |
134 | return HPD_PORT_E; | 136 | return HPD_PORT_E; |
137 | return HPD_PORT_F; | ||
135 | default: | 138 | default: |
136 | MISSING_CASE(port); | 139 | MISSING_CASE(port); |
137 | return HPD_NONE; | 140 | return HPD_NONE; |
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 65e2afb9b955..291285277403 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c | |||
@@ -55,7 +55,7 @@ int intel_huc_auth(struct intel_huc *huc) | |||
55 | return -ENOEXEC; | 55 | return -ENOEXEC; |
56 | 56 | ||
57 | vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0, | 57 | vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0, |
58 | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); | 58 | PIN_OFFSET_BIAS | guc->ggtt_pin_bias); |
59 | if (IS_ERR(vma)) { | 59 | if (IS_ERR(vma)) { |
60 | ret = PTR_ERR(vma); | 60 | ret = PTR_ERR(vma); |
61 | DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret); | 61 | DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret); |
@@ -63,7 +63,8 @@ int intel_huc_auth(struct intel_huc *huc) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | ret = intel_guc_auth_huc(guc, | 65 | ret = intel_guc_auth_huc(guc, |
66 | guc_ggtt_offset(vma) + huc->fw.rsa_offset); | 66 | intel_guc_ggtt_offset(guc, vma) + |
67 | huc->fw.rsa_offset); | ||
67 | if (ret) { | 68 | if (ret) { |
68 | DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); | 69 | DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); |
69 | goto fail_unpin; | 70 | goto fail_unpin; |
@@ -91,3 +92,28 @@ fail: | |||
91 | DRM_ERROR("HuC: Authentication failed %d\n", ret); | 92 | DRM_ERROR("HuC: Authentication failed %d\n", ret); |
92 | return ret; | 93 | return ret; |
93 | } | 94 | } |
95 | |||
96 | /** | ||
97 | * intel_huc_check_status() - check HuC status | ||
98 | * @huc: intel_huc structure | ||
99 | * | ||
100 | * This function reads status register to verify if HuC | ||
101 | * firmware was successfully loaded. | ||
102 | * | ||
103 | * Returns positive value if HuC firmware is loaded and verified | ||
104 | * and -ENODEV if HuC is not present. | ||
105 | */ | ||
106 | int intel_huc_check_status(struct intel_huc *huc) | ||
107 | { | ||
108 | struct drm_i915_private *dev_priv = huc_to_i915(huc); | ||
109 | u32 status; | ||
110 | |||
111 | if (!HAS_HUC(dev_priv)) | ||
112 | return -ENODEV; | ||
113 | |||
114 | intel_runtime_pm_get(dev_priv); | ||
115 | status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; | ||
116 | intel_runtime_pm_put(dev_priv); | ||
117 | |||
118 | return status; | ||
119 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h index 5d6e804f9771..aa854907abac 100644 --- a/drivers/gpu/drm/i915/intel_huc.h +++ b/drivers/gpu/drm/i915/intel_huc.h | |||
@@ -37,5 +37,12 @@ struct intel_huc { | |||
37 | 37 | ||
38 | void intel_huc_init_early(struct intel_huc *huc); | 38 | void intel_huc_init_early(struct intel_huc *huc); |
39 | int intel_huc_auth(struct intel_huc *huc); | 39 | int intel_huc_auth(struct intel_huc *huc); |
40 | int intel_huc_check_status(struct intel_huc *huc); | ||
41 | |||
42 | static inline int intel_huc_sanitize(struct intel_huc *huc) | ||
43 | { | ||
44 | intel_uc_fw_sanitize(&huc->fw); | ||
45 | return 0; | ||
46 | } | ||
40 | 47 | ||
41 | #endif | 48 | #endif |
diff --git a/drivers/gpu/drm/i915/intel_huc_fw.c b/drivers/gpu/drm/i915/intel_huc_fw.c index c66afa9b989a..f93d2384d482 100644 --- a/drivers/gpu/drm/i915/intel_huc_fw.c +++ b/drivers/gpu/drm/i915/intel_huc_fw.c | |||
@@ -118,7 +118,8 @@ static int huc_fw_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) | |||
118 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 118 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
119 | 119 | ||
120 | /* Set the source address for the uCode */ | 120 | /* Set the source address for the uCode */ |
121 | offset = guc_ggtt_offset(vma) + huc_fw->header_offset; | 121 | offset = intel_guc_ggtt_offset(&dev_priv->guc, vma) + |
122 | huc_fw->header_offset; | ||
122 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); | 123 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); |
123 | I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); | 124 | I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); |
124 | 125 | ||
@@ -154,9 +155,8 @@ static int huc_fw_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) | |||
154 | * Called from intel_uc_init_hw() during driver load, resume from sleep and | 155 | * Called from intel_uc_init_hw() during driver load, resume from sleep and |
155 | * after a GPU reset. Note that HuC must be loaded before GuC. | 156 | * after a GPU reset. Note that HuC must be loaded before GuC. |
156 | * | 157 | * |
157 | * The firmware image should have already been fetched into memory by the | 158 | * The firmware image should have already been fetched into memory, so only |
158 | * earlier call to intel_uc_init_fw(), so here we need to only check that | 159 | * check that fetch succeeded, and then transfer the image to the h/w. |
159 | * fetch succeeded, and then transfer the image to the h/w. | ||
160 | * | 160 | * |
161 | * Return: non-zero code on error | 161 | * Return: non-zero code on error |
162 | */ | 162 | */ |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e3a5f673ff67..c7c85134a84a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -139,6 +139,7 @@ | |||
139 | #include "i915_gem_render_state.h" | 139 | #include "i915_gem_render_state.h" |
140 | #include "intel_lrc_reg.h" | 140 | #include "intel_lrc_reg.h" |
141 | #include "intel_mocs.h" | 141 | #include "intel_mocs.h" |
142 | #include "intel_workarounds.h" | ||
142 | 143 | ||
143 | #define RING_EXECLIST_QFULL (1 << 0x2) | 144 | #define RING_EXECLIST_QFULL (1 << 0x2) |
144 | #define RING_EXECLIST1_VALID (1 << 0x3) | 145 | #define RING_EXECLIST1_VALID (1 << 0x3) |
@@ -183,7 +184,8 @@ static inline bool need_preempt(const struct intel_engine_cs *engine, | |||
183 | const struct i915_request *last, | 184 | const struct i915_request *last, |
184 | int prio) | 185 | int prio) |
185 | { | 186 | { |
186 | return engine->i915->preempt_context && prio > max(rq_prio(last), 0); | 187 | return (intel_engine_has_preemption(engine) && |
188 | __execlists_need_preempt(prio, rq_prio(last))); | ||
187 | } | 189 | } |
188 | 190 | ||
189 | /** | 191 | /** |
@@ -374,6 +376,19 @@ execlists_context_status_change(struct i915_request *rq, unsigned long status) | |||
374 | status, rq); | 376 | status, rq); |
375 | } | 377 | } |
376 | 378 | ||
379 | inline void | ||
380 | execlists_user_begin(struct intel_engine_execlists *execlists, | ||
381 | const struct execlist_port *port) | ||
382 | { | ||
383 | execlists_set_active_once(execlists, EXECLISTS_ACTIVE_USER); | ||
384 | } | ||
385 | |||
386 | inline void | ||
387 | execlists_user_end(struct intel_engine_execlists *execlists) | ||
388 | { | ||
389 | execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); | ||
390 | } | ||
391 | |||
377 | static inline void | 392 | static inline void |
378 | execlists_context_schedule_in(struct i915_request *rq) | 393 | execlists_context_schedule_in(struct i915_request *rq) |
379 | { | 394 | { |
@@ -454,10 +469,12 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) | |||
454 | desc = execlists_update_context(rq); | 469 | desc = execlists_update_context(rq); |
455 | GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); | 470 | GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); |
456 | 471 | ||
457 | GEM_TRACE("%s in[%d]: ctx=%d.%d, seqno=%x, prio=%d\n", | 472 | GEM_TRACE("%s in[%d]: ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n", |
458 | engine->name, n, | 473 | engine->name, n, |
459 | port[n].context_id, count, | 474 | port[n].context_id, count, |
460 | rq->global_seqno, | 475 | rq->global_seqno, |
476 | rq->fence.context, rq->fence.seqno, | ||
477 | intel_engine_get_seqno(engine), | ||
461 | rq_prio(rq)); | 478 | rq_prio(rq)); |
462 | } else { | 479 | } else { |
463 | GEM_BUG_ON(!n); | 480 | GEM_BUG_ON(!n); |
@@ -697,8 +714,27 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
697 | if (p->priority != I915_PRIORITY_NORMAL) | 714 | if (p->priority != I915_PRIORITY_NORMAL) |
698 | kmem_cache_free(engine->i915->priorities, p); | 715 | kmem_cache_free(engine->i915->priorities, p); |
699 | } | 716 | } |
717 | |||
700 | done: | 718 | done: |
701 | execlists->queue_priority = rb ? to_priolist(rb)->priority : INT_MIN; | 719 | /* |
720 | * Here be a bit of magic! Or sleight-of-hand, whichever you prefer. | ||
721 | * | ||
722 | * We choose queue_priority such that if we add a request of greater | ||
723 | * priority than this, we kick the submission tasklet to decide on | ||
724 | * the right order of submitting the requests to hardware. We must | ||
725 | * also be prepared to reorder requests as they are in-flight on the | ||
726 | * HW. We derive the queue_priority then as the first "hole" in | ||
727 | * the HW submission ports and if there are no available slots, | ||
728 | * the priority of the lowest executing request, i.e. last. | ||
729 | * | ||
730 | * When we do receive a higher priority request ready to run from the | ||
731 | * user, see queue_request(), the queue_priority is bumped to that | ||
732 | * request triggering preemption on the next dequeue (or subsequent | ||
733 | * interrupt for secondary ports). | ||
734 | */ | ||
735 | execlists->queue_priority = | ||
736 | port != execlists->port ? rq_prio(last) : INT_MIN; | ||
737 | |||
702 | execlists->first = rb; | 738 | execlists->first = rb; |
703 | if (submit) | 739 | if (submit) |
704 | port_assign(port, last); | 740 | port_assign(port, last); |
@@ -710,7 +746,7 @@ unlock: | |||
710 | spin_unlock_irq(&engine->timeline->lock); | 746 | spin_unlock_irq(&engine->timeline->lock); |
711 | 747 | ||
712 | if (submit) { | 748 | if (submit) { |
713 | execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | 749 | execlists_user_begin(execlists, execlists->port); |
714 | execlists_submit_ports(engine); | 750 | execlists_submit_ports(engine); |
715 | } | 751 | } |
716 | 752 | ||
@@ -727,6 +763,13 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) | |||
727 | while (num_ports-- && port_isset(port)) { | 763 | while (num_ports-- && port_isset(port)) { |
728 | struct i915_request *rq = port_request(port); | 764 | struct i915_request *rq = port_request(port); |
729 | 765 | ||
766 | GEM_TRACE("%s:port%u global=%d (fence %llx:%d), (current %d)\n", | ||
767 | rq->engine->name, | ||
768 | (unsigned int)(port - execlists->port), | ||
769 | rq->global_seqno, | ||
770 | rq->fence.context, rq->fence.seqno, | ||
771 | intel_engine_get_seqno(rq->engine)); | ||
772 | |||
730 | GEM_BUG_ON(!execlists->active); | 773 | GEM_BUG_ON(!execlists->active); |
731 | intel_engine_context_out(rq->engine); | 774 | intel_engine_context_out(rq->engine); |
732 | 775 | ||
@@ -741,7 +784,58 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) | |||
741 | port++; | 784 | port++; |
742 | } | 785 | } |
743 | 786 | ||
744 | execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); | 787 | execlists_user_end(execlists); |
788 | } | ||
789 | |||
790 | static void clear_gtiir(struct intel_engine_cs *engine) | ||
791 | { | ||
792 | static const u8 gtiir[] = { | ||
793 | [RCS] = 0, | ||
794 | [BCS] = 0, | ||
795 | [VCS] = 1, | ||
796 | [VCS2] = 1, | ||
797 | [VECS] = 3, | ||
798 | }; | ||
799 | struct drm_i915_private *dev_priv = engine->i915; | ||
800 | int i; | ||
801 | |||
802 | /* TODO: correctly reset irqs for gen11 */ | ||
803 | if (WARN_ON_ONCE(INTEL_GEN(engine->i915) >= 11)) | ||
804 | return; | ||
805 | |||
806 | GEM_BUG_ON(engine->id >= ARRAY_SIZE(gtiir)); | ||
807 | |||
808 | /* | ||
809 | * Clear any pending interrupt state. | ||
810 | * | ||
811 | * We do it twice out of paranoia that some of the IIR are | ||
812 | * double buffered, and so if we only reset it once there may | ||
813 | * still be an interrupt pending. | ||
814 | */ | ||
815 | for (i = 0; i < 2; i++) { | ||
816 | I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), | ||
817 | engine->irq_keep_mask); | ||
818 | POSTING_READ(GEN8_GT_IIR(gtiir[engine->id])); | ||
819 | } | ||
820 | GEM_BUG_ON(I915_READ(GEN8_GT_IIR(gtiir[engine->id])) & | ||
821 | engine->irq_keep_mask); | ||
822 | } | ||
823 | |||
824 | static void reset_irq(struct intel_engine_cs *engine) | ||
825 | { | ||
826 | /* Mark all CS interrupts as complete */ | ||
827 | smp_store_mb(engine->execlists.active, 0); | ||
828 | synchronize_hardirq(engine->i915->drm.irq); | ||
829 | |||
830 | clear_gtiir(engine); | ||
831 | |||
832 | /* | ||
833 | * The port is checked prior to scheduling a tasklet, but | ||
834 | * just in case we have suspended the tasklet to do the | ||
835 | * wedging make sure that when it wakes, it decides there | ||
836 | * is no work to do by clearing the irq_posted bit. | ||
837 | */ | ||
838 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | ||
745 | } | 839 | } |
746 | 840 | ||
747 | static void execlists_cancel_requests(struct intel_engine_cs *engine) | 841 | static void execlists_cancel_requests(struct intel_engine_cs *engine) |
@@ -751,7 +845,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
751 | struct rb_node *rb; | 845 | struct rb_node *rb; |
752 | unsigned long flags; | 846 | unsigned long flags; |
753 | 847 | ||
754 | GEM_TRACE("%s\n", engine->name); | 848 | GEM_TRACE("%s current %d\n", |
849 | engine->name, intel_engine_get_seqno(engine)); | ||
755 | 850 | ||
756 | /* | 851 | /* |
757 | * Before we call engine->cancel_requests(), we should have exclusive | 852 | * Before we call engine->cancel_requests(), we should have exclusive |
@@ -771,6 +866,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
771 | 866 | ||
772 | /* Cancel the requests on the HW and clear the ELSP tracker. */ | 867 | /* Cancel the requests on the HW and clear the ELSP tracker. */ |
773 | execlists_cancel_port_requests(execlists); | 868 | execlists_cancel_port_requests(execlists); |
869 | reset_irq(engine); | ||
774 | 870 | ||
775 | spin_lock(&engine->timeline->lock); | 871 | spin_lock(&engine->timeline->lock); |
776 | 872 | ||
@@ -809,17 +905,6 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
809 | 905 | ||
810 | spin_unlock(&engine->timeline->lock); | 906 | spin_unlock(&engine->timeline->lock); |
811 | 907 | ||
812 | /* | ||
813 | * The port is checked prior to scheduling a tasklet, but | ||
814 | * just in case we have suspended the tasklet to do the | ||
815 | * wedging make sure that when it wakes, it decides there | ||
816 | * is no work to do by clearing the irq_posted bit. | ||
817 | */ | ||
818 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | ||
819 | |||
820 | /* Mark all CS interrupts as complete */ | ||
821 | execlists->active = 0; | ||
822 | |||
823 | local_irq_restore(flags); | 908 | local_irq_restore(flags); |
824 | } | 909 | } |
825 | 910 | ||
@@ -831,7 +916,7 @@ static void execlists_submission_tasklet(unsigned long data) | |||
831 | { | 916 | { |
832 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; | 917 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; |
833 | struct intel_engine_execlists * const execlists = &engine->execlists; | 918 | struct intel_engine_execlists * const execlists = &engine->execlists; |
834 | struct execlist_port * const port = execlists->port; | 919 | struct execlist_port *port = execlists->port; |
835 | struct drm_i915_private *dev_priv = engine->i915; | 920 | struct drm_i915_private *dev_priv = engine->i915; |
836 | bool fw = false; | 921 | bool fw = false; |
837 | 922 | ||
@@ -958,10 +1043,13 @@ static void execlists_submission_tasklet(unsigned long data) | |||
958 | EXECLISTS_ACTIVE_USER)); | 1043 | EXECLISTS_ACTIVE_USER)); |
959 | 1044 | ||
960 | rq = port_unpack(port, &count); | 1045 | rq = port_unpack(port, &count); |
961 | GEM_TRACE("%s out[0]: ctx=%d.%d, seqno=%x, prio=%d\n", | 1046 | GEM_TRACE("%s out[0]: ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n", |
962 | engine->name, | 1047 | engine->name, |
963 | port->context_id, count, | 1048 | port->context_id, count, |
964 | rq ? rq->global_seqno : 0, | 1049 | rq ? rq->global_seqno : 0, |
1050 | rq ? rq->fence.context : 0, | ||
1051 | rq ? rq->fence.seqno : 0, | ||
1052 | intel_engine_get_seqno(engine), | ||
965 | rq ? rq_prio(rq) : 0); | 1053 | rq ? rq_prio(rq) : 0); |
966 | 1054 | ||
967 | /* Check the context/desc id for this event matches */ | 1055 | /* Check the context/desc id for this event matches */ |
@@ -969,10 +1057,28 @@ static void execlists_submission_tasklet(unsigned long data) | |||
969 | 1057 | ||
970 | GEM_BUG_ON(count == 0); | 1058 | GEM_BUG_ON(count == 0); |
971 | if (--count == 0) { | 1059 | if (--count == 0) { |
1060 | /* | ||
1061 | * On the final event corresponding to the | ||
1062 | * submission of this context, we expect either | ||
1063 | * an element-switch event or a completion | ||
1064 | * event (and on completion, the active-idle | ||
1065 | * marker). No more preemptions, lite-restore | ||
1066 | * or otherwise. | ||
1067 | */ | ||
972 | GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); | 1068 | GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); |
973 | GEM_BUG_ON(port_isset(&port[1]) && | 1069 | GEM_BUG_ON(port_isset(&port[1]) && |
974 | !(status & GEN8_CTX_STATUS_ELEMENT_SWITCH)); | 1070 | !(status & GEN8_CTX_STATUS_ELEMENT_SWITCH)); |
1071 | GEM_BUG_ON(!port_isset(&port[1]) && | ||
1072 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); | ||
1073 | |||
1074 | /* | ||
1075 | * We rely on the hardware being strongly | ||
1076 | * ordered, that the breadcrumb write is | ||
1077 | * coherent (visible from the CPU) before the | ||
1078 | * user interrupt and CSB is processed. | ||
1079 | */ | ||
975 | GEM_BUG_ON(!i915_request_completed(rq)); | 1080 | GEM_BUG_ON(!i915_request_completed(rq)); |
1081 | |||
976 | execlists_context_schedule_out(rq); | 1082 | execlists_context_schedule_out(rq); |
977 | trace_i915_request_out(rq); | 1083 | trace_i915_request_out(rq); |
978 | i915_request_put(rq); | 1084 | i915_request_put(rq); |
@@ -980,17 +1086,14 @@ static void execlists_submission_tasklet(unsigned long data) | |||
980 | GEM_TRACE("%s completed ctx=%d\n", | 1086 | GEM_TRACE("%s completed ctx=%d\n", |
981 | engine->name, port->context_id); | 1087 | engine->name, port->context_id); |
982 | 1088 | ||
983 | execlists_port_complete(execlists, port); | 1089 | port = execlists_port_complete(execlists, port); |
1090 | if (port_isset(port)) | ||
1091 | execlists_user_begin(execlists, port); | ||
1092 | else | ||
1093 | execlists_user_end(execlists); | ||
984 | } else { | 1094 | } else { |
985 | port_set(port, port_pack(rq, count)); | 1095 | port_set(port, port_pack(rq, count)); |
986 | } | 1096 | } |
987 | |||
988 | /* After the final element, the hw should be idle */ | ||
989 | GEM_BUG_ON(port_count(port) == 0 && | ||
990 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); | ||
991 | if (port_count(port) == 0) | ||
992 | execlists_clear_active(execlists, | ||
993 | EXECLISTS_ACTIVE_USER); | ||
994 | } | 1097 | } |
995 | 1098 | ||
996 | if (head != execlists->csb_head) { | 1099 | if (head != execlists->csb_head) { |
@@ -1019,12 +1122,16 @@ static void queue_request(struct intel_engine_cs *engine, | |||
1019 | list_add_tail(&pt->link, &lookup_priolist(engine, pt, prio)->requests); | 1122 | list_add_tail(&pt->link, &lookup_priolist(engine, pt, prio)->requests); |
1020 | } | 1123 | } |
1021 | 1124 | ||
1125 | static void __submit_queue(struct intel_engine_cs *engine, int prio) | ||
1126 | { | ||
1127 | engine->execlists.queue_priority = prio; | ||
1128 | tasklet_hi_schedule(&engine->execlists.tasklet); | ||
1129 | } | ||
1130 | |||
1022 | static void submit_queue(struct intel_engine_cs *engine, int prio) | 1131 | static void submit_queue(struct intel_engine_cs *engine, int prio) |
1023 | { | 1132 | { |
1024 | if (prio > engine->execlists.queue_priority) { | 1133 | if (prio > engine->execlists.queue_priority) |
1025 | engine->execlists.queue_priority = prio; | 1134 | __submit_queue(engine, prio); |
1026 | tasklet_hi_schedule(&engine->execlists.tasklet); | ||
1027 | } | ||
1028 | } | 1135 | } |
1029 | 1136 | ||
1030 | static void execlists_submit_request(struct i915_request *request) | 1137 | static void execlists_submit_request(struct i915_request *request) |
@@ -1157,7 +1264,10 @@ static void execlists_schedule(struct i915_request *request, int prio) | |||
1157 | __list_del_entry(&pt->link); | 1264 | __list_del_entry(&pt->link); |
1158 | queue_request(engine, pt, prio); | 1265 | queue_request(engine, pt, prio); |
1159 | } | 1266 | } |
1160 | submit_queue(engine, prio); | 1267 | |
1268 | if (prio > engine->execlists.queue_priority && | ||
1269 | i915_sw_fence_done(&pt_to_request(pt)->submit)) | ||
1270 | __submit_queue(engine, prio); | ||
1161 | } | 1271 | } |
1162 | 1272 | ||
1163 | spin_unlock_irq(&engine->timeline->lock); | 1273 | spin_unlock_irq(&engine->timeline->lock); |
@@ -1224,6 +1334,7 @@ execlists_context_pin(struct intel_engine_cs *engine, | |||
1224 | ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; | 1334 | ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; |
1225 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = | 1335 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = |
1226 | i915_ggtt_offset(ce->ring->vma); | 1336 | i915_ggtt_offset(ce->ring->vma); |
1337 | ce->lrc_reg_state[CTX_RING_HEAD+1] = ce->ring->head; | ||
1227 | 1338 | ||
1228 | ce->state->obj->pin_global++; | 1339 | ce->state->obj->pin_global++; |
1229 | i915_gem_context_get(ctx); | 1340 | i915_gem_context_get(ctx); |
@@ -1574,14 +1685,6 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) | |||
1574 | return ret; | 1685 | return ret; |
1575 | } | 1686 | } |
1576 | 1687 | ||
1577 | static u8 gtiir[] = { | ||
1578 | [RCS] = 0, | ||
1579 | [BCS] = 0, | ||
1580 | [VCS] = 1, | ||
1581 | [VCS2] = 1, | ||
1582 | [VECS] = 3, | ||
1583 | }; | ||
1584 | |||
1585 | static void enable_execlists(struct intel_engine_cs *engine) | 1688 | static void enable_execlists(struct intel_engine_cs *engine) |
1586 | { | 1689 | { |
1587 | struct drm_i915_private *dev_priv = engine->i915; | 1690 | struct drm_i915_private *dev_priv = engine->i915; |
@@ -1641,6 +1744,10 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine) | |||
1641 | if (ret) | 1744 | if (ret) |
1642 | return ret; | 1745 | return ret; |
1643 | 1746 | ||
1747 | ret = intel_whitelist_workarounds_apply(engine); | ||
1748 | if (ret) | ||
1749 | return ret; | ||
1750 | |||
1644 | /* We need to disable the AsyncFlip performance optimisations in order | 1751 | /* We need to disable the AsyncFlip performance optimisations in order |
1645 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be | 1752 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be |
1646 | * programmed to '1' on all products. | 1753 | * programmed to '1' on all products. |
@@ -1651,7 +1758,7 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine) | |||
1651 | 1758 | ||
1652 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); | 1759 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); |
1653 | 1760 | ||
1654 | return init_workarounds_ring(engine); | 1761 | return 0; |
1655 | } | 1762 | } |
1656 | 1763 | ||
1657 | static int gen9_init_render_ring(struct intel_engine_cs *engine) | 1764 | static int gen9_init_render_ring(struct intel_engine_cs *engine) |
@@ -1662,32 +1769,11 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) | |||
1662 | if (ret) | 1769 | if (ret) |
1663 | return ret; | 1770 | return ret; |
1664 | 1771 | ||
1665 | return init_workarounds_ring(engine); | 1772 | ret = intel_whitelist_workarounds_apply(engine); |
1666 | } | 1773 | if (ret) |
1667 | 1774 | return ret; | |
1668 | static void reset_irq(struct intel_engine_cs *engine) | ||
1669 | { | ||
1670 | struct drm_i915_private *dev_priv = engine->i915; | ||
1671 | int i; | ||
1672 | |||
1673 | GEM_BUG_ON(engine->id >= ARRAY_SIZE(gtiir)); | ||
1674 | |||
1675 | /* | ||
1676 | * Clear any pending interrupt state. | ||
1677 | * | ||
1678 | * We do it twice out of paranoia that some of the IIR are double | ||
1679 | * buffered, and if we only reset it once there may still be | ||
1680 | * an interrupt pending. | ||
1681 | */ | ||
1682 | for (i = 0; i < 2; i++) { | ||
1683 | I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), | ||
1684 | GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); | ||
1685 | POSTING_READ(GEN8_GT_IIR(gtiir[engine->id])); | ||
1686 | } | ||
1687 | GEM_BUG_ON(I915_READ(GEN8_GT_IIR(gtiir[engine->id])) & | ||
1688 | (GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift)); | ||
1689 | 1775 | ||
1690 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 1776 | return 0; |
1691 | } | 1777 | } |
1692 | 1778 | ||
1693 | static void reset_common_ring(struct intel_engine_cs *engine, | 1779 | static void reset_common_ring(struct intel_engine_cs *engine, |
@@ -1697,14 +1783,13 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1697 | struct intel_context *ce; | 1783 | struct intel_context *ce; |
1698 | unsigned long flags; | 1784 | unsigned long flags; |
1699 | 1785 | ||
1700 | GEM_TRACE("%s seqno=%x\n", | 1786 | GEM_TRACE("%s request global=%x, current=%d\n", |
1701 | engine->name, request ? request->global_seqno : 0); | 1787 | engine->name, request ? request->global_seqno : 0, |
1788 | intel_engine_get_seqno(engine)); | ||
1702 | 1789 | ||
1703 | /* See execlists_cancel_requests() for the irq/spinlock split. */ | 1790 | /* See execlists_cancel_requests() for the irq/spinlock split. */ |
1704 | local_irq_save(flags); | 1791 | local_irq_save(flags); |
1705 | 1792 | ||
1706 | reset_irq(engine); | ||
1707 | |||
1708 | /* | 1793 | /* |
1709 | * Catch up with any missed context-switch interrupts. | 1794 | * Catch up with any missed context-switch interrupts. |
1710 | * | 1795 | * |
@@ -1715,15 +1800,13 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1715 | * requests were completed. | 1800 | * requests were completed. |
1716 | */ | 1801 | */ |
1717 | execlists_cancel_port_requests(execlists); | 1802 | execlists_cancel_port_requests(execlists); |
1803 | reset_irq(engine); | ||
1718 | 1804 | ||
1719 | /* Push back any incomplete requests for replay after the reset. */ | 1805 | /* Push back any incomplete requests for replay after the reset. */ |
1720 | spin_lock(&engine->timeline->lock); | 1806 | spin_lock(&engine->timeline->lock); |
1721 | __unwind_incomplete_requests(engine); | 1807 | __unwind_incomplete_requests(engine); |
1722 | spin_unlock(&engine->timeline->lock); | 1808 | spin_unlock(&engine->timeline->lock); |
1723 | 1809 | ||
1724 | /* Mark all CS interrupts as complete */ | ||
1725 | execlists->active = 0; | ||
1726 | |||
1727 | local_irq_restore(flags); | 1810 | local_irq_restore(flags); |
1728 | 1811 | ||
1729 | /* | 1812 | /* |
@@ -2015,7 +2098,7 @@ static int gen8_init_rcs_context(struct i915_request *rq) | |||
2015 | { | 2098 | { |
2016 | int ret; | 2099 | int ret; |
2017 | 2100 | ||
2018 | ret = intel_ring_workarounds_emit(rq); | 2101 | ret = intel_ctx_workarounds_emit(rq); |
2019 | if (ret) | 2102 | if (ret) |
2020 | return ret; | 2103 | return ret; |
2021 | 2104 | ||
@@ -2075,11 +2158,13 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) | |||
2075 | engine->unpark = NULL; | 2158 | engine->unpark = NULL; |
2076 | 2159 | ||
2077 | engine->flags |= I915_ENGINE_SUPPORTS_STATS; | 2160 | engine->flags |= I915_ENGINE_SUPPORTS_STATS; |
2161 | if (engine->i915->preempt_context) | ||
2162 | engine->flags |= I915_ENGINE_HAS_PREEMPTION; | ||
2078 | 2163 | ||
2079 | engine->i915->caps.scheduler = | 2164 | engine->i915->caps.scheduler = |
2080 | I915_SCHEDULER_CAP_ENABLED | | 2165 | I915_SCHEDULER_CAP_ENABLED | |
2081 | I915_SCHEDULER_CAP_PRIORITY; | 2166 | I915_SCHEDULER_CAP_PRIORITY; |
2082 | if (engine->i915->preempt_context) | 2167 | if (intel_engine_has_preemption(engine)) |
2083 | engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; | 2168 | engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; |
2084 | } | 2169 | } |
2085 | 2170 | ||
@@ -2118,7 +2203,20 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) | |||
2118 | static inline void | 2203 | static inline void |
2119 | logical_ring_default_irqs(struct intel_engine_cs *engine) | 2204 | logical_ring_default_irqs(struct intel_engine_cs *engine) |
2120 | { | 2205 | { |
2121 | unsigned shift = engine->irq_shift; | 2206 | unsigned int shift = 0; |
2207 | |||
2208 | if (INTEL_GEN(engine->i915) < 11) { | ||
2209 | const u8 irq_shifts[] = { | ||
2210 | [RCS] = GEN8_RCS_IRQ_SHIFT, | ||
2211 | [BCS] = GEN8_BCS_IRQ_SHIFT, | ||
2212 | [VCS] = GEN8_VCS1_IRQ_SHIFT, | ||
2213 | [VCS2] = GEN8_VCS2_IRQ_SHIFT, | ||
2214 | [VECS] = GEN8_VECS_IRQ_SHIFT, | ||
2215 | }; | ||
2216 | |||
2217 | shift = irq_shifts[engine->id]; | ||
2218 | } | ||
2219 | |||
2122 | engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; | 2220 | engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; |
2123 | engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; | 2221 | engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; |
2124 | } | 2222 | } |
@@ -2551,3 +2649,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) | |||
2551 | } | 2649 | } |
2552 | } | 2650 | } |
2553 | } | 2651 | } |
2652 | |||
2653 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | ||
2654 | #include "selftests/intel_lrc.c" | ||
2655 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 36671a937fa4..c2f10d899329 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -807,6 +807,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
807 | ret = PTR_ERR(vma); | 807 | ret = PTR_ERR(vma); |
808 | goto out_pin_section; | 808 | goto out_pin_section; |
809 | } | 809 | } |
810 | intel_fb_obj_flush(new_bo, ORIGIN_DIRTYFB); | ||
810 | 811 | ||
811 | ret = i915_vma_put_fence(vma); | 812 | ret = i915_vma_put_fence(vma); |
812 | if (ret) | 813 | if (ret) |
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 1f5cd572a7ff..4f367c16e9e5 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c | |||
@@ -569,7 +569,8 @@ unlock: | |||
569 | static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, | 569 | static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, |
570 | enum pipe pipe, | 570 | enum pipe pipe, |
571 | enum intel_pipe_crc_source *source, | 571 | enum intel_pipe_crc_source *source, |
572 | uint32_t *val) | 572 | uint32_t *val, |
573 | bool set_wa) | ||
573 | { | 574 | { |
574 | if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) | 575 | if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) |
575 | *source = INTEL_PIPE_CRC_SOURCE_PF; | 576 | *source = INTEL_PIPE_CRC_SOURCE_PF; |
@@ -582,7 +583,7 @@ static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, | |||
582 | *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; | 583 | *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; |
583 | break; | 584 | break; |
584 | case INTEL_PIPE_CRC_SOURCE_PF: | 585 | case INTEL_PIPE_CRC_SOURCE_PF: |
585 | if ((IS_HASWELL(dev_priv) || | 586 | if (set_wa && (IS_HASWELL(dev_priv) || |
586 | IS_BROADWELL(dev_priv)) && pipe == PIPE_A) | 587 | IS_BROADWELL(dev_priv)) && pipe == PIPE_A) |
587 | hsw_pipe_A_crc_wa(dev_priv, true); | 588 | hsw_pipe_A_crc_wa(dev_priv, true); |
588 | 589 | ||
@@ -600,7 +601,8 @@ static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, | |||
600 | 601 | ||
601 | static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv, | 602 | static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv, |
602 | enum pipe pipe, | 603 | enum pipe pipe, |
603 | enum intel_pipe_crc_source *source, u32 *val) | 604 | enum intel_pipe_crc_source *source, u32 *val, |
605 | bool set_wa) | ||
604 | { | 606 | { |
605 | if (IS_GEN2(dev_priv)) | 607 | if (IS_GEN2(dev_priv)) |
606 | return i8xx_pipe_crc_ctl_reg(source, val); | 608 | return i8xx_pipe_crc_ctl_reg(source, val); |
@@ -611,7 +613,7 @@ static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv, | |||
611 | else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) | 613 | else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) |
612 | return ilk_pipe_crc_ctl_reg(source, val); | 614 | return ilk_pipe_crc_ctl_reg(source, val); |
613 | else | 615 | else |
614 | return ivb_pipe_crc_ctl_reg(dev_priv, pipe, source, val); | 616 | return ivb_pipe_crc_ctl_reg(dev_priv, pipe, source, val, set_wa); |
615 | } | 617 | } |
616 | 618 | ||
617 | static int pipe_crc_set_source(struct drm_i915_private *dev_priv, | 619 | static int pipe_crc_set_source(struct drm_i915_private *dev_priv, |
@@ -636,7 +638,7 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, | |||
636 | return -EIO; | 638 | return -EIO; |
637 | } | 639 | } |
638 | 640 | ||
639 | ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val); | 641 | ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val, true); |
640 | if (ret != 0) | 642 | if (ret != 0) |
641 | goto out; | 643 | goto out; |
642 | 644 | ||
@@ -916,7 +918,7 @@ int intel_pipe_crc_create(struct drm_minor *minor) | |||
916 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, | 918 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, |
917 | size_t *values_cnt) | 919 | size_t *values_cnt) |
918 | { | 920 | { |
919 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | 921 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); |
920 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; | 922 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; |
921 | enum intel_display_power_domain power_domain; | 923 | enum intel_display_power_domain power_domain; |
922 | enum intel_pipe_crc_source source; | 924 | enum intel_pipe_crc_source source; |
@@ -934,10 +936,11 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, | |||
934 | return -EIO; | 936 | return -EIO; |
935 | } | 937 | } |
936 | 938 | ||
937 | ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val); | 939 | ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val, true); |
938 | if (ret != 0) | 940 | if (ret != 0) |
939 | goto out; | 941 | goto out; |
940 | 942 | ||
943 | pipe_crc->source = source; | ||
941 | I915_WRITE(PIPE_CRC_CTL(crtc->index), val); | 944 | I915_WRITE(PIPE_CRC_CTL(crtc->index), val); |
942 | POSTING_READ(PIPE_CRC_CTL(crtc->index)); | 945 | POSTING_READ(PIPE_CRC_CTL(crtc->index)); |
943 | 946 | ||
@@ -959,3 +962,39 @@ out: | |||
959 | 962 | ||
960 | return ret; | 963 | return ret; |
961 | } | 964 | } |
965 | |||
966 | void intel_crtc_enable_pipe_crc(struct intel_crtc *intel_crtc) | ||
967 | { | ||
968 | struct drm_crtc *crtc = &intel_crtc->base; | ||
969 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | ||
970 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; | ||
971 | u32 val = 0; | ||
972 | |||
973 | if (!crtc->crc.opened) | ||
974 | return; | ||
975 | |||
976 | if (get_new_crc_ctl_reg(dev_priv, crtc->index, &pipe_crc->source, &val, false) < 0) | ||
977 | return; | ||
978 | |||
979 | /* Don't need pipe_crc->lock here, IRQs are not generated. */ | ||
980 | pipe_crc->skipped = 0; | ||
981 | |||
982 | I915_WRITE(PIPE_CRC_CTL(crtc->index), val); | ||
983 | POSTING_READ(PIPE_CRC_CTL(crtc->index)); | ||
984 | } | ||
985 | |||
986 | void intel_crtc_disable_pipe_crc(struct intel_crtc *intel_crtc) | ||
987 | { | ||
988 | struct drm_crtc *crtc = &intel_crtc->base; | ||
989 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | ||
990 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; | ||
991 | |||
992 | /* Swallow crc's until we stop generating them. */ | ||
993 | spin_lock_irq(&pipe_crc->lock); | ||
994 | pipe_crc->skipped = INT_MIN; | ||
995 | spin_unlock_irq(&pipe_crc->lock); | ||
996 | |||
997 | I915_WRITE(PIPE_CRC_CTL(crtc->index), 0); | ||
998 | POSTING_READ(PIPE_CRC_CTL(crtc->index)); | ||
999 | synchronize_irq(dev_priv->drm.irq); | ||
1000 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b8da4dcdd584..4baab858e442 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -3825,6 +3825,44 @@ static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg) | |||
3825 | entry->end += 1; | 3825 | entry->end += 1; |
3826 | } | 3826 | } |
3827 | 3827 | ||
3828 | static void | ||
3829 | skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, | ||
3830 | const enum pipe pipe, | ||
3831 | const enum plane_id plane_id, | ||
3832 | struct skl_ddb_allocation *ddb /* out */) | ||
3833 | { | ||
3834 | u32 val, val2 = 0; | ||
3835 | int fourcc, pixel_format; | ||
3836 | |||
3837 | /* Cursor doesn't support NV12/planar, so no extra calculation needed */ | ||
3838 | if (plane_id == PLANE_CURSOR) { | ||
3839 | val = I915_READ(CUR_BUF_CFG(pipe)); | ||
3840 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val); | ||
3841 | return; | ||
3842 | } | ||
3843 | |||
3844 | val = I915_READ(PLANE_CTL(pipe, plane_id)); | ||
3845 | |||
3846 | /* No DDB allocated for disabled planes */ | ||
3847 | if (!(val & PLANE_CTL_ENABLE)) | ||
3848 | return; | ||
3849 | |||
3850 | pixel_format = val & PLANE_CTL_FORMAT_MASK; | ||
3851 | fourcc = skl_format_to_fourcc(pixel_format, | ||
3852 | val & PLANE_CTL_ORDER_RGBX, | ||
3853 | val & PLANE_CTL_ALPHA_MASK); | ||
3854 | |||
3855 | val = I915_READ(PLANE_BUF_CFG(pipe, plane_id)); | ||
3856 | val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); | ||
3857 | |||
3858 | if (fourcc == DRM_FORMAT_NV12) { | ||
3859 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val2); | ||
3860 | skl_ddb_entry_init_from_hw(&ddb->uv_plane[pipe][plane_id], val); | ||
3861 | } else { | ||
3862 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val); | ||
3863 | } | ||
3864 | } | ||
3865 | |||
3828 | void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | 3866 | void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, |
3829 | struct skl_ddb_allocation *ddb /* out */) | 3867 | struct skl_ddb_allocation *ddb /* out */) |
3830 | { | 3868 | { |
@@ -3841,16 +3879,9 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | |||
3841 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) | 3879 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) |
3842 | continue; | 3880 | continue; |
3843 | 3881 | ||
3844 | for_each_plane_id_on_crtc(crtc, plane_id) { | 3882 | for_each_plane_id_on_crtc(crtc, plane_id) |
3845 | u32 val; | 3883 | skl_ddb_get_hw_plane_state(dev_priv, pipe, |
3846 | 3884 | plane_id, ddb); | |
3847 | if (plane_id != PLANE_CURSOR) | ||
3848 | val = I915_READ(PLANE_BUF_CFG(pipe, plane_id)); | ||
3849 | else | ||
3850 | val = I915_READ(CUR_BUF_CFG(pipe)); | ||
3851 | |||
3852 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val); | ||
3853 | } | ||
3854 | 3885 | ||
3855 | intel_display_power_put(dev_priv, power_domain); | 3886 | intel_display_power_put(dev_priv, power_domain); |
3856 | } | 3887 | } |
@@ -4009,9 +4040,9 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, | |||
4009 | static unsigned int | 4040 | static unsigned int |
4010 | skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | 4041 | skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, |
4011 | const struct drm_plane_state *pstate, | 4042 | const struct drm_plane_state *pstate, |
4012 | int y) | 4043 | const int plane) |
4013 | { | 4044 | { |
4014 | struct intel_plane *plane = to_intel_plane(pstate->plane); | 4045 | struct intel_plane *intel_plane = to_intel_plane(pstate->plane); |
4015 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); | 4046 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); |
4016 | uint32_t data_rate; | 4047 | uint32_t data_rate; |
4017 | uint32_t width = 0, height = 0; | 4048 | uint32_t width = 0, height = 0; |
@@ -4025,9 +4056,9 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
4025 | fb = pstate->fb; | 4056 | fb = pstate->fb; |
4026 | format = fb->format->format; | 4057 | format = fb->format->format; |
4027 | 4058 | ||
4028 | if (plane->id == PLANE_CURSOR) | 4059 | if (intel_plane->id == PLANE_CURSOR) |
4029 | return 0; | 4060 | return 0; |
4030 | if (y && format != DRM_FORMAT_NV12) | 4061 | if (plane == 1 && format != DRM_FORMAT_NV12) |
4031 | return 0; | 4062 | return 0; |
4032 | 4063 | ||
4033 | /* | 4064 | /* |
@@ -4038,19 +4069,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
4038 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | 4069 | width = drm_rect_width(&intel_pstate->base.src) >> 16; |
4039 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | 4070 | height = drm_rect_height(&intel_pstate->base.src) >> 16; |
4040 | 4071 | ||
4041 | /* for planar format */ | 4072 | /* UV plane does 1/2 pixel sub-sampling */ |
4042 | if (format == DRM_FORMAT_NV12) { | 4073 | if (plane == 1 && format == DRM_FORMAT_NV12) { |
4043 | if (y) /* y-plane data rate */ | 4074 | width /= 2; |
4044 | data_rate = width * height * | 4075 | height /= 2; |
4045 | fb->format->cpp[0]; | ||
4046 | else /* uv-plane data rate */ | ||
4047 | data_rate = (width / 2) * (height / 2) * | ||
4048 | fb->format->cpp[1]; | ||
4049 | } else { | ||
4050 | /* for packed formats */ | ||
4051 | data_rate = width * height * fb->format->cpp[0]; | ||
4052 | } | 4076 | } |
4053 | 4077 | ||
4078 | data_rate = width * height * fb->format->cpp[plane]; | ||
4079 | |||
4054 | down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate); | 4080 | down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate); |
4055 | 4081 | ||
4056 | return mul_round_up_u32_fixed16(data_rate, down_scale_amount); | 4082 | return mul_round_up_u32_fixed16(data_rate, down_scale_amount); |
@@ -4063,8 +4089,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
4063 | */ | 4089 | */ |
4064 | static unsigned int | 4090 | static unsigned int |
4065 | skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, | 4091 | skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, |
4066 | unsigned *plane_data_rate, | 4092 | unsigned int *plane_data_rate, |
4067 | unsigned *plane_y_data_rate) | 4093 | unsigned int *uv_plane_data_rate) |
4068 | { | 4094 | { |
4069 | struct drm_crtc_state *cstate = &intel_cstate->base; | 4095 | struct drm_crtc_state *cstate = &intel_cstate->base; |
4070 | struct drm_atomic_state *state = cstate->state; | 4096 | struct drm_atomic_state *state = cstate->state; |
@@ -4080,17 +4106,17 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, | |||
4080 | enum plane_id plane_id = to_intel_plane(plane)->id; | 4106 | enum plane_id plane_id = to_intel_plane(plane)->id; |
4081 | unsigned int rate; | 4107 | unsigned int rate; |
4082 | 4108 | ||
4083 | /* packed/uv */ | 4109 | /* packed/y */ |
4084 | rate = skl_plane_relative_data_rate(intel_cstate, | 4110 | rate = skl_plane_relative_data_rate(intel_cstate, |
4085 | pstate, 0); | 4111 | pstate, 0); |
4086 | plane_data_rate[plane_id] = rate; | 4112 | plane_data_rate[plane_id] = rate; |
4087 | 4113 | ||
4088 | total_data_rate += rate; | 4114 | total_data_rate += rate; |
4089 | 4115 | ||
4090 | /* y-plane */ | 4116 | /* uv-plane */ |
4091 | rate = skl_plane_relative_data_rate(intel_cstate, | 4117 | rate = skl_plane_relative_data_rate(intel_cstate, |
4092 | pstate, 1); | 4118 | pstate, 1); |
4093 | plane_y_data_rate[plane_id] = rate; | 4119 | uv_plane_data_rate[plane_id] = rate; |
4094 | 4120 | ||
4095 | total_data_rate += rate; | 4121 | total_data_rate += rate; |
4096 | } | 4122 | } |
@@ -4099,8 +4125,7 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, | |||
4099 | } | 4125 | } |
4100 | 4126 | ||
4101 | static uint16_t | 4127 | static uint16_t |
4102 | skl_ddb_min_alloc(const struct drm_plane_state *pstate, | 4128 | skl_ddb_min_alloc(const struct drm_plane_state *pstate, const int plane) |
4103 | const int y) | ||
4104 | { | 4129 | { |
4105 | struct drm_framebuffer *fb = pstate->fb; | 4130 | struct drm_framebuffer *fb = pstate->fb; |
4106 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); | 4131 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); |
@@ -4111,8 +4136,8 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |||
4111 | if (WARN_ON(!fb)) | 4136 | if (WARN_ON(!fb)) |
4112 | return 0; | 4137 | return 0; |
4113 | 4138 | ||
4114 | /* For packed formats, no y-plane, return 0 */ | 4139 | /* For packed formats, and uv-plane, return 0 */ |
4115 | if (y && fb->format->format != DRM_FORMAT_NV12) | 4140 | if (plane == 1 && fb->format->format != DRM_FORMAT_NV12) |
4116 | return 0; | 4141 | return 0; |
4117 | 4142 | ||
4118 | /* For Non Y-tile return 8-blocks */ | 4143 | /* For Non Y-tile return 8-blocks */ |
@@ -4131,15 +4156,12 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |||
4131 | src_h = drm_rect_height(&intel_pstate->base.src) >> 16; | 4156 | src_h = drm_rect_height(&intel_pstate->base.src) >> 16; |
4132 | 4157 | ||
4133 | /* Halve UV plane width and height for NV12 */ | 4158 | /* Halve UV plane width and height for NV12 */ |
4134 | if (fb->format->format == DRM_FORMAT_NV12 && !y) { | 4159 | if (plane == 1) { |
4135 | src_w /= 2; | 4160 | src_w /= 2; |
4136 | src_h /= 2; | 4161 | src_h /= 2; |
4137 | } | 4162 | } |
4138 | 4163 | ||
4139 | if (fb->format->format == DRM_FORMAT_NV12 && !y) | 4164 | plane_bpp = fb->format->cpp[plane]; |
4140 | plane_bpp = fb->format->cpp[1]; | ||
4141 | else | ||
4142 | plane_bpp = fb->format->cpp[0]; | ||
4143 | 4165 | ||
4144 | if (drm_rotation_90_or_270(pstate->rotation)) { | 4166 | if (drm_rotation_90_or_270(pstate->rotation)) { |
4145 | switch (plane_bpp) { | 4167 | switch (plane_bpp) { |
@@ -4167,7 +4189,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |||
4167 | 4189 | ||
4168 | static void | 4190 | static void |
4169 | skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, | 4191 | skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, |
4170 | uint16_t *minimum, uint16_t *y_minimum) | 4192 | uint16_t *minimum, uint16_t *uv_minimum) |
4171 | { | 4193 | { |
4172 | const struct drm_plane_state *pstate; | 4194 | const struct drm_plane_state *pstate; |
4173 | struct drm_plane *plane; | 4195 | struct drm_plane *plane; |
@@ -4182,7 +4204,7 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, | |||
4182 | continue; | 4204 | continue; |
4183 | 4205 | ||
4184 | minimum[plane_id] = skl_ddb_min_alloc(pstate, 0); | 4206 | minimum[plane_id] = skl_ddb_min_alloc(pstate, 0); |
4185 | y_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1); | 4207 | uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1); |
4186 | } | 4208 | } |
4187 | 4209 | ||
4188 | minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); | 4210 | minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); |
@@ -4200,17 +4222,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4200 | struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; | 4222 | struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; |
4201 | uint16_t alloc_size, start; | 4223 | uint16_t alloc_size, start; |
4202 | uint16_t minimum[I915_MAX_PLANES] = {}; | 4224 | uint16_t minimum[I915_MAX_PLANES] = {}; |
4203 | uint16_t y_minimum[I915_MAX_PLANES] = {}; | 4225 | uint16_t uv_minimum[I915_MAX_PLANES] = {}; |
4204 | unsigned int total_data_rate; | 4226 | unsigned int total_data_rate; |
4205 | enum plane_id plane_id; | 4227 | enum plane_id plane_id; |
4206 | int num_active; | 4228 | int num_active; |
4207 | unsigned plane_data_rate[I915_MAX_PLANES] = {}; | 4229 | unsigned int plane_data_rate[I915_MAX_PLANES] = {}; |
4208 | unsigned plane_y_data_rate[I915_MAX_PLANES] = {}; | 4230 | unsigned int uv_plane_data_rate[I915_MAX_PLANES] = {}; |
4209 | uint16_t total_min_blocks = 0; | 4231 | uint16_t total_min_blocks = 0; |
4210 | 4232 | ||
4211 | /* Clear the partitioning for disabled planes. */ | 4233 | /* Clear the partitioning for disabled planes. */ |
4212 | memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); | 4234 | memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); |
4213 | memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); | 4235 | memset(ddb->uv_plane[pipe], 0, sizeof(ddb->uv_plane[pipe])); |
4214 | 4236 | ||
4215 | if (WARN_ON(!state)) | 4237 | if (WARN_ON(!state)) |
4216 | return 0; | 4238 | return 0; |
@@ -4225,7 +4247,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4225 | if (alloc_size == 0) | 4247 | if (alloc_size == 0) |
4226 | return 0; | 4248 | return 0; |
4227 | 4249 | ||
4228 | skl_ddb_calc_min(cstate, num_active, minimum, y_minimum); | 4250 | skl_ddb_calc_min(cstate, num_active, minimum, uv_minimum); |
4229 | 4251 | ||
4230 | /* | 4252 | /* |
4231 | * 1. Allocate the mininum required blocks for each active plane | 4253 | * 1. Allocate the mininum required blocks for each active plane |
@@ -4235,7 +4257,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4235 | 4257 | ||
4236 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { | 4258 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { |
4237 | total_min_blocks += minimum[plane_id]; | 4259 | total_min_blocks += minimum[plane_id]; |
4238 | total_min_blocks += y_minimum[plane_id]; | 4260 | total_min_blocks += uv_minimum[plane_id]; |
4239 | } | 4261 | } |
4240 | 4262 | ||
4241 | if (total_min_blocks > alloc_size) { | 4263 | if (total_min_blocks > alloc_size) { |
@@ -4257,14 +4279,14 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4257 | */ | 4279 | */ |
4258 | total_data_rate = skl_get_total_relative_data_rate(cstate, | 4280 | total_data_rate = skl_get_total_relative_data_rate(cstate, |
4259 | plane_data_rate, | 4281 | plane_data_rate, |
4260 | plane_y_data_rate); | 4282 | uv_plane_data_rate); |
4261 | if (total_data_rate == 0) | 4283 | if (total_data_rate == 0) |
4262 | return 0; | 4284 | return 0; |
4263 | 4285 | ||
4264 | start = alloc->start; | 4286 | start = alloc->start; |
4265 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { | 4287 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { |
4266 | unsigned int data_rate, y_data_rate; | 4288 | unsigned int data_rate, uv_data_rate; |
4267 | uint16_t plane_blocks, y_plane_blocks = 0; | 4289 | uint16_t plane_blocks, uv_plane_blocks; |
4268 | 4290 | ||
4269 | if (plane_id == PLANE_CURSOR) | 4291 | if (plane_id == PLANE_CURSOR) |
4270 | continue; | 4292 | continue; |
@@ -4288,21 +4310,20 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4288 | 4310 | ||
4289 | start += plane_blocks; | 4311 | start += plane_blocks; |
4290 | 4312 | ||
4291 | /* | 4313 | /* Allocate DDB for UV plane for planar format/NV12 */ |
4292 | * allocation for y_plane part of planar format: | 4314 | uv_data_rate = uv_plane_data_rate[plane_id]; |
4293 | */ | ||
4294 | y_data_rate = plane_y_data_rate[plane_id]; | ||
4295 | 4315 | ||
4296 | y_plane_blocks = y_minimum[plane_id]; | 4316 | uv_plane_blocks = uv_minimum[plane_id]; |
4297 | y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, | 4317 | uv_plane_blocks += div_u64((uint64_t)alloc_size * uv_data_rate, |
4298 | total_data_rate); | 4318 | total_data_rate); |
4299 | 4319 | ||
4300 | if (y_data_rate) { | 4320 | if (uv_data_rate) { |
4301 | ddb->y_plane[pipe][plane_id].start = start; | 4321 | ddb->uv_plane[pipe][plane_id].start = start; |
4302 | ddb->y_plane[pipe][plane_id].end = start + y_plane_blocks; | 4322 | ddb->uv_plane[pipe][plane_id].end = |
4323 | start + uv_plane_blocks; | ||
4303 | } | 4324 | } |
4304 | 4325 | ||
4305 | start += y_plane_blocks; | 4326 | start += uv_plane_blocks; |
4306 | } | 4327 | } |
4307 | 4328 | ||
4308 | return 0; | 4329 | return 0; |
@@ -4398,7 +4419,7 @@ static int | |||
4398 | skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, | 4419 | skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, |
4399 | struct intel_crtc_state *cstate, | 4420 | struct intel_crtc_state *cstate, |
4400 | const struct intel_plane_state *intel_pstate, | 4421 | const struct intel_plane_state *intel_pstate, |
4401 | struct skl_wm_params *wp) | 4422 | struct skl_wm_params *wp, int plane_id) |
4402 | { | 4423 | { |
4403 | struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); | 4424 | struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); |
4404 | const struct drm_plane_state *pstate = &intel_pstate->base; | 4425 | const struct drm_plane_state *pstate = &intel_pstate->base; |
@@ -4411,6 +4432,12 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, | |||
4411 | if (!intel_wm_plane_visible(cstate, intel_pstate)) | 4432 | if (!intel_wm_plane_visible(cstate, intel_pstate)) |
4412 | return 0; | 4433 | return 0; |
4413 | 4434 | ||
4435 | /* only NV12 format has two planes */ | ||
4436 | if (plane_id == 1 && fb->format->format != DRM_FORMAT_NV12) { | ||
4437 | DRM_DEBUG_KMS("Non NV12 format have single plane\n"); | ||
4438 | return -EINVAL; | ||
4439 | } | ||
4440 | |||
4414 | wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || | 4441 | wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || |
4415 | fb->modifier == I915_FORMAT_MOD_Yf_TILED || | 4442 | fb->modifier == I915_FORMAT_MOD_Yf_TILED || |
4416 | fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || | 4443 | fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || |
@@ -4418,6 +4445,7 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, | |||
4418 | wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; | 4445 | wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; |
4419 | wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || | 4446 | wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || |
4420 | fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; | 4447 | fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; |
4448 | wp->is_planar = fb->format->format == DRM_FORMAT_NV12; | ||
4421 | 4449 | ||
4422 | if (plane->id == PLANE_CURSOR) { | 4450 | if (plane->id == PLANE_CURSOR) { |
4423 | wp->width = intel_pstate->base.crtc_w; | 4451 | wp->width = intel_pstate->base.crtc_w; |
@@ -4430,8 +4458,10 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, | |||
4430 | wp->width = drm_rect_width(&intel_pstate->base.src) >> 16; | 4458 | wp->width = drm_rect_width(&intel_pstate->base.src) >> 16; |
4431 | } | 4459 | } |
4432 | 4460 | ||
4433 | wp->cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : | 4461 | if (plane_id == 1 && wp->is_planar) |
4434 | fb->format->cpp[0]; | 4462 | wp->width /= 2; |
4463 | |||
4464 | wp->cpp = fb->format->cpp[plane_id]; | ||
4435 | wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, | 4465 | wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, |
4436 | intel_pstate); | 4466 | intel_pstate); |
4437 | 4467 | ||
@@ -4499,9 +4529,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
4499 | uint16_t ddb_allocation, | 4529 | uint16_t ddb_allocation, |
4500 | int level, | 4530 | int level, |
4501 | const struct skl_wm_params *wp, | 4531 | const struct skl_wm_params *wp, |
4502 | uint16_t *out_blocks, /* out */ | 4532 | const struct skl_wm_level *result_prev, |
4503 | uint8_t *out_lines, /* out */ | 4533 | struct skl_wm_level *result /* out */) |
4504 | bool *enabled /* out */) | ||
4505 | { | 4534 | { |
4506 | const struct drm_plane_state *pstate = &intel_pstate->base; | 4535 | const struct drm_plane_state *pstate = &intel_pstate->base; |
4507 | uint32_t latency = dev_priv->wm.skl_latency[level]; | 4536 | uint32_t latency = dev_priv->wm.skl_latency[level]; |
@@ -4515,7 +4544,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
4515 | 4544 | ||
4516 | if (latency == 0 || | 4545 | if (latency == 0 || |
4517 | !intel_wm_plane_visible(cstate, intel_pstate)) { | 4546 | !intel_wm_plane_visible(cstate, intel_pstate)) { |
4518 | *enabled = false; | 4547 | result->plane_en = false; |
4519 | return 0; | 4548 | return 0; |
4520 | } | 4549 | } |
4521 | 4550 | ||
@@ -4568,6 +4597,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
4568 | } else { | 4597 | } else { |
4569 | res_blocks++; | 4598 | res_blocks++; |
4570 | } | 4599 | } |
4600 | |||
4601 | /* | ||
4602 | * Make sure result blocks for higher latency levels are atleast | ||
4603 | * as high as level below the current level. | ||
4604 | * Assumption in DDB algorithm optimization for special cases. | ||
4605 | * Also covers Display WA #1125 for RC. | ||
4606 | */ | ||
4607 | if (result_prev->plane_res_b > res_blocks) | ||
4608 | res_blocks = result_prev->plane_res_b; | ||
4571 | } | 4609 | } |
4572 | 4610 | ||
4573 | if (INTEL_GEN(dev_priv) >= 11) { | 4611 | if (INTEL_GEN(dev_priv) >= 11) { |
@@ -4596,7 +4634,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
4596 | if ((level > 0 && res_lines > 31) || | 4634 | if ((level > 0 && res_lines > 31) || |
4597 | res_blocks >= ddb_allocation || | 4635 | res_blocks >= ddb_allocation || |
4598 | min_disp_buf_needed >= ddb_allocation) { | 4636 | min_disp_buf_needed >= ddb_allocation) { |
4599 | *enabled = false; | 4637 | result->plane_en = false; |
4600 | 4638 | ||
4601 | /* | 4639 | /* |
4602 | * If there are no valid level 0 watermarks, then we can't | 4640 | * If there are no valid level 0 watermarks, then we can't |
@@ -4615,10 +4653,21 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
4615 | } | 4653 | } |
4616 | } | 4654 | } |
4617 | 4655 | ||
4656 | /* | ||
4657 | * Display WA #826 (SKL:ALL, BXT:ALL) & #1059 (CNL:A) | ||
4658 | * disable wm level 1-7 on NV12 planes | ||
4659 | */ | ||
4660 | if (wp->is_planar && level >= 1 && | ||
4661 | (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || | ||
4662 | IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0))) { | ||
4663 | result->plane_en = false; | ||
4664 | return 0; | ||
4665 | } | ||
4666 | |||
4618 | /* The number of lines are ignored for the level 0 watermark. */ | 4667 | /* The number of lines are ignored for the level 0 watermark. */ |
4619 | *out_lines = level ? res_lines : 0; | 4668 | result->plane_res_b = res_blocks; |
4620 | *out_blocks = res_blocks; | 4669 | result->plane_res_l = res_lines; |
4621 | *enabled = true; | 4670 | result->plane_en = true; |
4622 | 4671 | ||
4623 | return 0; | 4672 | return 0; |
4624 | } | 4673 | } |
@@ -4629,7 +4678,8 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, | |||
4629 | struct intel_crtc_state *cstate, | 4678 | struct intel_crtc_state *cstate, |
4630 | const struct intel_plane_state *intel_pstate, | 4679 | const struct intel_plane_state *intel_pstate, |
4631 | const struct skl_wm_params *wm_params, | 4680 | const struct skl_wm_params *wm_params, |
4632 | struct skl_plane_wm *wm) | 4681 | struct skl_plane_wm *wm, |
4682 | int plane_id) | ||
4633 | { | 4683 | { |
4634 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); | 4684 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); |
4635 | struct drm_plane *plane = intel_pstate->base.plane; | 4685 | struct drm_plane *plane = intel_pstate->base.plane; |
@@ -4637,15 +4687,26 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, | |||
4637 | uint16_t ddb_blocks; | 4687 | uint16_t ddb_blocks; |
4638 | enum pipe pipe = intel_crtc->pipe; | 4688 | enum pipe pipe = intel_crtc->pipe; |
4639 | int level, max_level = ilk_wm_max_level(dev_priv); | 4689 | int level, max_level = ilk_wm_max_level(dev_priv); |
4690 | enum plane_id intel_plane_id = intel_plane->id; | ||
4640 | int ret; | 4691 | int ret; |
4641 | 4692 | ||
4642 | if (WARN_ON(!intel_pstate->base.fb)) | 4693 | if (WARN_ON(!intel_pstate->base.fb)) |
4643 | return -EINVAL; | 4694 | return -EINVAL; |
4644 | 4695 | ||
4645 | ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][intel_plane->id]); | 4696 | ddb_blocks = plane_id ? |
4697 | skl_ddb_entry_size(&ddb->uv_plane[pipe][intel_plane_id]) : | ||
4698 | skl_ddb_entry_size(&ddb->plane[pipe][intel_plane_id]); | ||
4646 | 4699 | ||
4647 | for (level = 0; level <= max_level; level++) { | 4700 | for (level = 0; level <= max_level; level++) { |
4648 | struct skl_wm_level *result = &wm->wm[level]; | 4701 | struct skl_wm_level *result = plane_id ? &wm->uv_wm[level] : |
4702 | &wm->wm[level]; | ||
4703 | struct skl_wm_level *result_prev; | ||
4704 | |||
4705 | if (level) | ||
4706 | result_prev = plane_id ? &wm->uv_wm[level - 1] : | ||
4707 | &wm->wm[level - 1]; | ||
4708 | else | ||
4709 | result_prev = plane_id ? &wm->uv_wm[0] : &wm->wm[0]; | ||
4649 | 4710 | ||
4650 | ret = skl_compute_plane_wm(dev_priv, | 4711 | ret = skl_compute_plane_wm(dev_priv, |
4651 | cstate, | 4712 | cstate, |
@@ -4653,13 +4714,15 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, | |||
4653 | ddb_blocks, | 4714 | ddb_blocks, |
4654 | level, | 4715 | level, |
4655 | wm_params, | 4716 | wm_params, |
4656 | &result->plane_res_b, | 4717 | result_prev, |
4657 | &result->plane_res_l, | 4718 | result); |
4658 | &result->plane_en); | ||
4659 | if (ret) | 4719 | if (ret) |
4660 | return ret; | 4720 | return ret; |
4661 | } | 4721 | } |
4662 | 4722 | ||
4723 | if (intel_pstate->base.fb->format->format == DRM_FORMAT_NV12) | ||
4724 | wm->is_planar = true; | ||
4725 | |||
4663 | return 0; | 4726 | return 0; |
4664 | } | 4727 | } |
4665 | 4728 | ||
@@ -4769,20 +4832,39 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, | |||
4769 | 4832 | ||
4770 | wm = &pipe_wm->planes[plane_id]; | 4833 | wm = &pipe_wm->planes[plane_id]; |
4771 | ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); | 4834 | ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); |
4772 | memset(&wm_params, 0, sizeof(struct skl_wm_params)); | ||
4773 | 4835 | ||
4774 | ret = skl_compute_plane_wm_params(dev_priv, cstate, | 4836 | ret = skl_compute_plane_wm_params(dev_priv, cstate, |
4775 | intel_pstate, &wm_params); | 4837 | intel_pstate, &wm_params, 0); |
4776 | if (ret) | 4838 | if (ret) |
4777 | return ret; | 4839 | return ret; |
4778 | 4840 | ||
4779 | ret = skl_compute_wm_levels(dev_priv, ddb, cstate, | 4841 | ret = skl_compute_wm_levels(dev_priv, ddb, cstate, |
4780 | intel_pstate, &wm_params, wm); | 4842 | intel_pstate, &wm_params, wm, 0); |
4781 | if (ret) | 4843 | if (ret) |
4782 | return ret; | 4844 | return ret; |
4845 | |||
4783 | skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], | 4846 | skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], |
4784 | ddb_blocks, &wm->trans_wm); | 4847 | ddb_blocks, &wm->trans_wm); |
4848 | |||
4849 | /* uv plane watermarks must also be validated for NV12/Planar */ | ||
4850 | if (wm_params.is_planar) { | ||
4851 | memset(&wm_params, 0, sizeof(struct skl_wm_params)); | ||
4852 | wm->is_planar = true; | ||
4853 | |||
4854 | ret = skl_compute_plane_wm_params(dev_priv, cstate, | ||
4855 | intel_pstate, | ||
4856 | &wm_params, 1); | ||
4857 | if (ret) | ||
4858 | return ret; | ||
4859 | |||
4860 | ret = skl_compute_wm_levels(dev_priv, ddb, cstate, | ||
4861 | intel_pstate, &wm_params, | ||
4862 | wm, 1); | ||
4863 | if (ret) | ||
4864 | return ret; | ||
4865 | } | ||
4785 | } | 4866 | } |
4867 | |||
4786 | pipe_wm->linetime = skl_compute_linetime_wm(cstate); | 4868 | pipe_wm->linetime = skl_compute_linetime_wm(cstate); |
4787 | 4869 | ||
4788 | return 0; | 4870 | return 0; |
@@ -4833,10 +4915,21 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, | |||
4833 | 4915 | ||
4834 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), | 4916 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), |
4835 | &ddb->plane[pipe][plane_id]); | 4917 | &ddb->plane[pipe][plane_id]); |
4836 | if (INTEL_GEN(dev_priv) < 11) | 4918 | if (INTEL_GEN(dev_priv) >= 11) |
4919 | return skl_ddb_entry_write(dev_priv, | ||
4920 | PLANE_BUF_CFG(pipe, plane_id), | ||
4921 | &ddb->plane[pipe][plane_id]); | ||
4922 | if (wm->is_planar) { | ||
4923 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), | ||
4924 | &ddb->uv_plane[pipe][plane_id]); | ||
4837 | skl_ddb_entry_write(dev_priv, | 4925 | skl_ddb_entry_write(dev_priv, |
4838 | PLANE_NV12_BUF_CFG(pipe, plane_id), | 4926 | PLANE_NV12_BUF_CFG(pipe, plane_id), |
4839 | &ddb->y_plane[pipe][plane_id]); | 4927 | &ddb->plane[pipe][plane_id]); |
4928 | } else { | ||
4929 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), | ||
4930 | &ddb->plane[pipe][plane_id]); | ||
4931 | I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0); | ||
4932 | } | ||
4840 | } | 4933 | } |
4841 | 4934 | ||
4842 | static void skl_write_cursor_wm(struct intel_crtc *intel_crtc, | 4935 | static void skl_write_cursor_wm(struct intel_crtc *intel_crtc, |
@@ -4944,15 +5037,13 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) | |||
4944 | struct drm_plane *plane; | 5037 | struct drm_plane *plane; |
4945 | enum pipe pipe = intel_crtc->pipe; | 5038 | enum pipe pipe = intel_crtc->pipe; |
4946 | 5039 | ||
4947 | WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); | ||
4948 | |||
4949 | drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { | 5040 | drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { |
4950 | enum plane_id plane_id = to_intel_plane(plane)->id; | 5041 | enum plane_id plane_id = to_intel_plane(plane)->id; |
4951 | 5042 | ||
4952 | if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id], | 5043 | if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id], |
4953 | &new_ddb->plane[pipe][plane_id]) && | 5044 | &new_ddb->plane[pipe][plane_id]) && |
4954 | skl_ddb_entry_equal(&cur_ddb->y_plane[pipe][plane_id], | 5045 | skl_ddb_entry_equal(&cur_ddb->uv_plane[pipe][plane_id], |
4955 | &new_ddb->y_plane[pipe][plane_id])) | 5046 | &new_ddb->uv_plane[pipe][plane_id])) |
4956 | continue; | 5047 | continue; |
4957 | 5048 | ||
4958 | plane_state = drm_atomic_get_plane_state(state, plane); | 5049 | plane_state = drm_atomic_get_plane_state(state, plane); |
@@ -4966,69 +5057,16 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) | |||
4966 | static int | 5057 | static int |
4967 | skl_compute_ddb(struct drm_atomic_state *state) | 5058 | skl_compute_ddb(struct drm_atomic_state *state) |
4968 | { | 5059 | { |
4969 | struct drm_device *dev = state->dev; | 5060 | const struct drm_i915_private *dev_priv = to_i915(state->dev); |
4970 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
4971 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | 5061 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); |
4972 | struct intel_crtc *intel_crtc; | ||
4973 | struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb; | 5062 | struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb; |
4974 | uint32_t realloc_pipes = pipes_modified(state); | 5063 | struct intel_crtc *crtc; |
4975 | int ret; | 5064 | struct intel_crtc_state *cstate; |
4976 | 5065 | int ret, i; | |
4977 | /* | ||
4978 | * If this is our first atomic update following hardware readout, | ||
4979 | * we can't trust the DDB that the BIOS programmed for us. Let's | ||
4980 | * pretend that all pipes switched active status so that we'll | ||
4981 | * ensure a full DDB recompute. | ||
4982 | */ | ||
4983 | if (dev_priv->wm.distrust_bios_wm) { | ||
4984 | ret = drm_modeset_lock(&dev->mode_config.connection_mutex, | ||
4985 | state->acquire_ctx); | ||
4986 | if (ret) | ||
4987 | return ret; | ||
4988 | |||
4989 | intel_state->active_pipe_changes = ~0; | ||
4990 | |||
4991 | /* | ||
4992 | * We usually only initialize intel_state->active_crtcs if we | ||
4993 | * we're doing a modeset; make sure this field is always | ||
4994 | * initialized during the sanitization process that happens | ||
4995 | * on the first commit too. | ||
4996 | */ | ||
4997 | if (!intel_state->modeset) | ||
4998 | intel_state->active_crtcs = dev_priv->active_crtcs; | ||
4999 | } | ||
5000 | |||
5001 | /* | ||
5002 | * If the modeset changes which CRTC's are active, we need to | ||
5003 | * recompute the DDB allocation for *all* active pipes, even | ||
5004 | * those that weren't otherwise being modified in any way by this | ||
5005 | * atomic commit. Due to the shrinking of the per-pipe allocations | ||
5006 | * when new active CRTC's are added, it's possible for a pipe that | ||
5007 | * we were already using and aren't changing at all here to suddenly | ||
5008 | * become invalid if its DDB needs exceeds its new allocation. | ||
5009 | * | ||
5010 | * Note that if we wind up doing a full DDB recompute, we can't let | ||
5011 | * any other display updates race with this transaction, so we need | ||
5012 | * to grab the lock on *all* CRTC's. | ||
5013 | */ | ||
5014 | if (intel_state->active_pipe_changes) { | ||
5015 | realloc_pipes = ~0; | ||
5016 | intel_state->wm_results.dirty_pipes = ~0; | ||
5017 | } | ||
5018 | 5066 | ||
5019 | /* | ||
5020 | * We're not recomputing for the pipes not included in the commit, so | ||
5021 | * make sure we start with the current state. | ||
5022 | */ | ||
5023 | memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); | 5067 | memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); |
5024 | 5068 | ||
5025 | for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { | 5069 | for_each_new_intel_crtc_in_state(intel_state, crtc, cstate, i) { |
5026 | struct intel_crtc_state *cstate; | ||
5027 | |||
5028 | cstate = intel_atomic_get_crtc_state(state, intel_crtc); | ||
5029 | if (IS_ERR(cstate)) | ||
5030 | return PTR_ERR(cstate); | ||
5031 | |||
5032 | ret = skl_allocate_pipe_ddb(cstate, ddb); | 5070 | ret = skl_allocate_pipe_ddb(cstate, ddb); |
5033 | if (ret) | 5071 | if (ret) |
5034 | return ret; | 5072 | return ret; |
@@ -5042,12 +5080,12 @@ skl_compute_ddb(struct drm_atomic_state *state) | |||
5042 | } | 5080 | } |
5043 | 5081 | ||
5044 | static void | 5082 | static void |
5045 | skl_copy_wm_for_pipe(struct skl_wm_values *dst, | 5083 | skl_copy_ddb_for_pipe(struct skl_ddb_values *dst, |
5046 | struct skl_wm_values *src, | 5084 | struct skl_ddb_values *src, |
5047 | enum pipe pipe) | 5085 | enum pipe pipe) |
5048 | { | 5086 | { |
5049 | memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], | 5087 | memcpy(dst->ddb.uv_plane[pipe], src->ddb.uv_plane[pipe], |
5050 | sizeof(dst->ddb.y_plane[pipe])); | 5088 | sizeof(dst->ddb.uv_plane[pipe])); |
5051 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], | 5089 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], |
5052 | sizeof(dst->ddb.plane[pipe])); | 5090 | sizeof(dst->ddb.plane[pipe])); |
5053 | } | 5091 | } |
@@ -5090,23 +5128,23 @@ skl_print_wm_changes(const struct drm_atomic_state *state) | |||
5090 | } | 5128 | } |
5091 | 5129 | ||
5092 | static int | 5130 | static int |
5093 | skl_compute_wm(struct drm_atomic_state *state) | 5131 | skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed) |
5094 | { | 5132 | { |
5095 | struct drm_crtc *crtc; | ||
5096 | struct drm_crtc_state *cstate; | ||
5097 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | ||
5098 | struct skl_wm_values *results = &intel_state->wm_results; | ||
5099 | struct drm_device *dev = state->dev; | 5133 | struct drm_device *dev = state->dev; |
5100 | struct skl_pipe_wm *pipe_wm; | 5134 | const struct drm_i915_private *dev_priv = to_i915(dev); |
5101 | bool changed = false; | 5135 | const struct drm_crtc *crtc; |
5136 | const struct drm_crtc_state *cstate; | ||
5137 | struct intel_crtc *intel_crtc; | ||
5138 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | ||
5139 | uint32_t realloc_pipes = pipes_modified(state); | ||
5102 | int ret, i; | 5140 | int ret, i; |
5103 | 5141 | ||
5104 | /* | 5142 | /* |
5105 | * When we distrust bios wm we always need to recompute to set the | 5143 | * When we distrust bios wm we always need to recompute to set the |
5106 | * expected DDB allocations for each CRTC. | 5144 | * expected DDB allocations for each CRTC. |
5107 | */ | 5145 | */ |
5108 | if (to_i915(dev)->wm.distrust_bios_wm) | 5146 | if (dev_priv->wm.distrust_bios_wm) |
5109 | changed = true; | 5147 | (*changed) = true; |
5110 | 5148 | ||
5111 | /* | 5149 | /* |
5112 | * If this transaction isn't actually touching any CRTC's, don't | 5150 | * If this transaction isn't actually touching any CRTC's, don't |
@@ -5117,14 +5155,86 @@ skl_compute_wm(struct drm_atomic_state *state) | |||
5117 | * hold _all_ CRTC state mutexes. | 5155 | * hold _all_ CRTC state mutexes. |
5118 | */ | 5156 | */ |
5119 | for_each_new_crtc_in_state(state, crtc, cstate, i) | 5157 | for_each_new_crtc_in_state(state, crtc, cstate, i) |
5120 | changed = true; | 5158 | (*changed) = true; |
5121 | 5159 | ||
5122 | if (!changed) | 5160 | if (!*changed) |
5123 | return 0; | 5161 | return 0; |
5124 | 5162 | ||
5163 | /* | ||
5164 | * If this is our first atomic update following hardware readout, | ||
5165 | * we can't trust the DDB that the BIOS programmed for us. Let's | ||
5166 | * pretend that all pipes switched active status so that we'll | ||
5167 | * ensure a full DDB recompute. | ||
5168 | */ | ||
5169 | if (dev_priv->wm.distrust_bios_wm) { | ||
5170 | ret = drm_modeset_lock(&dev->mode_config.connection_mutex, | ||
5171 | state->acquire_ctx); | ||
5172 | if (ret) | ||
5173 | return ret; | ||
5174 | |||
5175 | intel_state->active_pipe_changes = ~0; | ||
5176 | |||
5177 | /* | ||
5178 | * We usually only initialize intel_state->active_crtcs if we | ||
5179 | * we're doing a modeset; make sure this field is always | ||
5180 | * initialized during the sanitization process that happens | ||
5181 | * on the first commit too. | ||
5182 | */ | ||
5183 | if (!intel_state->modeset) | ||
5184 | intel_state->active_crtcs = dev_priv->active_crtcs; | ||
5185 | } | ||
5186 | |||
5187 | /* | ||
5188 | * If the modeset changes which CRTC's are active, we need to | ||
5189 | * recompute the DDB allocation for *all* active pipes, even | ||
5190 | * those that weren't otherwise being modified in any way by this | ||
5191 | * atomic commit. Due to the shrinking of the per-pipe allocations | ||
5192 | * when new active CRTC's are added, it's possible for a pipe that | ||
5193 | * we were already using and aren't changing at all here to suddenly | ||
5194 | * become invalid if its DDB needs exceeds its new allocation. | ||
5195 | * | ||
5196 | * Note that if we wind up doing a full DDB recompute, we can't let | ||
5197 | * any other display updates race with this transaction, so we need | ||
5198 | * to grab the lock on *all* CRTC's. | ||
5199 | */ | ||
5200 | if (intel_state->active_pipe_changes) { | ||
5201 | realloc_pipes = ~0; | ||
5202 | intel_state->wm_results.dirty_pipes = ~0; | ||
5203 | } | ||
5204 | |||
5205 | /* | ||
5206 | * We're not recomputing for the pipes not included in the commit, so | ||
5207 | * make sure we start with the current state. | ||
5208 | */ | ||
5209 | for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { | ||
5210 | struct intel_crtc_state *cstate; | ||
5211 | |||
5212 | cstate = intel_atomic_get_crtc_state(state, intel_crtc); | ||
5213 | if (IS_ERR(cstate)) | ||
5214 | return PTR_ERR(cstate); | ||
5215 | } | ||
5216 | |||
5217 | return 0; | ||
5218 | } | ||
5219 | |||
5220 | static int | ||
5221 | skl_compute_wm(struct drm_atomic_state *state) | ||
5222 | { | ||
5223 | struct drm_crtc *crtc; | ||
5224 | struct drm_crtc_state *cstate; | ||
5225 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | ||
5226 | struct skl_ddb_values *results = &intel_state->wm_results; | ||
5227 | struct skl_pipe_wm *pipe_wm; | ||
5228 | bool changed = false; | ||
5229 | int ret, i; | ||
5230 | |||
5125 | /* Clear all dirty flags */ | 5231 | /* Clear all dirty flags */ |
5126 | results->dirty_pipes = 0; | 5232 | results->dirty_pipes = 0; |
5127 | 5233 | ||
5234 | ret = skl_ddb_add_affected_pipes(state, &changed); | ||
5235 | if (ret || !changed) | ||
5236 | return ret; | ||
5237 | |||
5128 | ret = skl_compute_ddb(state); | 5238 | ret = skl_compute_ddb(state); |
5129 | if (ret) | 5239 | if (ret) |
5130 | return ret; | 5240 | return ret; |
@@ -5197,8 +5307,8 @@ static void skl_initial_wm(struct intel_atomic_state *state, | |||
5197 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); | 5307 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); |
5198 | struct drm_device *dev = intel_crtc->base.dev; | 5308 | struct drm_device *dev = intel_crtc->base.dev; |
5199 | struct drm_i915_private *dev_priv = to_i915(dev); | 5309 | struct drm_i915_private *dev_priv = to_i915(dev); |
5200 | struct skl_wm_values *results = &state->wm_results; | 5310 | struct skl_ddb_values *results = &state->wm_results; |
5201 | struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw; | 5311 | struct skl_ddb_values *hw_vals = &dev_priv->wm.skl_hw; |
5202 | enum pipe pipe = intel_crtc->pipe; | 5312 | enum pipe pipe = intel_crtc->pipe; |
5203 | 5313 | ||
5204 | if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0) | 5314 | if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0) |
@@ -5209,7 +5319,7 @@ static void skl_initial_wm(struct intel_atomic_state *state, | |||
5209 | if (cstate->base.active_changed) | 5319 | if (cstate->base.active_changed) |
5210 | skl_atomic_update_crtc_wm(state, cstate); | 5320 | skl_atomic_update_crtc_wm(state, cstate); |
5211 | 5321 | ||
5212 | skl_copy_wm_for_pipe(hw_vals, results, pipe); | 5322 | skl_copy_ddb_for_pipe(hw_vals, results, pipe); |
5213 | 5323 | ||
5214 | mutex_unlock(&dev_priv->wm.wm_mutex); | 5324 | mutex_unlock(&dev_priv->wm.wm_mutex); |
5215 | } | 5325 | } |
@@ -5341,7 +5451,7 @@ void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, | |||
5341 | void skl_wm_get_hw_state(struct drm_device *dev) | 5451 | void skl_wm_get_hw_state(struct drm_device *dev) |
5342 | { | 5452 | { |
5343 | struct drm_i915_private *dev_priv = to_i915(dev); | 5453 | struct drm_i915_private *dev_priv = to_i915(dev); |
5344 | struct skl_wm_values *hw = &dev_priv->wm.skl_hw; | 5454 | struct skl_ddb_values *hw = &dev_priv->wm.skl_hw; |
5345 | struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; | 5455 | struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; |
5346 | struct drm_crtc *crtc; | 5456 | struct drm_crtc *crtc; |
5347 | struct intel_crtc *intel_crtc; | 5457 | struct intel_crtc *intel_crtc; |
@@ -6572,7 +6682,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) | |||
6572 | 6682 | ||
6573 | rps->efficient_freq = rps->rp1_freq; | 6683 | rps->efficient_freq = rps->rp1_freq; |
6574 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) || | 6684 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) || |
6575 | IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 6685 | IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) { |
6576 | u32 ddcc_status = 0; | 6686 | u32 ddcc_status = 0; |
6577 | 6687 | ||
6578 | if (sandybridge_pcode_read(dev_priv, | 6688 | if (sandybridge_pcode_read(dev_priv, |
@@ -6585,7 +6695,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) | |||
6585 | rps->max_freq); | 6695 | rps->max_freq); |
6586 | } | 6696 | } |
6587 | 6697 | ||
6588 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 6698 | if (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) { |
6589 | /* Store the frequency values in 16.66 MHZ units, which is | 6699 | /* Store the frequency values in 16.66 MHZ units, which is |
6590 | * the natural hardware unit for SKL | 6700 | * the natural hardware unit for SKL |
6591 | */ | 6701 | */ |
@@ -6890,15 +7000,18 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
6890 | static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | 7000 | static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) |
6891 | { | 7001 | { |
6892 | struct intel_rps *rps = &dev_priv->gt_pm.rps; | 7002 | struct intel_rps *rps = &dev_priv->gt_pm.rps; |
6893 | int min_freq = 15; | 7003 | const int min_freq = 15; |
7004 | const int scaling_factor = 180; | ||
6894 | unsigned int gpu_freq; | 7005 | unsigned int gpu_freq; |
6895 | unsigned int max_ia_freq, min_ring_freq; | 7006 | unsigned int max_ia_freq, min_ring_freq; |
6896 | unsigned int max_gpu_freq, min_gpu_freq; | 7007 | unsigned int max_gpu_freq, min_gpu_freq; |
6897 | int scaling_factor = 180; | ||
6898 | struct cpufreq_policy *policy; | 7008 | struct cpufreq_policy *policy; |
6899 | 7009 | ||
6900 | WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); | 7010 | WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); |
6901 | 7011 | ||
7012 | if (rps->max_freq <= rps->min_freq) | ||
7013 | return; | ||
7014 | |||
6902 | policy = cpufreq_cpu_get(0); | 7015 | policy = cpufreq_cpu_get(0); |
6903 | if (policy) { | 7016 | if (policy) { |
6904 | max_ia_freq = policy->cpuinfo.max_freq; | 7017 | max_ia_freq = policy->cpuinfo.max_freq; |
@@ -6918,13 +7031,12 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
6918 | /* convert DDR frequency from units of 266.6MHz to bandwidth */ | 7031 | /* convert DDR frequency from units of 266.6MHz to bandwidth */ |
6919 | min_ring_freq = mult_frac(min_ring_freq, 8, 3); | 7032 | min_ring_freq = mult_frac(min_ring_freq, 8, 3); |
6920 | 7033 | ||
6921 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 7034 | min_gpu_freq = rps->min_freq; |
7035 | max_gpu_freq = rps->max_freq; | ||
7036 | if (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) { | ||
6922 | /* Convert GT frequency to 50 HZ units */ | 7037 | /* Convert GT frequency to 50 HZ units */ |
6923 | min_gpu_freq = rps->min_freq / GEN9_FREQ_SCALER; | 7038 | min_gpu_freq /= GEN9_FREQ_SCALER; |
6924 | max_gpu_freq = rps->max_freq / GEN9_FREQ_SCALER; | 7039 | max_gpu_freq /= GEN9_FREQ_SCALER; |
6925 | } else { | ||
6926 | min_gpu_freq = rps->min_freq; | ||
6927 | max_gpu_freq = rps->max_freq; | ||
6928 | } | 7040 | } |
6929 | 7041 | ||
6930 | /* | 7042 | /* |
@@ -6933,10 +7045,10 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
6933 | * the PCU should use as a reference to determine the ring frequency. | 7045 | * the PCU should use as a reference to determine the ring frequency. |
6934 | */ | 7046 | */ |
6935 | for (gpu_freq = max_gpu_freq; gpu_freq >= min_gpu_freq; gpu_freq--) { | 7047 | for (gpu_freq = max_gpu_freq; gpu_freq >= min_gpu_freq; gpu_freq--) { |
6936 | int diff = max_gpu_freq - gpu_freq; | 7048 | const int diff = max_gpu_freq - gpu_freq; |
6937 | unsigned int ia_freq = 0, ring_freq = 0; | 7049 | unsigned int ia_freq = 0, ring_freq = 0; |
6938 | 7050 | ||
6939 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 7051 | if (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) { |
6940 | /* | 7052 | /* |
6941 | * ring_freq = 2 * GT. ring_freq is in 100MHz units | 7053 | * ring_freq = 2 * GT. ring_freq is in 100MHz units |
6942 | * No floor required for ring frequency on SKL. | 7054 | * No floor required for ring frequency on SKL. |
@@ -8026,10 +8138,10 @@ void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv) | |||
8026 | dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */ | 8138 | dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */ |
8027 | intel_disable_gt_powersave(dev_priv); | 8139 | intel_disable_gt_powersave(dev_priv); |
8028 | 8140 | ||
8029 | if (INTEL_GEN(dev_priv) < 11) | 8141 | if (INTEL_GEN(dev_priv) >= 11) |
8030 | gen6_reset_rps_interrupts(dev_priv); | 8142 | gen11_reset_rps_interrupts(dev_priv); |
8031 | else | 8143 | else |
8032 | WARN_ON_ONCE(1); | 8144 | gen6_reset_rps_interrupts(dev_priv); |
8033 | } | 8145 | } |
8034 | 8146 | ||
8035 | static inline void intel_disable_llc_pstate(struct drm_i915_private *i915) | 8147 | static inline void intel_disable_llc_pstate(struct drm_i915_private *i915) |
@@ -8142,8 +8254,6 @@ static void intel_enable_rps(struct drm_i915_private *dev_priv) | |||
8142 | cherryview_enable_rps(dev_priv); | 8254 | cherryview_enable_rps(dev_priv); |
8143 | } else if (IS_VALLEYVIEW(dev_priv)) { | 8255 | } else if (IS_VALLEYVIEW(dev_priv)) { |
8144 | valleyview_enable_rps(dev_priv); | 8256 | valleyview_enable_rps(dev_priv); |
8145 | } else if (WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11)) { | ||
8146 | /* TODO */ | ||
8147 | } else if (INTEL_GEN(dev_priv) >= 9) { | 8257 | } else if (INTEL_GEN(dev_priv) >= 9) { |
8148 | gen9_enable_rps(dev_priv); | 8258 | gen9_enable_rps(dev_priv); |
8149 | } else if (IS_BROADWELL(dev_priv)) { | 8259 | } else if (IS_BROADWELL(dev_priv)) { |
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 23175c5c4a50..69a5b276f4d8 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c | |||
@@ -93,7 +93,7 @@ static void psr_aux_io_power_put(struct intel_dp *intel_dp) | |||
93 | intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); | 93 | intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); |
94 | } | 94 | } |
95 | 95 | ||
96 | static bool intel_dp_get_y_cord_status(struct intel_dp *intel_dp) | 96 | static bool intel_dp_get_y_coord_required(struct intel_dp *intel_dp) |
97 | { | 97 | { |
98 | uint8_t psr_caps = 0; | 98 | uint8_t psr_caps = 0; |
99 | 99 | ||
@@ -122,6 +122,18 @@ static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp) | |||
122 | return alpm_caps & DP_ALPM_CAP; | 122 | return alpm_caps & DP_ALPM_CAP; |
123 | } | 123 | } |
124 | 124 | ||
125 | static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) | ||
126 | { | ||
127 | u8 val = 0; | ||
128 | |||
129 | if (drm_dp_dpcd_readb(&intel_dp->aux, | ||
130 | DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val) == 1) | ||
131 | val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; | ||
132 | else | ||
133 | DRM_ERROR("Unable to get sink synchronization latency\n"); | ||
134 | return val; | ||
135 | } | ||
136 | |||
125 | void intel_psr_init_dpcd(struct intel_dp *intel_dp) | 137 | void intel_psr_init_dpcd(struct intel_dp *intel_dp) |
126 | { | 138 | { |
127 | struct drm_i915_private *dev_priv = | 139 | struct drm_i915_private *dev_priv = |
@@ -130,33 +142,36 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) | |||
130 | drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, | 142 | drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, |
131 | sizeof(intel_dp->psr_dpcd)); | 143 | sizeof(intel_dp->psr_dpcd)); |
132 | 144 | ||
133 | if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { | 145 | if (intel_dp->psr_dpcd[0]) { |
134 | dev_priv->psr.sink_support = true; | 146 | dev_priv->psr.sink_support = true; |
135 | DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); | 147 | DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); |
136 | } | 148 | } |
137 | 149 | ||
138 | if (INTEL_GEN(dev_priv) >= 9 && | 150 | if (INTEL_GEN(dev_priv) >= 9 && |
139 | (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { | 151 | (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) { |
140 | uint8_t frame_sync_cap; | 152 | /* |
153 | * All panels that supports PSR version 03h (PSR2 + | ||
154 | * Y-coordinate) can handle Y-coordinates in VSC but we are | ||
155 | * only sure that it is going to be used when required by the | ||
156 | * panel. This way panel is capable to do selective update | ||
157 | * without a aux frame sync. | ||
158 | * | ||
159 | * To support PSR version 02h and PSR version 03h without | ||
160 | * Y-coordinate requirement panels we would need to enable | ||
161 | * GTC first. | ||
162 | */ | ||
163 | dev_priv->psr.sink_psr2_support = | ||
164 | intel_dp_get_y_coord_required(intel_dp); | ||
165 | DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.sink_psr2_support | ||
166 | ? "supported" : "not supported"); | ||
141 | 167 | ||
142 | dev_priv->psr.sink_support = true; | 168 | if (dev_priv->psr.sink_psr2_support) { |
143 | if (drm_dp_dpcd_readb(&intel_dp->aux, | ||
144 | DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, | ||
145 | &frame_sync_cap) != 1) | ||
146 | frame_sync_cap = 0; | ||
147 | dev_priv->psr.aux_frame_sync = frame_sync_cap & DP_AUX_FRAME_SYNC_CAP; | ||
148 | /* PSR2 needs frame sync as well */ | ||
149 | dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; | ||
150 | DRM_DEBUG_KMS("PSR2 %s on sink", | ||
151 | dev_priv->psr.psr2_support ? "supported" : "not supported"); | ||
152 | |||
153 | if (dev_priv->psr.psr2_support) { | ||
154 | dev_priv->psr.y_cord_support = | ||
155 | intel_dp_get_y_cord_status(intel_dp); | ||
156 | dev_priv->psr.colorimetry_support = | 169 | dev_priv->psr.colorimetry_support = |
157 | intel_dp_get_colorimetry_status(intel_dp); | 170 | intel_dp_get_colorimetry_status(intel_dp); |
158 | dev_priv->psr.alpm = | 171 | dev_priv->psr.alpm = |
159 | intel_dp_get_alpm_status(intel_dp); | 172 | intel_dp_get_alpm_status(intel_dp); |
173 | dev_priv->psr.sink_sync_latency = | ||
174 | intel_dp_get_sink_sync_latency(intel_dp); | ||
160 | } | 175 | } |
161 | } | 176 | } |
162 | } | 177 | } |
@@ -193,21 +208,17 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, | |||
193 | struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); | 208 | struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); |
194 | struct edp_vsc_psr psr_vsc; | 209 | struct edp_vsc_psr psr_vsc; |
195 | 210 | ||
196 | if (dev_priv->psr.psr2_support) { | 211 | if (dev_priv->psr.psr2_enabled) { |
197 | /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ | 212 | /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ |
198 | memset(&psr_vsc, 0, sizeof(psr_vsc)); | 213 | memset(&psr_vsc, 0, sizeof(psr_vsc)); |
199 | psr_vsc.sdp_header.HB0 = 0; | 214 | psr_vsc.sdp_header.HB0 = 0; |
200 | psr_vsc.sdp_header.HB1 = 0x7; | 215 | psr_vsc.sdp_header.HB1 = 0x7; |
201 | if (dev_priv->psr.colorimetry_support && | 216 | if (dev_priv->psr.colorimetry_support) { |
202 | dev_priv->psr.y_cord_support) { | ||
203 | psr_vsc.sdp_header.HB2 = 0x5; | 217 | psr_vsc.sdp_header.HB2 = 0x5; |
204 | psr_vsc.sdp_header.HB3 = 0x13; | 218 | psr_vsc.sdp_header.HB3 = 0x13; |
205 | } else if (dev_priv->psr.y_cord_support) { | 219 | } else { |
206 | psr_vsc.sdp_header.HB2 = 0x4; | 220 | psr_vsc.sdp_header.HB2 = 0x4; |
207 | psr_vsc.sdp_header.HB3 = 0xe; | 221 | psr_vsc.sdp_header.HB3 = 0xe; |
208 | } else { | ||
209 | psr_vsc.sdp_header.HB2 = 0x3; | ||
210 | psr_vsc.sdp_header.HB3 = 0xc; | ||
211 | } | 222 | } |
212 | } else { | 223 | } else { |
213 | /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ | 224 | /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ |
@@ -228,31 +239,12 @@ static void vlv_psr_enable_sink(struct intel_dp *intel_dp) | |||
228 | DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); | 239 | DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); |
229 | } | 240 | } |
230 | 241 | ||
231 | static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, | 242 | static void hsw_psr_setup_aux(struct intel_dp *intel_dp) |
232 | enum port port) | ||
233 | { | ||
234 | if (INTEL_GEN(dev_priv) >= 9) | ||
235 | return DP_AUX_CH_CTL(port); | ||
236 | else | ||
237 | return EDP_PSR_AUX_CTL; | ||
238 | } | ||
239 | |||
240 | static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, | ||
241 | enum port port, int index) | ||
242 | { | ||
243 | if (INTEL_GEN(dev_priv) >= 9) | ||
244 | return DP_AUX_CH_DATA(port, index); | ||
245 | else | ||
246 | return EDP_PSR_AUX_DATA(index); | ||
247 | } | ||
248 | |||
249 | static void hsw_psr_enable_sink(struct intel_dp *intel_dp) | ||
250 | { | 243 | { |
251 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | 244 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
252 | struct drm_device *dev = dig_port->base.base.dev; | 245 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
253 | struct drm_i915_private *dev_priv = to_i915(dev); | 246 | u32 aux_clock_divider, aux_ctl; |
254 | uint32_t aux_clock_divider; | 247 | int i; |
255 | i915_reg_t aux_ctl_reg; | ||
256 | static const uint8_t aux_msg[] = { | 248 | static const uint8_t aux_msg[] = { |
257 | [0] = DP_AUX_NATIVE_WRITE << 4, | 249 | [0] = DP_AUX_NATIVE_WRITE << 4, |
258 | [1] = DP_SET_POWER >> 8, | 250 | [1] = DP_SET_POWER >> 8, |
@@ -260,41 +252,47 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) | |||
260 | [3] = 1 - 1, | 252 | [3] = 1 - 1, |
261 | [4] = DP_SET_POWER_D0, | 253 | [4] = DP_SET_POWER_D0, |
262 | }; | 254 | }; |
263 | enum port port = dig_port->base.port; | 255 | u32 psr_aux_mask = EDP_PSR_AUX_CTL_TIME_OUT_MASK | |
264 | u32 aux_ctl; | 256 | EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK | |
265 | int i; | 257 | EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK | |
258 | EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK; | ||
266 | 259 | ||
267 | BUILD_BUG_ON(sizeof(aux_msg) > 20); | 260 | BUILD_BUG_ON(sizeof(aux_msg) > 20); |
261 | for (i = 0; i < sizeof(aux_msg); i += 4) | ||
262 | I915_WRITE(EDP_PSR_AUX_DATA(i >> 2), | ||
263 | intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i)); | ||
268 | 264 | ||
269 | aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); | 265 | aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); |
270 | 266 | ||
271 | /* Enable AUX frame sync at sink */ | 267 | /* Start with bits set for DDI_AUX_CTL register */ |
272 | if (dev_priv->psr.aux_frame_sync) | 268 | aux_ctl = intel_dp->get_aux_send_ctl(intel_dp, 0, sizeof(aux_msg), |
273 | drm_dp_dpcd_writeb(&intel_dp->aux, | 269 | aux_clock_divider); |
274 | DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, | 270 | |
275 | DP_AUX_FRAME_SYNC_ENABLE); | 271 | /* Select only valid bits for SRD_AUX_CTL */ |
272 | aux_ctl &= psr_aux_mask; | ||
273 | I915_WRITE(EDP_PSR_AUX_CTL, aux_ctl); | ||
274 | } | ||
275 | |||
276 | static void hsw_psr_enable_sink(struct intel_dp *intel_dp) | ||
277 | { | ||
278 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | ||
279 | struct drm_device *dev = dig_port->base.base.dev; | ||
280 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
281 | u8 dpcd_val = DP_PSR_ENABLE; | ||
282 | |||
276 | /* Enable ALPM at sink for psr2 */ | 283 | /* Enable ALPM at sink for psr2 */ |
277 | if (dev_priv->psr.psr2_support && dev_priv->psr.alpm) | 284 | if (dev_priv->psr.psr2_enabled && dev_priv->psr.alpm) |
278 | drm_dp_dpcd_writeb(&intel_dp->aux, | 285 | drm_dp_dpcd_writeb(&intel_dp->aux, |
279 | DP_RECEIVER_ALPM_CONFIG, | 286 | DP_RECEIVER_ALPM_CONFIG, |
280 | DP_ALPM_ENABLE); | 287 | DP_ALPM_ENABLE); |
281 | if (dev_priv->psr.link_standby) | ||
282 | drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, | ||
283 | DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); | ||
284 | else | ||
285 | drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, | ||
286 | DP_PSR_ENABLE); | ||
287 | |||
288 | aux_ctl_reg = psr_aux_ctl_reg(dev_priv, port); | ||
289 | 288 | ||
290 | /* Setup AUX registers */ | 289 | if (dev_priv->psr.psr2_enabled) |
291 | for (i = 0; i < sizeof(aux_msg); i += 4) | 290 | dpcd_val |= DP_PSR_ENABLE_PSR2; |
292 | I915_WRITE(psr_aux_data_reg(dev_priv, port, i >> 2), | 291 | if (dev_priv->psr.link_standby) |
293 | intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i)); | 292 | dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; |
293 | drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, dpcd_val); | ||
294 | 294 | ||
295 | aux_ctl = intel_dp->get_aux_send_ctl(intel_dp, 0, sizeof(aux_msg), | 295 | drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); |
296 | aux_clock_divider); | ||
297 | I915_WRITE(aux_ctl_reg, aux_ctl); | ||
298 | } | 296 | } |
299 | 297 | ||
300 | static void vlv_psr_enable_source(struct intel_dp *intel_dp, | 298 | static void vlv_psr_enable_source(struct intel_dp *intel_dp, |
@@ -396,25 +394,17 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) | |||
396 | * with the 5 or 6 idle patterns. | 394 | * with the 5 or 6 idle patterns. |
397 | */ | 395 | */ |
398 | uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); | 396 | uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); |
399 | uint32_t val; | 397 | u32 val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; |
400 | uint8_t sink_latency; | ||
401 | |||
402 | val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; | ||
403 | 398 | ||
404 | /* FIXME: selective update is probably totally broken because it doesn't | 399 | /* FIXME: selective update is probably totally broken because it doesn't |
405 | * mesh at all with our frontbuffer tracking. And the hw alone isn't | 400 | * mesh at all with our frontbuffer tracking. And the hw alone isn't |
406 | * good enough. */ | 401 | * good enough. */ |
407 | val |= EDP_PSR2_ENABLE | | 402 | val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; |
408 | EDP_SU_TRACK_ENABLE; | 403 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { |
409 | 404 | val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; | |
410 | if (drm_dp_dpcd_readb(&intel_dp->aux, | ||
411 | DP_SYNCHRONIZATION_LATENCY_IN_SINK, | ||
412 | &sink_latency) == 1) { | ||
413 | sink_latency &= DP_MAX_RESYNC_FRAME_COUNT_MASK; | ||
414 | } else { | ||
415 | sink_latency = 0; | ||
416 | } | 405 | } |
417 | val |= EDP_PSR2_FRAME_BEFORE_SU(sink_latency + 1); | 406 | |
407 | val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); | ||
418 | 408 | ||
419 | if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) | 409 | if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) |
420 | val |= EDP_PSR2_TP2_TIME_2500; | 410 | val |= EDP_PSR2_TP2_TIME_2500; |
@@ -440,7 +430,7 @@ static void hsw_psr_activate(struct intel_dp *intel_dp) | |||
440 | */ | 430 | */ |
441 | 431 | ||
442 | /* psr1 and psr2 are mutually exclusive.*/ | 432 | /* psr1 and psr2 are mutually exclusive.*/ |
443 | if (dev_priv->psr.psr2_support) | 433 | if (dev_priv->psr.psr2_enabled) |
444 | hsw_activate_psr2(intel_dp); | 434 | hsw_activate_psr2(intel_dp); |
445 | else | 435 | else |
446 | hsw_activate_psr1(intel_dp); | 436 | hsw_activate_psr1(intel_dp); |
@@ -460,7 +450,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, | |||
460 | * dynamically during PSR enable, and extracted from sink | 450 | * dynamically during PSR enable, and extracted from sink |
461 | * caps during eDP detection. | 451 | * caps during eDP detection. |
462 | */ | 452 | */ |
463 | if (!dev_priv->psr.psr2_support) | 453 | if (!dev_priv->psr.sink_psr2_support) |
464 | return false; | 454 | return false; |
465 | 455 | ||
466 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { | 456 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { |
@@ -478,15 +468,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, | |||
478 | return false; | 468 | return false; |
479 | } | 469 | } |
480 | 470 | ||
481 | /* | ||
482 | * FIXME:enable psr2 only for y-cordinate psr2 panels | ||
483 | * After gtc implementation , remove this restriction. | ||
484 | */ | ||
485 | if (!dev_priv->psr.y_cord_support) { | ||
486 | DRM_DEBUG_KMS("PSR2 not enabled, panel does not support Y coordinate\n"); | ||
487 | return false; | ||
488 | } | ||
489 | |||
490 | return true; | 471 | return true; |
491 | } | 472 | } |
492 | 473 | ||
@@ -568,7 +549,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) | |||
568 | struct drm_device *dev = intel_dig_port->base.base.dev; | 549 | struct drm_device *dev = intel_dig_port->base.base.dev; |
569 | struct drm_i915_private *dev_priv = to_i915(dev); | 550 | struct drm_i915_private *dev_priv = to_i915(dev); |
570 | 551 | ||
571 | if (dev_priv->psr.psr2_support) | 552 | if (dev_priv->psr.psr2_enabled) |
572 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); | 553 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); |
573 | else | 554 | else |
574 | WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); | 555 | WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); |
@@ -586,14 +567,24 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp, | |||
586 | struct drm_device *dev = dig_port->base.base.dev; | 567 | struct drm_device *dev = dig_port->base.base.dev; |
587 | struct drm_i915_private *dev_priv = to_i915(dev); | 568 | struct drm_i915_private *dev_priv = to_i915(dev); |
588 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; | 569 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
589 | u32 chicken; | ||
590 | 570 | ||
591 | psr_aux_io_power_get(intel_dp); | 571 | psr_aux_io_power_get(intel_dp); |
592 | 572 | ||
593 | if (dev_priv->psr.psr2_support) { | 573 | /* Only HSW and BDW have PSR AUX registers that need to be setup. SKL+ |
594 | chicken = PSR2_VSC_ENABLE_PROG_HEADER; | 574 | * use hardcoded values PSR AUX transactions |
595 | if (dev_priv->psr.y_cord_support) | 575 | */ |
596 | chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; | 576 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
577 | hsw_psr_setup_aux(intel_dp); | ||
578 | |||
579 | if (dev_priv->psr.psr2_enabled) { | ||
580 | u32 chicken = I915_READ(CHICKEN_TRANS(cpu_transcoder)); | ||
581 | |||
582 | if (INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) | ||
583 | chicken |= (PSR2_VSC_ENABLE_PROG_HEADER | ||
584 | | PSR2_ADD_VERTICAL_LINE_COUNT); | ||
585 | |||
586 | else | ||
587 | chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL; | ||
597 | I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); | 588 | I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); |
598 | 589 | ||
599 | I915_WRITE(EDP_PSR_DEBUG, | 590 | I915_WRITE(EDP_PSR_DEBUG, |
@@ -644,7 +635,7 @@ void intel_psr_enable(struct intel_dp *intel_dp, | |||
644 | goto unlock; | 635 | goto unlock; |
645 | } | 636 | } |
646 | 637 | ||
647 | dev_priv->psr.psr2_support = crtc_state->has_psr2; | 638 | dev_priv->psr.psr2_enabled = crtc_state->has_psr2; |
648 | dev_priv->psr.busy_frontbuffer_bits = 0; | 639 | dev_priv->psr.busy_frontbuffer_bits = 0; |
649 | 640 | ||
650 | dev_priv->psr.setup_vsc(intel_dp, crtc_state); | 641 | dev_priv->psr.setup_vsc(intel_dp, crtc_state); |
@@ -714,12 +705,7 @@ static void hsw_psr_disable(struct intel_dp *intel_dp, | |||
714 | i915_reg_t psr_status; | 705 | i915_reg_t psr_status; |
715 | u32 psr_status_mask; | 706 | u32 psr_status_mask; |
716 | 707 | ||
717 | if (dev_priv->psr.aux_frame_sync) | 708 | if (dev_priv->psr.psr2_enabled) { |
718 | drm_dp_dpcd_writeb(&intel_dp->aux, | ||
719 | DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, | ||
720 | 0); | ||
721 | |||
722 | if (dev_priv->psr.psr2_support) { | ||
723 | psr_status = EDP_PSR2_STATUS; | 709 | psr_status = EDP_PSR2_STATUS; |
724 | psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; | 710 | psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; |
725 | 711 | ||
@@ -743,7 +729,7 @@ static void hsw_psr_disable(struct intel_dp *intel_dp, | |||
743 | 729 | ||
744 | dev_priv->psr.active = false; | 730 | dev_priv->psr.active = false; |
745 | } else { | 731 | } else { |
746 | if (dev_priv->psr.psr2_support) | 732 | if (dev_priv->psr.psr2_enabled) |
747 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); | 733 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); |
748 | else | 734 | else |
749 | WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); | 735 | WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); |
@@ -789,53 +775,59 @@ void intel_psr_disable(struct intel_dp *intel_dp, | |||
789 | cancel_delayed_work_sync(&dev_priv->psr.work); | 775 | cancel_delayed_work_sync(&dev_priv->psr.work); |
790 | } | 776 | } |
791 | 777 | ||
792 | static void intel_psr_work(struct work_struct *work) | 778 | static bool psr_wait_for_idle(struct drm_i915_private *dev_priv) |
793 | { | 779 | { |
794 | struct drm_i915_private *dev_priv = | 780 | struct intel_dp *intel_dp; |
795 | container_of(work, typeof(*dev_priv), psr.work.work); | 781 | i915_reg_t reg; |
796 | struct intel_dp *intel_dp = dev_priv->psr.enabled; | 782 | u32 mask; |
797 | struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; | 783 | int err; |
798 | enum pipe pipe = to_intel_crtc(crtc)->pipe; | 784 | |
785 | intel_dp = dev_priv->psr.enabled; | ||
786 | if (!intel_dp) | ||
787 | return false; | ||
799 | 788 | ||
800 | /* We have to make sure PSR is ready for re-enable | ||
801 | * otherwise it keeps disabled until next full enable/disable cycle. | ||
802 | * PSR might take some time to get fully disabled | ||
803 | * and be ready for re-enable. | ||
804 | */ | ||
805 | if (HAS_DDI(dev_priv)) { | 789 | if (HAS_DDI(dev_priv)) { |
806 | if (dev_priv->psr.psr2_support) { | 790 | if (dev_priv->psr.psr2_enabled) { |
807 | if (intel_wait_for_register(dev_priv, | 791 | reg = EDP_PSR2_STATUS; |
808 | EDP_PSR2_STATUS, | 792 | mask = EDP_PSR2_STATUS_STATE_MASK; |
809 | EDP_PSR2_STATUS_STATE_MASK, | ||
810 | 0, | ||
811 | 50)) { | ||
812 | DRM_ERROR("Timed out waiting for PSR2 Idle for re-enable\n"); | ||
813 | return; | ||
814 | } | ||
815 | } else { | 793 | } else { |
816 | if (intel_wait_for_register(dev_priv, | 794 | reg = EDP_PSR_STATUS; |
817 | EDP_PSR_STATUS, | 795 | mask = EDP_PSR_STATUS_STATE_MASK; |
818 | EDP_PSR_STATUS_STATE_MASK, | ||
819 | 0, | ||
820 | 50)) { | ||
821 | DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); | ||
822 | return; | ||
823 | } | ||
824 | } | 796 | } |
825 | } else { | 797 | } else { |
826 | if (intel_wait_for_register(dev_priv, | 798 | struct drm_crtc *crtc = |
827 | VLV_PSRSTAT(pipe), | 799 | dp_to_dig_port(intel_dp)->base.base.crtc; |
828 | VLV_EDP_PSR_IN_TRANS, | 800 | enum pipe pipe = to_intel_crtc(crtc)->pipe; |
829 | 0, | 801 | |
830 | 1)) { | 802 | reg = VLV_PSRSTAT(pipe); |
831 | DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); | 803 | mask = VLV_EDP_PSR_IN_TRANS; |
832 | return; | ||
833 | } | ||
834 | } | 804 | } |
805 | |||
806 | mutex_unlock(&dev_priv->psr.lock); | ||
807 | |||
808 | err = intel_wait_for_register(dev_priv, reg, mask, 0, 50); | ||
809 | if (err) | ||
810 | DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); | ||
811 | |||
812 | /* After the unlocked wait, verify that PSR is still wanted! */ | ||
835 | mutex_lock(&dev_priv->psr.lock); | 813 | mutex_lock(&dev_priv->psr.lock); |
836 | intel_dp = dev_priv->psr.enabled; | 814 | return err == 0 && dev_priv->psr.enabled; |
815 | } | ||
837 | 816 | ||
838 | if (!intel_dp) | 817 | static void intel_psr_work(struct work_struct *work) |
818 | { | ||
819 | struct drm_i915_private *dev_priv = | ||
820 | container_of(work, typeof(*dev_priv), psr.work.work); | ||
821 | |||
822 | mutex_lock(&dev_priv->psr.lock); | ||
823 | |||
824 | /* | ||
825 | * We have to make sure PSR is ready for re-enable | ||
826 | * otherwise it keeps disabled until next full enable/disable cycle. | ||
827 | * PSR might take some time to get fully disabled | ||
828 | * and be ready for re-enable. | ||
829 | */ | ||
830 | if (!psr_wait_for_idle(dev_priv)) | ||
839 | goto unlock; | 831 | goto unlock; |
840 | 832 | ||
841 | /* | 833 | /* |
@@ -846,7 +838,7 @@ static void intel_psr_work(struct work_struct *work) | |||
846 | if (dev_priv->psr.busy_frontbuffer_bits) | 838 | if (dev_priv->psr.busy_frontbuffer_bits) |
847 | goto unlock; | 839 | goto unlock; |
848 | 840 | ||
849 | intel_psr_activate(intel_dp); | 841 | intel_psr_activate(dev_priv->psr.enabled); |
850 | unlock: | 842 | unlock: |
851 | mutex_unlock(&dev_priv->psr.lock); | 843 | mutex_unlock(&dev_priv->psr.lock); |
852 | } | 844 | } |
@@ -862,11 +854,7 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) | |||
862 | return; | 854 | return; |
863 | 855 | ||
864 | if (HAS_DDI(dev_priv)) { | 856 | if (HAS_DDI(dev_priv)) { |
865 | if (dev_priv->psr.aux_frame_sync) | 857 | if (dev_priv->psr.psr2_enabled) { |
866 | drm_dp_dpcd_writeb(&intel_dp->aux, | ||
867 | DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, | ||
868 | 0); | ||
869 | if (dev_priv->psr.psr2_support) { | ||
870 | val = I915_READ(EDP_PSR2_CTL); | 858 | val = I915_READ(EDP_PSR2_CTL); |
871 | WARN_ON(!(val & EDP_PSR2_ENABLE)); | 859 | WARN_ON(!(val & EDP_PSR2_ENABLE)); |
872 | I915_WRITE(EDP_PSR2_CTL, val & ~EDP_PSR2_ENABLE); | 860 | I915_WRITE(EDP_PSR2_CTL, val & ~EDP_PSR2_ENABLE); |
@@ -957,6 +945,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, | |||
957 | * intel_psr_invalidate - Invalidade PSR | 945 | * intel_psr_invalidate - Invalidade PSR |
958 | * @dev_priv: i915 device | 946 | * @dev_priv: i915 device |
959 | * @frontbuffer_bits: frontbuffer plane tracking bits | 947 | * @frontbuffer_bits: frontbuffer plane tracking bits |
948 | * @origin: which operation caused the invalidate | ||
960 | * | 949 | * |
961 | * Since the hardware frontbuffer tracking has gaps we need to integrate | 950 | * Since the hardware frontbuffer tracking has gaps we need to integrate |
962 | * with the software frontbuffer tracking. This function gets called every | 951 | * with the software frontbuffer tracking. This function gets called every |
@@ -966,7 +955,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, | |||
966 | * Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits." | 955 | * Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits." |
967 | */ | 956 | */ |
968 | void intel_psr_invalidate(struct drm_i915_private *dev_priv, | 957 | void intel_psr_invalidate(struct drm_i915_private *dev_priv, |
969 | unsigned frontbuffer_bits) | 958 | unsigned frontbuffer_bits, enum fb_op_origin origin) |
970 | { | 959 | { |
971 | struct drm_crtc *crtc; | 960 | struct drm_crtc *crtc; |
972 | enum pipe pipe; | 961 | enum pipe pipe; |
@@ -974,6 +963,9 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, | |||
974 | if (!CAN_PSR(dev_priv)) | 963 | if (!CAN_PSR(dev_priv)) |
975 | return; | 964 | return; |
976 | 965 | ||
966 | if (dev_priv->psr.has_hw_tracking && origin == ORIGIN_FLIP) | ||
967 | return; | ||
968 | |||
977 | mutex_lock(&dev_priv->psr.lock); | 969 | mutex_lock(&dev_priv->psr.lock); |
978 | if (!dev_priv->psr.enabled) { | 970 | if (!dev_priv->psr.enabled) { |
979 | mutex_unlock(&dev_priv->psr.lock); | 971 | mutex_unlock(&dev_priv->psr.lock); |
@@ -1014,6 +1006,9 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, | |||
1014 | if (!CAN_PSR(dev_priv)) | 1006 | if (!CAN_PSR(dev_priv)) |
1015 | return; | 1007 | return; |
1016 | 1008 | ||
1009 | if (dev_priv->psr.has_hw_tracking && origin == ORIGIN_FLIP) | ||
1010 | return; | ||
1011 | |||
1017 | mutex_lock(&dev_priv->psr.lock); | 1012 | mutex_lock(&dev_priv->psr.lock); |
1018 | if (!dev_priv->psr.enabled) { | 1013 | if (!dev_priv->psr.enabled) { |
1019 | mutex_unlock(&dev_priv->psr.lock); | 1014 | mutex_unlock(&dev_priv->psr.lock); |
@@ -1027,8 +1022,23 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, | |||
1027 | dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; | 1022 | dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; |
1028 | 1023 | ||
1029 | /* By definition flush = invalidate + flush */ | 1024 | /* By definition flush = invalidate + flush */ |
1030 | if (frontbuffer_bits) | 1025 | if (frontbuffer_bits) { |
1031 | intel_psr_exit(dev_priv); | 1026 | if (dev_priv->psr.psr2_enabled || |
1027 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
1028 | intel_psr_exit(dev_priv); | ||
1029 | } else { | ||
1030 | /* | ||
1031 | * Display WA #0884: all | ||
1032 | * This documented WA for bxt can be safely applied | ||
1033 | * broadly so we can force HW tracking to exit PSR | ||
1034 | * instead of disabling and re-enabling. | ||
1035 | * Workaround tells us to write 0 to CUR_SURFLIVE_A, | ||
1036 | * but it makes more sense write to the current active | ||
1037 | * pipe. | ||
1038 | */ | ||
1039 | I915_WRITE(CURSURFLIVE(pipe), 0); | ||
1040 | } | ||
1041 | } | ||
1032 | 1042 | ||
1033 | if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) | 1043 | if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) |
1034 | if (!work_busy(&dev_priv->psr.work.work)) | 1044 | if (!work_busy(&dev_priv->psr.work.work)) |
@@ -1090,6 +1100,7 @@ void intel_psr_init(struct drm_i915_private *dev_priv) | |||
1090 | dev_priv->psr.activate = vlv_psr_activate; | 1100 | dev_priv->psr.activate = vlv_psr_activate; |
1091 | dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; | 1101 | dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; |
1092 | } else { | 1102 | } else { |
1103 | dev_priv->psr.has_hw_tracking = true; | ||
1093 | dev_priv->psr.enable_source = hsw_psr_enable_source; | 1104 | dev_priv->psr.enable_source = hsw_psr_enable_source; |
1094 | dev_priv->psr.disable_source = hsw_psr_disable; | 1105 | dev_priv->psr.disable_source = hsw_psr_disable; |
1095 | dev_priv->psr.enable_sink = hsw_psr_enable_sink; | 1106 | dev_priv->psr.enable_sink = hsw_psr_enable_sink; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1d599524a759..757bb0990c07 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "i915_gem_render_state.h" | 36 | #include "i915_gem_render_state.h" |
37 | #include "i915_trace.h" | 37 | #include "i915_trace.h" |
38 | #include "intel_drv.h" | 38 | #include "intel_drv.h" |
39 | #include "intel_workarounds.h" | ||
39 | 40 | ||
40 | /* Rough estimate of the typical request size, performing a flush, | 41 | /* Rough estimate of the typical request size, performing a flush, |
41 | * set-context and then emitting the batch. | 42 | * set-context and then emitting the batch. |
@@ -599,7 +600,7 @@ static int intel_rcs_ctx_init(struct i915_request *rq) | |||
599 | { | 600 | { |
600 | int ret; | 601 | int ret; |
601 | 602 | ||
602 | ret = intel_ring_workarounds_emit(rq); | 603 | ret = intel_ctx_workarounds_emit(rq); |
603 | if (ret != 0) | 604 | if (ret != 0) |
604 | return ret; | 605 | return ret; |
605 | 606 | ||
@@ -617,6 +618,10 @@ static int init_render_ring(struct intel_engine_cs *engine) | |||
617 | if (ret) | 618 | if (ret) |
618 | return ret; | 619 | return ret; |
619 | 620 | ||
621 | ret = intel_whitelist_workarounds_apply(engine); | ||
622 | if (ret) | ||
623 | return ret; | ||
624 | |||
620 | /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ | 625 | /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ |
621 | if (IS_GEN(dev_priv, 4, 6)) | 626 | if (IS_GEN(dev_priv, 4, 6)) |
622 | I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); | 627 | I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); |
@@ -658,7 +663,7 @@ static int init_render_ring(struct intel_engine_cs *engine) | |||
658 | if (INTEL_GEN(dev_priv) >= 6) | 663 | if (INTEL_GEN(dev_priv) >= 6) |
659 | I915_WRITE_IMR(engine, ~engine->irq_keep_mask); | 664 | I915_WRITE_IMR(engine, ~engine->irq_keep_mask); |
660 | 665 | ||
661 | return init_workarounds_ring(engine); | 666 | return 0; |
662 | } | 667 | } |
663 | 668 | ||
664 | static u32 *gen6_signal(struct i915_request *rq, u32 *cs) | 669 | static u32 *gen6_signal(struct i915_request *rq, u32 *cs) |
@@ -1593,6 +1598,7 @@ static noinline int wait_for_space(struct intel_ring *ring, unsigned int bytes) | |||
1593 | if (intel_ring_update_space(ring) >= bytes) | 1598 | if (intel_ring_update_space(ring) >= bytes) |
1594 | return 0; | 1599 | return 0; |
1595 | 1600 | ||
1601 | GEM_BUG_ON(list_empty(&ring->request_list)); | ||
1596 | list_for_each_entry(target, &ring->request_list, ring_link) { | 1602 | list_for_each_entry(target, &ring->request_list, ring_link) { |
1597 | /* Would completion of this request free enough space? */ | 1603 | /* Would completion of this request free enough space? */ |
1598 | if (bytes <= __intel_ring_space(target->postfix, | 1604 | if (bytes <= __intel_ring_space(target->postfix, |
@@ -1692,17 +1698,18 @@ u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords) | |||
1692 | need_wrap &= ~1; | 1698 | need_wrap &= ~1; |
1693 | GEM_BUG_ON(need_wrap > ring->space); | 1699 | GEM_BUG_ON(need_wrap > ring->space); |
1694 | GEM_BUG_ON(ring->emit + need_wrap > ring->size); | 1700 | GEM_BUG_ON(ring->emit + need_wrap > ring->size); |
1701 | GEM_BUG_ON(!IS_ALIGNED(need_wrap, sizeof(u64))); | ||
1695 | 1702 | ||
1696 | /* Fill the tail with MI_NOOP */ | 1703 | /* Fill the tail with MI_NOOP */ |
1697 | memset(ring->vaddr + ring->emit, 0, need_wrap); | 1704 | memset64(ring->vaddr + ring->emit, 0, need_wrap / sizeof(u64)); |
1698 | ring->emit = 0; | ||
1699 | ring->space -= need_wrap; | 1705 | ring->space -= need_wrap; |
1706 | ring->emit = 0; | ||
1700 | } | 1707 | } |
1701 | 1708 | ||
1702 | GEM_BUG_ON(ring->emit > ring->size - bytes); | 1709 | GEM_BUG_ON(ring->emit > ring->size - bytes); |
1703 | GEM_BUG_ON(ring->space < bytes); | 1710 | GEM_BUG_ON(ring->space < bytes); |
1704 | cs = ring->vaddr + ring->emit; | 1711 | cs = ring->vaddr + ring->emit; |
1705 | GEM_DEBUG_EXEC(memset(cs, POISON_INUSE, bytes)); | 1712 | GEM_DEBUG_EXEC(memset32(cs, POISON_INUSE, bytes / sizeof(*cs))); |
1706 | ring->emit += bytes; | 1713 | ring->emit += bytes; |
1707 | ring->space -= bytes; | 1714 | ring->space -= bytes; |
1708 | 1715 | ||
@@ -1943,8 +1950,6 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, | |||
1943 | static void intel_ring_init_irq(struct drm_i915_private *dev_priv, | 1950 | static void intel_ring_init_irq(struct drm_i915_private *dev_priv, |
1944 | struct intel_engine_cs *engine) | 1951 | struct intel_engine_cs *engine) |
1945 | { | 1952 | { |
1946 | engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; | ||
1947 | |||
1948 | if (INTEL_GEN(dev_priv) >= 6) { | 1953 | if (INTEL_GEN(dev_priv) >= 6) { |
1949 | engine->irq_enable = gen6_irq_enable; | 1954 | engine->irq_enable = gen6_irq_enable; |
1950 | engine->irq_disable = gen6_irq_disable; | 1955 | engine->irq_disable = gen6_irq_disable; |
@@ -2029,6 +2034,8 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) | |||
2029 | if (HAS_L3_DPF(dev_priv)) | 2034 | if (HAS_L3_DPF(dev_priv)) |
2030 | engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; | 2035 | engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; |
2031 | 2036 | ||
2037 | engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; | ||
2038 | |||
2032 | if (INTEL_GEN(dev_priv) >= 6) { | 2039 | if (INTEL_GEN(dev_priv) >= 6) { |
2033 | engine->init_context = intel_rcs_ctx_init; | 2040 | engine->init_context = intel_rcs_ctx_init; |
2034 | engine->emit_flush = gen7_render_ring_flush; | 2041 | engine->emit_flush = gen7_render_ring_flush; |
@@ -2079,7 +2086,6 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) | |||
2079 | engine->emit_flush = gen6_bsd_ring_flush; | 2086 | engine->emit_flush = gen6_bsd_ring_flush; |
2080 | engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; | 2087 | engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; |
2081 | } else { | 2088 | } else { |
2082 | engine->mmio_base = BSD_RING_BASE; | ||
2083 | engine->emit_flush = bsd_ring_flush; | 2089 | engine->emit_flush = bsd_ring_flush; |
2084 | if (IS_GEN5(dev_priv)) | 2090 | if (IS_GEN5(dev_priv)) |
2085 | engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; | 2091 | engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 0320c2c4cfba..717041640135 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -7,9 +7,11 @@ | |||
7 | #include "i915_gem_batch_pool.h" | 7 | #include "i915_gem_batch_pool.h" |
8 | #include "i915_gem_timeline.h" | 8 | #include "i915_gem_timeline.h" |
9 | 9 | ||
10 | #include "i915_reg.h" | ||
10 | #include "i915_pmu.h" | 11 | #include "i915_pmu.h" |
11 | #include "i915_request.h" | 12 | #include "i915_request.h" |
12 | #include "i915_selftest.h" | 13 | #include "i915_selftest.h" |
14 | #include "intel_gpu_commands.h" | ||
13 | 15 | ||
14 | struct drm_printer; | 16 | struct drm_printer; |
15 | 17 | ||
@@ -84,7 +86,7 @@ hangcheck_action_to_str(const enum intel_engine_hangcheck_action a) | |||
84 | } | 86 | } |
85 | 87 | ||
86 | #define I915_MAX_SLICES 3 | 88 | #define I915_MAX_SLICES 3 |
87 | #define I915_MAX_SUBSLICES 3 | 89 | #define I915_MAX_SUBSLICES 8 |
88 | 90 | ||
89 | #define instdone_slice_mask(dev_priv__) \ | 91 | #define instdone_slice_mask(dev_priv__) \ |
90 | (INTEL_GEN(dev_priv__) == 7 ? \ | 92 | (INTEL_GEN(dev_priv__) == 7 ? \ |
@@ -330,7 +332,6 @@ struct intel_engine_cs { | |||
330 | u8 instance; | 332 | u8 instance; |
331 | u32 context_size; | 333 | u32 context_size; |
332 | u32 mmio_base; | 334 | u32 mmio_base; |
333 | unsigned int irq_shift; | ||
334 | 335 | ||
335 | struct intel_ring *buffer; | 336 | struct intel_ring *buffer; |
336 | struct intel_timeline *timeline; | 337 | struct intel_timeline *timeline; |
@@ -561,6 +562,7 @@ struct intel_engine_cs { | |||
561 | 562 | ||
562 | #define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) | 563 | #define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) |
563 | #define I915_ENGINE_SUPPORTS_STATS BIT(1) | 564 | #define I915_ENGINE_SUPPORTS_STATS BIT(1) |
565 | #define I915_ENGINE_HAS_PREEMPTION BIT(2) | ||
564 | unsigned int flags; | 566 | unsigned int flags; |
565 | 567 | ||
566 | /* | 568 | /* |
@@ -620,16 +622,29 @@ struct intel_engine_cs { | |||
620 | } stats; | 622 | } stats; |
621 | }; | 623 | }; |
622 | 624 | ||
623 | static inline bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) | 625 | static inline bool |
626 | intel_engine_needs_cmd_parser(const struct intel_engine_cs *engine) | ||
624 | { | 627 | { |
625 | return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; | 628 | return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; |
626 | } | 629 | } |
627 | 630 | ||
628 | static inline bool intel_engine_supports_stats(struct intel_engine_cs *engine) | 631 | static inline bool |
632 | intel_engine_supports_stats(const struct intel_engine_cs *engine) | ||
629 | { | 633 | { |
630 | return engine->flags & I915_ENGINE_SUPPORTS_STATS; | 634 | return engine->flags & I915_ENGINE_SUPPORTS_STATS; |
631 | } | 635 | } |
632 | 636 | ||
637 | static inline bool | ||
638 | intel_engine_has_preemption(const struct intel_engine_cs *engine) | ||
639 | { | ||
640 | return engine->flags & I915_ENGINE_HAS_PREEMPTION; | ||
641 | } | ||
642 | |||
643 | static inline bool __execlists_need_preempt(int prio, int last) | ||
644 | { | ||
645 | return prio > max(0, last); | ||
646 | } | ||
647 | |||
633 | static inline void | 648 | static inline void |
634 | execlists_set_active(struct intel_engine_execlists *execlists, | 649 | execlists_set_active(struct intel_engine_execlists *execlists, |
635 | unsigned int bit) | 650 | unsigned int bit) |
@@ -637,6 +652,13 @@ execlists_set_active(struct intel_engine_execlists *execlists, | |||
637 | __set_bit(bit, (unsigned long *)&execlists->active); | 652 | __set_bit(bit, (unsigned long *)&execlists->active); |
638 | } | 653 | } |
639 | 654 | ||
655 | static inline bool | ||
656 | execlists_set_active_once(struct intel_engine_execlists *execlists, | ||
657 | unsigned int bit) | ||
658 | { | ||
659 | return !__test_and_set_bit(bit, (unsigned long *)&execlists->active); | ||
660 | } | ||
661 | |||
640 | static inline void | 662 | static inline void |
641 | execlists_clear_active(struct intel_engine_execlists *execlists, | 663 | execlists_clear_active(struct intel_engine_execlists *execlists, |
642 | unsigned int bit) | 664 | unsigned int bit) |
@@ -651,6 +673,10 @@ execlists_is_active(const struct intel_engine_execlists *execlists, | |||
651 | return test_bit(bit, (unsigned long *)&execlists->active); | 673 | return test_bit(bit, (unsigned long *)&execlists->active); |
652 | } | 674 | } |
653 | 675 | ||
676 | void execlists_user_begin(struct intel_engine_execlists *execlists, | ||
677 | const struct execlist_port *port); | ||
678 | void execlists_user_end(struct intel_engine_execlists *execlists); | ||
679 | |||
654 | void | 680 | void |
655 | execlists_cancel_port_requests(struct intel_engine_execlists * const execlists); | 681 | execlists_cancel_port_requests(struct intel_engine_execlists * const execlists); |
656 | 682 | ||
@@ -663,7 +689,7 @@ execlists_num_ports(const struct intel_engine_execlists * const execlists) | |||
663 | return execlists->port_mask + 1; | 689 | return execlists->port_mask + 1; |
664 | } | 690 | } |
665 | 691 | ||
666 | static inline void | 692 | static inline struct execlist_port * |
667 | execlists_port_complete(struct intel_engine_execlists * const execlists, | 693 | execlists_port_complete(struct intel_engine_execlists * const execlists, |
668 | struct execlist_port * const port) | 694 | struct execlist_port * const port) |
669 | { | 695 | { |
@@ -674,6 +700,8 @@ execlists_port_complete(struct intel_engine_execlists * const execlists, | |||
674 | 700 | ||
675 | memmove(port, port + 1, m * sizeof(struct execlist_port)); | 701 | memmove(port, port + 1, m * sizeof(struct execlist_port)); |
676 | memset(port + m, 0, sizeof(struct execlist_port)); | 702 | memset(port + m, 0, sizeof(struct execlist_port)); |
703 | |||
704 | return port; | ||
677 | } | 705 | } |
678 | 706 | ||
679 | static inline unsigned int | 707 | static inline unsigned int |
@@ -857,9 +885,6 @@ static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine) | |||
857 | return READ_ONCE(engine->timeline->seqno); | 885 | return READ_ONCE(engine->timeline->seqno); |
858 | } | 886 | } |
859 | 887 | ||
860 | int init_workarounds_ring(struct intel_engine_cs *engine); | ||
861 | int intel_ring_workarounds_emit(struct i915_request *rq); | ||
862 | |||
863 | void intel_engine_get_instdone(struct intel_engine_cs *engine, | 888 | void intel_engine_get_instdone(struct intel_engine_cs *engine, |
864 | struct intel_instdone *instdone); | 889 | struct intel_instdone *instdone); |
865 | 890 | ||
@@ -939,7 +964,7 @@ bool intel_engine_add_wait(struct intel_engine_cs *engine, | |||
939 | struct intel_wait *wait); | 964 | struct intel_wait *wait); |
940 | void intel_engine_remove_wait(struct intel_engine_cs *engine, | 965 | void intel_engine_remove_wait(struct intel_engine_cs *engine, |
941 | struct intel_wait *wait); | 966 | struct intel_wait *wait); |
942 | void intel_engine_enable_signaling(struct i915_request *request, bool wakeup); | 967 | bool intel_engine_enable_signaling(struct i915_request *request, bool wakeup); |
943 | void intel_engine_cancel_signaling(struct i915_request *request); | 968 | void intel_engine_cancel_signaling(struct i915_request *request); |
944 | 969 | ||
945 | static inline bool intel_engine_has_waiter(const struct intel_engine_cs *engine) | 970 | static inline bool intel_engine_has_waiter(const struct intel_engine_cs *engine) |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index dbdcf85032df..aa1dfaa692b9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -48,6 +48,7 @@ bool intel_format_is_yuv(u32 format) | |||
48 | case DRM_FORMAT_UYVY: | 48 | case DRM_FORMAT_UYVY: |
49 | case DRM_FORMAT_VYUY: | 49 | case DRM_FORMAT_VYUY: |
50 | case DRM_FORMAT_YVYU: | 50 | case DRM_FORMAT_YVYU: |
51 | case DRM_FORMAT_NV12: | ||
51 | return true; | 52 | return true; |
52 | default: | 53 | default: |
53 | return false; | 54 | return false; |
@@ -946,6 +947,7 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
946 | int max_scale, min_scale; | 947 | int max_scale, min_scale; |
947 | bool can_scale; | 948 | bool can_scale; |
948 | int ret; | 949 | int ret; |
950 | uint32_t pixel_format = 0; | ||
949 | 951 | ||
950 | *src = drm_plane_state_src(&state->base); | 952 | *src = drm_plane_state_src(&state->base); |
951 | *dst = drm_plane_state_dest(&state->base); | 953 | *dst = drm_plane_state_dest(&state->base); |
@@ -969,11 +971,14 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
969 | 971 | ||
970 | /* setup can_scale, min_scale, max_scale */ | 972 | /* setup can_scale, min_scale, max_scale */ |
971 | if (INTEL_GEN(dev_priv) >= 9) { | 973 | if (INTEL_GEN(dev_priv) >= 9) { |
974 | if (state->base.fb) | ||
975 | pixel_format = state->base.fb->format->format; | ||
972 | /* use scaler when colorkey is not required */ | 976 | /* use scaler when colorkey is not required */ |
973 | if (!state->ckey.flags) { | 977 | if (!state->ckey.flags) { |
974 | can_scale = 1; | 978 | can_scale = 1; |
975 | min_scale = 1; | 979 | min_scale = 1; |
976 | max_scale = skl_max_scale(crtc, crtc_state); | 980 | max_scale = |
981 | skl_max_scale(crtc, crtc_state, pixel_format); | ||
977 | } else { | 982 | } else { |
978 | can_scale = 0; | 983 | can_scale = 0; |
979 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | 984 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index e5bf0d37bf43..1cffaf7b5dbe 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c | |||
@@ -69,13 +69,15 @@ static int __get_platform_enable_guc(struct drm_i915_private *dev_priv) | |||
69 | 69 | ||
70 | static int __get_default_guc_log_level(struct drm_i915_private *dev_priv) | 70 | static int __get_default_guc_log_level(struct drm_i915_private *dev_priv) |
71 | { | 71 | { |
72 | int guc_log_level = 0; /* disabled */ | 72 | int guc_log_level; |
73 | 73 | ||
74 | /* Enable if we're running on platform with GuC and debug config */ | 74 | if (!HAS_GUC(dev_priv) || !intel_uc_is_using_guc()) |
75 | if (HAS_GUC(dev_priv) && intel_uc_is_using_guc() && | 75 | guc_log_level = GUC_LOG_LEVEL_DISABLED; |
76 | (IS_ENABLED(CONFIG_DRM_I915_DEBUG) || | 76 | else if (IS_ENABLED(CONFIG_DRM_I915_DEBUG) || |
77 | IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))) | 77 | IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) |
78 | guc_log_level = 1 + GUC_LOG_VERBOSITY_MAX; | 78 | guc_log_level = GUC_LOG_LEVEL_MAX; |
79 | else | ||
80 | guc_log_level = GUC_LOG_LEVEL_NON_VERBOSE; | ||
79 | 81 | ||
80 | /* Any platform specific fine-tuning can be done here */ | 82 | /* Any platform specific fine-tuning can be done here */ |
81 | 83 | ||
@@ -83,7 +85,7 @@ static int __get_default_guc_log_level(struct drm_i915_private *dev_priv) | |||
83 | } | 85 | } |
84 | 86 | ||
85 | /** | 87 | /** |
86 | * intel_uc_sanitize_options - sanitize uC related modparam options | 88 | * sanitize_options_early - sanitize uC related modparam options |
87 | * @dev_priv: device private | 89 | * @dev_priv: device private |
88 | * | 90 | * |
89 | * In case of "enable_guc" option this function will attempt to modify | 91 | * In case of "enable_guc" option this function will attempt to modify |
@@ -99,7 +101,7 @@ static int __get_default_guc_log_level(struct drm_i915_private *dev_priv) | |||
99 | * unless GuC is enabled on given platform and the driver is compiled with | 101 | * unless GuC is enabled on given platform and the driver is compiled with |
100 | * debug config when this modparam will default to "enable(1..4)". | 102 | * debug config when this modparam will default to "enable(1..4)". |
101 | */ | 103 | */ |
102 | void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) | 104 | static void sanitize_options_early(struct drm_i915_private *dev_priv) |
103 | { | 105 | { |
104 | struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; | 106 | struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; |
105 | struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; | 107 | struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; |
@@ -142,51 +144,53 @@ void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) | |||
142 | i915_modparams.guc_log_level = 0; | 144 | i915_modparams.guc_log_level = 0; |
143 | } | 145 | } |
144 | 146 | ||
145 | if (i915_modparams.guc_log_level > 1 + GUC_LOG_VERBOSITY_MAX) { | 147 | if (i915_modparams.guc_log_level > GUC_LOG_LEVEL_MAX) { |
146 | DRM_WARN("Incompatible option detected: %s=%d, %s!\n", | 148 | DRM_WARN("Incompatible option detected: %s=%d, %s!\n", |
147 | "guc_log_level", i915_modparams.guc_log_level, | 149 | "guc_log_level", i915_modparams.guc_log_level, |
148 | "verbosity too high"); | 150 | "verbosity too high"); |
149 | i915_modparams.guc_log_level = 1 + GUC_LOG_VERBOSITY_MAX; | 151 | i915_modparams.guc_log_level = GUC_LOG_LEVEL_MAX; |
150 | } | 152 | } |
151 | 153 | ||
152 | DRM_DEBUG_DRIVER("guc_log_level=%d (enabled:%s verbosity:%d)\n", | 154 | DRM_DEBUG_DRIVER("guc_log_level=%d (enabled:%s, verbose:%s, verbosity:%d)\n", |
153 | i915_modparams.guc_log_level, | 155 | i915_modparams.guc_log_level, |
154 | yesno(i915_modparams.guc_log_level), | 156 | yesno(i915_modparams.guc_log_level), |
155 | i915_modparams.guc_log_level - 1); | 157 | yesno(GUC_LOG_LEVEL_IS_VERBOSE(i915_modparams.guc_log_level)), |
158 | GUC_LOG_LEVEL_TO_VERBOSITY(i915_modparams.guc_log_level)); | ||
156 | 159 | ||
157 | /* Make sure that sanitization was done */ | 160 | /* Make sure that sanitization was done */ |
158 | GEM_BUG_ON(i915_modparams.enable_guc < 0); | 161 | GEM_BUG_ON(i915_modparams.enable_guc < 0); |
159 | GEM_BUG_ON(i915_modparams.guc_log_level < 0); | 162 | GEM_BUG_ON(i915_modparams.guc_log_level < 0); |
160 | } | 163 | } |
161 | 164 | ||
162 | void intel_uc_init_early(struct drm_i915_private *dev_priv) | 165 | void intel_uc_init_early(struct drm_i915_private *i915) |
163 | { | 166 | { |
164 | intel_guc_init_early(&dev_priv->guc); | 167 | struct intel_guc *guc = &i915->guc; |
165 | intel_huc_init_early(&dev_priv->huc); | 168 | struct intel_huc *huc = &i915->huc; |
166 | } | ||
167 | 169 | ||
168 | void intel_uc_init_fw(struct drm_i915_private *dev_priv) | 170 | intel_guc_init_early(guc); |
169 | { | 171 | intel_huc_init_early(huc); |
170 | if (!USES_GUC(dev_priv)) | ||
171 | return; | ||
172 | 172 | ||
173 | if (USES_HUC(dev_priv)) | 173 | sanitize_options_early(i915); |
174 | intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw); | ||
175 | 174 | ||
176 | intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw); | 175 | if (USES_GUC(i915)) |
176 | intel_uc_fw_fetch(i915, &guc->fw); | ||
177 | |||
178 | if (USES_HUC(i915)) | ||
179 | intel_uc_fw_fetch(i915, &huc->fw); | ||
177 | } | 180 | } |
178 | 181 | ||
179 | void intel_uc_fini_fw(struct drm_i915_private *dev_priv) | 182 | void intel_uc_cleanup_early(struct drm_i915_private *i915) |
180 | { | 183 | { |
181 | if (!USES_GUC(dev_priv)) | 184 | struct intel_guc *guc = &i915->guc; |
182 | return; | 185 | struct intel_huc *huc = &i915->huc; |
183 | 186 | ||
184 | intel_uc_fw_fini(&dev_priv->guc.fw); | 187 | if (USES_HUC(i915)) |
188 | intel_uc_fw_fini(&huc->fw); | ||
185 | 189 | ||
186 | if (USES_HUC(dev_priv)) | 190 | if (USES_GUC(i915)) |
187 | intel_uc_fw_fini(&dev_priv->huc.fw); | 191 | intel_uc_fw_fini(&guc->fw); |
188 | 192 | ||
189 | guc_free_load_err_log(&dev_priv->guc); | 193 | guc_free_load_err_log(guc); |
190 | } | 194 | } |
191 | 195 | ||
192 | /** | 196 | /** |
@@ -223,10 +227,13 @@ static int guc_enable_communication(struct intel_guc *guc) | |||
223 | { | 227 | { |
224 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 228 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
225 | 229 | ||
230 | gen9_enable_guc_interrupts(dev_priv); | ||
231 | |||
226 | if (HAS_GUC_CT(dev_priv)) | 232 | if (HAS_GUC_CT(dev_priv)) |
227 | return intel_guc_enable_ct(guc); | 233 | return intel_guc_ct_enable(&guc->ct); |
228 | 234 | ||
229 | guc->send = intel_guc_send_mmio; | 235 | guc->send = intel_guc_send_mmio; |
236 | guc->handler = intel_guc_to_host_event_handler_mmio; | ||
230 | return 0; | 237 | return 0; |
231 | } | 238 | } |
232 | 239 | ||
@@ -235,9 +242,12 @@ static void guc_disable_communication(struct intel_guc *guc) | |||
235 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 242 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
236 | 243 | ||
237 | if (HAS_GUC_CT(dev_priv)) | 244 | if (HAS_GUC_CT(dev_priv)) |
238 | intel_guc_disable_ct(guc); | 245 | intel_guc_ct_disable(&guc->ct); |
246 | |||
247 | gen9_disable_guc_interrupts(dev_priv); | ||
239 | 248 | ||
240 | guc->send = intel_guc_send_nop; | 249 | guc->send = intel_guc_send_nop; |
250 | guc->handler = intel_guc_to_host_event_handler_nop; | ||
241 | } | 251 | } |
242 | 252 | ||
243 | int intel_uc_init_misc(struct drm_i915_private *dev_priv) | 253 | int intel_uc_init_misc(struct drm_i915_private *dev_priv) |
@@ -248,24 +258,13 @@ int intel_uc_init_misc(struct drm_i915_private *dev_priv) | |||
248 | if (!USES_GUC(dev_priv)) | 258 | if (!USES_GUC(dev_priv)) |
249 | return 0; | 259 | return 0; |
250 | 260 | ||
251 | ret = intel_guc_init_wq(guc); | 261 | intel_guc_init_ggtt_pin_bias(guc); |
252 | if (ret) { | ||
253 | DRM_ERROR("Couldn't allocate workqueues for GuC\n"); | ||
254 | goto err; | ||
255 | } | ||
256 | 262 | ||
257 | ret = intel_guc_log_relay_create(guc); | 263 | ret = intel_guc_init_wq(guc); |
258 | if (ret) { | 264 | if (ret) |
259 | DRM_ERROR("Couldn't allocate relay for GuC log\n"); | 265 | return ret; |
260 | goto err_relay; | ||
261 | } | ||
262 | 266 | ||
263 | return 0; | 267 | return 0; |
264 | |||
265 | err_relay: | ||
266 | intel_guc_fini_wq(guc); | ||
267 | err: | ||
268 | return ret; | ||
269 | } | 268 | } |
270 | 269 | ||
271 | void intel_uc_fini_misc(struct drm_i915_private *dev_priv) | 270 | void intel_uc_fini_misc(struct drm_i915_private *dev_priv) |
@@ -276,8 +275,6 @@ void intel_uc_fini_misc(struct drm_i915_private *dev_priv) | |||
276 | return; | 275 | return; |
277 | 276 | ||
278 | intel_guc_fini_wq(guc); | 277 | intel_guc_fini_wq(guc); |
279 | |||
280 | intel_guc_log_relay_destroy(guc); | ||
281 | } | 278 | } |
282 | 279 | ||
283 | int intel_uc_init(struct drm_i915_private *dev_priv) | 280 | int intel_uc_init(struct drm_i915_private *dev_priv) |
@@ -325,6 +322,24 @@ void intel_uc_fini(struct drm_i915_private *dev_priv) | |||
325 | intel_guc_fini(guc); | 322 | intel_guc_fini(guc); |
326 | } | 323 | } |
327 | 324 | ||
325 | void intel_uc_sanitize(struct drm_i915_private *i915) | ||
326 | { | ||
327 | struct intel_guc *guc = &i915->guc; | ||
328 | struct intel_huc *huc = &i915->huc; | ||
329 | |||
330 | if (!USES_GUC(i915)) | ||
331 | return; | ||
332 | |||
333 | GEM_BUG_ON(!HAS_GUC(i915)); | ||
334 | |||
335 | guc_disable_communication(guc); | ||
336 | |||
337 | intel_huc_sanitize(huc); | ||
338 | intel_guc_sanitize(guc); | ||
339 | |||
340 | __intel_uc_reset_hw(i915); | ||
341 | } | ||
342 | |||
328 | int intel_uc_init_hw(struct drm_i915_private *dev_priv) | 343 | int intel_uc_init_hw(struct drm_i915_private *dev_priv) |
329 | { | 344 | { |
330 | struct intel_guc *guc = &dev_priv->guc; | 345 | struct intel_guc *guc = &dev_priv->guc; |
@@ -336,14 +351,8 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
336 | 351 | ||
337 | GEM_BUG_ON(!HAS_GUC(dev_priv)); | 352 | GEM_BUG_ON(!HAS_GUC(dev_priv)); |
338 | 353 | ||
339 | guc_disable_communication(guc); | ||
340 | gen9_reset_guc_interrupts(dev_priv); | 354 | gen9_reset_guc_interrupts(dev_priv); |
341 | 355 | ||
342 | /* init WOPCM */ | ||
343 | I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv)); | ||
344 | I915_WRITE(DMA_GUC_WOPCM_OFFSET, | ||
345 | GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC); | ||
346 | |||
347 | /* WaEnableuKernelHeaderValidFix:skl */ | 356 | /* WaEnableuKernelHeaderValidFix:skl */ |
348 | /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */ | 357 | /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */ |
349 | if (IS_GEN9(dev_priv)) | 358 | if (IS_GEN9(dev_priv)) |
@@ -390,12 +399,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
390 | } | 399 | } |
391 | 400 | ||
392 | if (USES_GUC_SUBMISSION(dev_priv)) { | 401 | if (USES_GUC_SUBMISSION(dev_priv)) { |
393 | if (i915_modparams.guc_log_level) | ||
394 | gen9_enable_guc_interrupts(dev_priv); | ||
395 | |||
396 | ret = intel_guc_submission_enable(guc); | 402 | ret = intel_guc_submission_enable(guc); |
397 | if (ret) | 403 | if (ret) |
398 | goto err_interrupts; | 404 | goto err_communication; |
399 | } | 405 | } |
400 | 406 | ||
401 | dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n", | 407 | dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n", |
@@ -410,8 +416,6 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
410 | /* | 416 | /* |
411 | * We've failed to load the firmware :( | 417 | * We've failed to load the firmware :( |
412 | */ | 418 | */ |
413 | err_interrupts: | ||
414 | gen9_disable_guc_interrupts(dev_priv); | ||
415 | err_communication: | 419 | err_communication: |
416 | guc_disable_communication(guc); | 420 | guc_disable_communication(guc); |
417 | err_log_capture: | 421 | err_log_capture: |
@@ -441,9 +445,6 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv) | |||
441 | intel_guc_submission_disable(guc); | 445 | intel_guc_submission_disable(guc); |
442 | 446 | ||
443 | guc_disable_communication(guc); | 447 | guc_disable_communication(guc); |
444 | |||
445 | if (USES_GUC_SUBMISSION(dev_priv)) | ||
446 | gen9_disable_guc_interrupts(dev_priv); | ||
447 | } | 448 | } |
448 | 449 | ||
449 | int intel_uc_suspend(struct drm_i915_private *i915) | 450 | int intel_uc_suspend(struct drm_i915_private *i915) |
@@ -479,8 +480,7 @@ int intel_uc_resume(struct drm_i915_private *i915) | |||
479 | if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) | 480 | if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) |
480 | return 0; | 481 | return 0; |
481 | 482 | ||
482 | if (i915_modparams.guc_log_level) | 483 | gen9_enable_guc_interrupts(i915); |
483 | gen9_enable_guc_interrupts(i915); | ||
484 | 484 | ||
485 | err = intel_guc_resume(guc); | 485 | err = intel_guc_resume(guc); |
486 | if (err) { | 486 | if (err) { |
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index f76d51d1ce70..25d73ada74ae 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h | |||
@@ -28,13 +28,12 @@ | |||
28 | #include "intel_huc.h" | 28 | #include "intel_huc.h" |
29 | #include "i915_params.h" | 29 | #include "i915_params.h" |
30 | 30 | ||
31 | void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); | ||
32 | void intel_uc_init_early(struct drm_i915_private *dev_priv); | 31 | void intel_uc_init_early(struct drm_i915_private *dev_priv); |
32 | void intel_uc_cleanup_early(struct drm_i915_private *dev_priv); | ||
33 | void intel_uc_init_mmio(struct drm_i915_private *dev_priv); | 33 | void intel_uc_init_mmio(struct drm_i915_private *dev_priv); |
34 | void intel_uc_init_fw(struct drm_i915_private *dev_priv); | ||
35 | void intel_uc_fini_fw(struct drm_i915_private *dev_priv); | ||
36 | int intel_uc_init_misc(struct drm_i915_private *dev_priv); | 34 | int intel_uc_init_misc(struct drm_i915_private *dev_priv); |
37 | void intel_uc_fini_misc(struct drm_i915_private *dev_priv); | 35 | void intel_uc_fini_misc(struct drm_i915_private *dev_priv); |
36 | void intel_uc_sanitize(struct drm_i915_private *dev_priv); | ||
38 | int intel_uc_init_hw(struct drm_i915_private *dev_priv); | 37 | int intel_uc_init_hw(struct drm_i915_private *dev_priv); |
39 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv); | 38 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv); |
40 | int intel_uc_init(struct drm_i915_private *dev_priv); | 39 | int intel_uc_init(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c index 3ec0ce505b76..6e8e0b546743 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/intel_uc_fw.c | |||
@@ -95,15 +95,6 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, | |||
95 | uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; | 95 | uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; |
96 | uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); | 96 | uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); |
97 | 97 | ||
98 | /* Header and uCode will be loaded to WOPCM */ | ||
99 | size = uc_fw->header_size + uc_fw->ucode_size; | ||
100 | if (size > intel_guc_wopcm_size(dev_priv)) { | ||
101 | DRM_WARN("%s: Firmware is too large to fit in WOPCM\n", | ||
102 | intel_uc_fw_type_repr(uc_fw->type)); | ||
103 | err = -E2BIG; | ||
104 | goto fail; | ||
105 | } | ||
106 | |||
107 | /* now RSA */ | 98 | /* now RSA */ |
108 | if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) { | 99 | if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) { |
109 | DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n", | 100 | DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n", |
@@ -209,6 +200,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, | |||
209 | struct i915_vma *vma)) | 200 | struct i915_vma *vma)) |
210 | { | 201 | { |
211 | struct i915_vma *vma; | 202 | struct i915_vma *vma; |
203 | u32 ggtt_pin_bias; | ||
212 | int err; | 204 | int err; |
213 | 205 | ||
214 | DRM_DEBUG_DRIVER("%s fw load %s\n", | 206 | DRM_DEBUG_DRIVER("%s fw load %s\n", |
@@ -230,8 +222,9 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, | |||
230 | goto fail; | 222 | goto fail; |
231 | } | 223 | } |
232 | 224 | ||
225 | ggtt_pin_bias = to_i915(uc_fw->obj->base.dev)->guc.ggtt_pin_bias; | ||
233 | vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0, | 226 | vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0, |
234 | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); | 227 | PIN_OFFSET_BIAS | ggtt_pin_bias); |
235 | if (IS_ERR(vma)) { | 228 | if (IS_ERR(vma)) { |
236 | err = PTR_ERR(vma); | 229 | err = PTR_ERR(vma); |
237 | DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n", | 230 | DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n", |
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h index d5fd4609c785..dc33b12394de 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/intel_uc_fw.h | |||
@@ -115,6 +115,28 @@ static inline bool intel_uc_fw_is_selected(struct intel_uc_fw *uc_fw) | |||
115 | return uc_fw->path != NULL; | 115 | return uc_fw->path != NULL; |
116 | } | 116 | } |
117 | 117 | ||
118 | static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw) | ||
119 | { | ||
120 | if (uc_fw->load_status == INTEL_UC_FIRMWARE_SUCCESS) | ||
121 | uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * intel_uc_fw_get_upload_size() - Get size of firmware needed to be uploaded. | ||
126 | * @uc_fw: uC firmware. | ||
127 | * | ||
128 | * Get the size of the firmware and header that will be uploaded to WOPCM. | ||
129 | * | ||
130 | * Return: Upload firmware size, or zero on firmware fetch failure. | ||
131 | */ | ||
132 | static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) | ||
133 | { | ||
134 | if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS) | ||
135 | return 0; | ||
136 | |||
137 | return uc_fw->header_size + uc_fw->ucode_size; | ||
138 | } | ||
139 | |||
118 | void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, | 140 | void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, |
119 | struct intel_uc_fw *uc_fw); | 141 | struct intel_uc_fw *uc_fw); |
120 | int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, | 142 | int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, |
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 4df7c2ef8576..d6e20f0f4c28 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c | |||
@@ -62,6 +62,11 @@ static inline void | |||
62 | fw_domain_reset(struct drm_i915_private *i915, | 62 | fw_domain_reset(struct drm_i915_private *i915, |
63 | const struct intel_uncore_forcewake_domain *d) | 63 | const struct intel_uncore_forcewake_domain *d) |
64 | { | 64 | { |
65 | /* | ||
66 | * We don't really know if the powerwell for the forcewake domain we are | ||
67 | * trying to reset here does exist at this point (engines could be fused | ||
68 | * off in ICL+), so no waiting for acks | ||
69 | */ | ||
65 | __raw_i915_write32(i915, d->reg_set, i915->uncore.fw_reset); | 70 | __raw_i915_write32(i915, d->reg_set, i915->uncore.fw_reset); |
66 | } | 71 | } |
67 | 72 | ||
@@ -1353,6 +1358,23 @@ static void fw_domain_init(struct drm_i915_private *dev_priv, | |||
1353 | fw_domain_reset(dev_priv, d); | 1358 | fw_domain_reset(dev_priv, d); |
1354 | } | 1359 | } |
1355 | 1360 | ||
1361 | static void fw_domain_fini(struct drm_i915_private *dev_priv, | ||
1362 | enum forcewake_domain_id domain_id) | ||
1363 | { | ||
1364 | struct intel_uncore_forcewake_domain *d; | ||
1365 | |||
1366 | if (WARN_ON(domain_id >= FW_DOMAIN_ID_COUNT)) | ||
1367 | return; | ||
1368 | |||
1369 | d = &dev_priv->uncore.fw_domain[domain_id]; | ||
1370 | |||
1371 | WARN_ON(d->wake_count); | ||
1372 | WARN_ON(hrtimer_cancel(&d->timer)); | ||
1373 | memset(d, 0, sizeof(*d)); | ||
1374 | |||
1375 | dev_priv->uncore.fw_domains &= ~BIT(domain_id); | ||
1376 | } | ||
1377 | |||
1356 | static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | 1378 | static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) |
1357 | { | 1379 | { |
1358 | if (INTEL_GEN(dev_priv) <= 5 || intel_vgpu_active(dev_priv)) | 1380 | if (INTEL_GEN(dev_priv) <= 5 || intel_vgpu_active(dev_priv)) |
@@ -1565,6 +1587,40 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) | |||
1565 | &dev_priv->uncore.pmic_bus_access_nb); | 1587 | &dev_priv->uncore.pmic_bus_access_nb); |
1566 | } | 1588 | } |
1567 | 1589 | ||
1590 | /* | ||
1591 | * We might have detected that some engines are fused off after we initialized | ||
1592 | * the forcewake domains. Prune them, to make sure they only reference existing | ||
1593 | * engines. | ||
1594 | */ | ||
1595 | void intel_uncore_prune(struct drm_i915_private *dev_priv) | ||
1596 | { | ||
1597 | if (INTEL_GEN(dev_priv) >= 11) { | ||
1598 | enum forcewake_domains fw_domains = dev_priv->uncore.fw_domains; | ||
1599 | enum forcewake_domain_id domain_id; | ||
1600 | int i; | ||
1601 | |||
1602 | for (i = 0; i < I915_MAX_VCS; i++) { | ||
1603 | domain_id = FW_DOMAIN_ID_MEDIA_VDBOX0 + i; | ||
1604 | |||
1605 | if (HAS_ENGINE(dev_priv, _VCS(i))) | ||
1606 | continue; | ||
1607 | |||
1608 | if (fw_domains & BIT(domain_id)) | ||
1609 | fw_domain_fini(dev_priv, domain_id); | ||
1610 | } | ||
1611 | |||
1612 | for (i = 0; i < I915_MAX_VECS; i++) { | ||
1613 | domain_id = FW_DOMAIN_ID_MEDIA_VEBOX0 + i; | ||
1614 | |||
1615 | if (HAS_ENGINE(dev_priv, _VECS(i))) | ||
1616 | continue; | ||
1617 | |||
1618 | if (fw_domains & BIT(domain_id)) | ||
1619 | fw_domain_fini(dev_priv, domain_id); | ||
1620 | } | ||
1621 | } | ||
1622 | } | ||
1623 | |||
1568 | void intel_uncore_fini(struct drm_i915_private *dev_priv) | 1624 | void intel_uncore_fini(struct drm_i915_private *dev_priv) |
1569 | { | 1625 | { |
1570 | /* Paranoia: make sure we have disabled everything before we exit. */ | 1626 | /* Paranoia: make sure we have disabled everything before we exit. */ |
@@ -1646,11 +1702,10 @@ static void gen3_stop_engine(struct intel_engine_cs *engine) | |||
1646 | const i915_reg_t mode = RING_MI_MODE(base); | 1702 | const i915_reg_t mode = RING_MI_MODE(base); |
1647 | 1703 | ||
1648 | I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); | 1704 | I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); |
1649 | if (intel_wait_for_register_fw(dev_priv, | 1705 | if (__intel_wait_for_register_fw(dev_priv, |
1650 | mode, | 1706 | mode, MODE_IDLE, MODE_IDLE, |
1651 | MODE_IDLE, | 1707 | 500, 0, |
1652 | MODE_IDLE, | 1708 | NULL)) |
1653 | 500)) | ||
1654 | DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", | 1709 | DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", |
1655 | engine->name); | 1710 | engine->name); |
1656 | 1711 | ||
@@ -1804,9 +1859,10 @@ static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv, | |||
1804 | __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask); | 1859 | __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask); |
1805 | 1860 | ||
1806 | /* Wait for the device to ack the reset requests */ | 1861 | /* Wait for the device to ack the reset requests */ |
1807 | err = intel_wait_for_register_fw(dev_priv, | 1862 | err = __intel_wait_for_register_fw(dev_priv, |
1808 | GEN6_GDRST, hw_domain_mask, 0, | 1863 | GEN6_GDRST, hw_domain_mask, 0, |
1809 | 500); | 1864 | 500, 0, |
1865 | NULL); | ||
1810 | if (err) | 1866 | if (err) |
1811 | DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n", | 1867 | DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n", |
1812 | hw_domain_mask); | 1868 | hw_domain_mask); |
@@ -1854,6 +1910,50 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv, | |||
1854 | } | 1910 | } |
1855 | 1911 | ||
1856 | /** | 1912 | /** |
1913 | * gen11_reset_engines - reset individual engines | ||
1914 | * @dev_priv: i915 device | ||
1915 | * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset | ||
1916 | * | ||
1917 | * This function will reset the individual engines that are set in engine_mask. | ||
1918 | * If you provide ALL_ENGINES as mask, full global domain reset will be issued. | ||
1919 | * | ||
1920 | * Note: It is responsibility of the caller to handle the difference between | ||
1921 | * asking full domain reset versus reset for all available individual engines. | ||
1922 | * | ||
1923 | * Returns 0 on success, nonzero on error. | ||
1924 | */ | ||
1925 | static int gen11_reset_engines(struct drm_i915_private *dev_priv, | ||
1926 | unsigned engine_mask) | ||
1927 | { | ||
1928 | struct intel_engine_cs *engine; | ||
1929 | const u32 hw_engine_mask[I915_NUM_ENGINES] = { | ||
1930 | [RCS] = GEN11_GRDOM_RENDER, | ||
1931 | [BCS] = GEN11_GRDOM_BLT, | ||
1932 | [VCS] = GEN11_GRDOM_MEDIA, | ||
1933 | [VCS2] = GEN11_GRDOM_MEDIA2, | ||
1934 | [VCS3] = GEN11_GRDOM_MEDIA3, | ||
1935 | [VCS4] = GEN11_GRDOM_MEDIA4, | ||
1936 | [VECS] = GEN11_GRDOM_VECS, | ||
1937 | [VECS2] = GEN11_GRDOM_VECS2, | ||
1938 | }; | ||
1939 | u32 hw_mask; | ||
1940 | |||
1941 | BUILD_BUG_ON(VECS2 + 1 != I915_NUM_ENGINES); | ||
1942 | |||
1943 | if (engine_mask == ALL_ENGINES) { | ||
1944 | hw_mask = GEN11_GRDOM_FULL; | ||
1945 | } else { | ||
1946 | unsigned int tmp; | ||
1947 | |||
1948 | hw_mask = 0; | ||
1949 | for_each_engine_masked(engine, dev_priv, engine_mask, tmp) | ||
1950 | hw_mask |= hw_engine_mask[engine->id]; | ||
1951 | } | ||
1952 | |||
1953 | return gen6_hw_domain_reset(dev_priv, hw_mask); | ||
1954 | } | ||
1955 | |||
1956 | /** | ||
1857 | * __intel_wait_for_register_fw - wait until register matches expected state | 1957 | * __intel_wait_for_register_fw - wait until register matches expected state |
1858 | * @dev_priv: the i915 device | 1958 | * @dev_priv: the i915 device |
1859 | * @reg: the register to read | 1959 | * @reg: the register to read |
@@ -1940,7 +2040,7 @@ int __intel_wait_for_register(struct drm_i915_private *dev_priv, | |||
1940 | u32 reg_value; | 2040 | u32 reg_value; |
1941 | int ret; | 2041 | int ret; |
1942 | 2042 | ||
1943 | might_sleep(); | 2043 | might_sleep_if(slow_timeout_ms); |
1944 | 2044 | ||
1945 | spin_lock_irq(&dev_priv->uncore.lock); | 2045 | spin_lock_irq(&dev_priv->uncore.lock); |
1946 | intel_uncore_forcewake_get__locked(dev_priv, fw); | 2046 | intel_uncore_forcewake_get__locked(dev_priv, fw); |
@@ -1952,7 +2052,7 @@ int __intel_wait_for_register(struct drm_i915_private *dev_priv, | |||
1952 | intel_uncore_forcewake_put__locked(dev_priv, fw); | 2052 | intel_uncore_forcewake_put__locked(dev_priv, fw); |
1953 | spin_unlock_irq(&dev_priv->uncore.lock); | 2053 | spin_unlock_irq(&dev_priv->uncore.lock); |
1954 | 2054 | ||
1955 | if (ret) | 2055 | if (ret && slow_timeout_ms) |
1956 | ret = __wait_for(reg_value = I915_READ_NOTRACE(reg), | 2056 | ret = __wait_for(reg_value = I915_READ_NOTRACE(reg), |
1957 | (reg_value & mask) == value, | 2057 | (reg_value & mask) == value, |
1958 | slow_timeout_ms * 1000, 10, 1000); | 2058 | slow_timeout_ms * 1000, 10, 1000); |
@@ -1971,11 +2071,12 @@ static int gen8_reset_engine_start(struct intel_engine_cs *engine) | |||
1971 | I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), | 2071 | I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), |
1972 | _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); | 2072 | _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); |
1973 | 2073 | ||
1974 | ret = intel_wait_for_register_fw(dev_priv, | 2074 | ret = __intel_wait_for_register_fw(dev_priv, |
1975 | RING_RESET_CTL(engine->mmio_base), | 2075 | RING_RESET_CTL(engine->mmio_base), |
1976 | RESET_CTL_READY_TO_RESET, | 2076 | RESET_CTL_READY_TO_RESET, |
1977 | RESET_CTL_READY_TO_RESET, | 2077 | RESET_CTL_READY_TO_RESET, |
1978 | 700); | 2078 | 700, 0, |
2079 | NULL); | ||
1979 | if (ret) | 2080 | if (ret) |
1980 | DRM_ERROR("%s: reset request timeout\n", engine->name); | 2081 | DRM_ERROR("%s: reset request timeout\n", engine->name); |
1981 | 2082 | ||
@@ -2000,7 +2101,10 @@ static int gen8_reset_engines(struct drm_i915_private *dev_priv, | |||
2000 | if (gen8_reset_engine_start(engine)) | 2101 | if (gen8_reset_engine_start(engine)) |
2001 | goto not_ready; | 2102 | goto not_ready; |
2002 | 2103 | ||
2003 | return gen6_reset_engines(dev_priv, engine_mask); | 2104 | if (INTEL_GEN(dev_priv) >= 11) |
2105 | return gen11_reset_engines(dev_priv, engine_mask); | ||
2106 | else | ||
2107 | return gen6_reset_engines(dev_priv, engine_mask); | ||
2004 | 2108 | ||
2005 | not_ready: | 2109 | not_ready: |
2006 | for_each_engine_masked(engine, dev_priv, engine_mask, tmp) | 2110 | for_each_engine_masked(engine, dev_priv, engine_mask, tmp) |
@@ -2038,15 +2142,31 @@ int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) | |||
2038 | int retry; | 2142 | int retry; |
2039 | int ret; | 2143 | int ret; |
2040 | 2144 | ||
2041 | might_sleep(); | 2145 | /* |
2146 | * We want to perform per-engine reset from atomic context (e.g. | ||
2147 | * softirq), which imposes the constraint that we cannot sleep. | ||
2148 | * However, experience suggests that spending a bit of time waiting | ||
2149 | * for a reset helps in various cases, so for a full-device reset | ||
2150 | * we apply the opposite rule and wait if we want to. As we should | ||
2151 | * always follow up a failed per-engine reset with a full device reset, | ||
2152 | * being a little faster, stricter and more error prone for the | ||
2153 | * atomic case seems an acceptable compromise. | ||
2154 | * | ||
2155 | * Unfortunately this leads to a bimodal routine, when the goal was | ||
2156 | * to have a single reset function that worked for resetting any | ||
2157 | * number of engines simultaneously. | ||
2158 | */ | ||
2159 | might_sleep_if(engine_mask == ALL_ENGINES); | ||
2042 | 2160 | ||
2043 | /* If the power well sleeps during the reset, the reset | 2161 | /* |
2162 | * If the power well sleeps during the reset, the reset | ||
2044 | * request may be dropped and never completes (causing -EIO). | 2163 | * request may be dropped and never completes (causing -EIO). |
2045 | */ | 2164 | */ |
2046 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 2165 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
2047 | for (retry = 0; retry < 3; retry++) { | 2166 | for (retry = 0; retry < 3; retry++) { |
2048 | 2167 | ||
2049 | /* We stop engines, otherwise we might get failed reset and a | 2168 | /* |
2169 | * We stop engines, otherwise we might get failed reset and a | ||
2050 | * dead gpu (on elk). Also as modern gpu as kbl can suffer | 2170 | * dead gpu (on elk). Also as modern gpu as kbl can suffer |
2051 | * from system hang if batchbuffer is progressing when | 2171 | * from system hang if batchbuffer is progressing when |
2052 | * the reset is issued, regardless of READY_TO_RESET ack. | 2172 | * the reset is issued, regardless of READY_TO_RESET ack. |
@@ -2060,9 +2180,11 @@ int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) | |||
2060 | i915_stop_engines(dev_priv, engine_mask); | 2180 | i915_stop_engines(dev_priv, engine_mask); |
2061 | 2181 | ||
2062 | ret = -ENODEV; | 2182 | ret = -ENODEV; |
2063 | if (reset) | 2183 | if (reset) { |
2184 | GEM_TRACE("engine_mask=%x\n", engine_mask); | ||
2064 | ret = reset(dev_priv, engine_mask); | 2185 | ret = reset(dev_priv, engine_mask); |
2065 | if (ret != -ETIMEDOUT) | 2186 | } |
2187 | if (ret != -ETIMEDOUT || engine_mask != ALL_ENGINES) | ||
2066 | break; | 2188 | break; |
2067 | 2189 | ||
2068 | cond_resched(); | 2190 | cond_resched(); |
@@ -2085,12 +2207,14 @@ bool intel_has_reset_engine(struct drm_i915_private *dev_priv) | |||
2085 | 2207 | ||
2086 | int intel_reset_guc(struct drm_i915_private *dev_priv) | 2208 | int intel_reset_guc(struct drm_i915_private *dev_priv) |
2087 | { | 2209 | { |
2210 | u32 guc_domain = INTEL_GEN(dev_priv) >= 11 ? GEN11_GRDOM_GUC : | ||
2211 | GEN9_GRDOM_GUC; | ||
2088 | int ret; | 2212 | int ret; |
2089 | 2213 | ||
2090 | GEM_BUG_ON(!HAS_GUC(dev_priv)); | 2214 | GEM_BUG_ON(!HAS_GUC(dev_priv)); |
2091 | 2215 | ||
2092 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 2216 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
2093 | ret = gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC); | 2217 | ret = gen6_hw_domain_reset(dev_priv, guc_domain); |
2094 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); | 2218 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
2095 | 2219 | ||
2096 | return ret; | 2220 | return ret; |
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index dfdf444e4bcc..47478d609630 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h | |||
@@ -140,6 +140,7 @@ struct intel_uncore { | |||
140 | 140 | ||
141 | void intel_uncore_sanitize(struct drm_i915_private *dev_priv); | 141 | void intel_uncore_sanitize(struct drm_i915_private *dev_priv); |
142 | void intel_uncore_init(struct drm_i915_private *dev_priv); | 142 | void intel_uncore_init(struct drm_i915_private *dev_priv); |
143 | void intel_uncore_prune(struct drm_i915_private *dev_priv); | ||
143 | bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); | 144 | bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); |
144 | bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); | 145 | bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); |
145 | void intel_uncore_fini(struct drm_i915_private *dev_priv); | 146 | void intel_uncore_fini(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c new file mode 100644 index 000000000000..74bf76f3fddc --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wopcm.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2017-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "intel_wopcm.h" | ||
8 | #include "i915_drv.h" | ||
9 | |||
10 | /** | ||
11 | * DOC: WOPCM Layout | ||
12 | * | ||
13 | * The layout of the WOPCM will be fixed after writing to GuC WOPCM size and | ||
14 | * offset registers whose values are calculated and determined by HuC/GuC | ||
15 | * firmware size and set of hardware requirements/restrictions as shown below: | ||
16 | * | ||
17 | * :: | ||
18 | * | ||
19 | * +=========> +====================+ <== WOPCM Top | ||
20 | * ^ | HW contexts RSVD | | ||
21 | * | +===> +====================+ <== GuC WOPCM Top | ||
22 | * | ^ | | | ||
23 | * | | | | | ||
24 | * | | | | | ||
25 | * | GuC | | | ||
26 | * | WOPCM | | | ||
27 | * | Size +--------------------+ | ||
28 | * WOPCM | | GuC FW RSVD | | ||
29 | * | | +--------------------+ | ||
30 | * | | | GuC Stack RSVD | | ||
31 | * | | +------------------- + | ||
32 | * | v | GuC WOPCM RSVD | | ||
33 | * | +===> +====================+ <== GuC WOPCM base | ||
34 | * | | WOPCM RSVD | | ||
35 | * | +------------------- + <== HuC Firmware Top | ||
36 | * v | HuC FW | | ||
37 | * +=========> +====================+ <== WOPCM Base | ||
38 | * | ||
39 | * GuC accessible WOPCM starts at GuC WOPCM base and ends at GuC WOPCM top. | ||
40 | * The top part of the WOPCM is reserved for hardware contexts (e.g. RC6 | ||
41 | * context). | ||
42 | */ | ||
43 | |||
44 | /* Default WOPCM size 1MB. */ | ||
45 | #define GEN9_WOPCM_SIZE (1024 * 1024) | ||
46 | /* 16KB WOPCM (RSVD WOPCM) is reserved from HuC firmware top. */ | ||
47 | #define WOPCM_RESERVED_SIZE (16 * 1024) | ||
48 | |||
49 | /* 16KB reserved at the beginning of GuC WOPCM. */ | ||
50 | #define GUC_WOPCM_RESERVED (16 * 1024) | ||
51 | /* 8KB from GUC_WOPCM_RESERVED is reserved for GuC stack. */ | ||
52 | #define GUC_WOPCM_STACK_RESERVED (8 * 1024) | ||
53 | |||
54 | /* GuC WOPCM Offset value needs to be aligned to 16KB. */ | ||
55 | #define GUC_WOPCM_OFFSET_ALIGNMENT (1UL << GUC_WOPCM_OFFSET_SHIFT) | ||
56 | |||
57 | /* 24KB at the end of WOPCM is reserved for RC6 CTX on BXT. */ | ||
58 | #define BXT_WOPCM_RC6_CTX_RESERVED (24 * 1024) | ||
59 | /* 36KB WOPCM reserved at the end of WOPCM on CNL. */ | ||
60 | #define CNL_WOPCM_HW_CTX_RESERVED (36 * 1024) | ||
61 | |||
62 | /* 128KB from GUC_WOPCM_RESERVED is reserved for FW on Gen9. */ | ||
63 | #define GEN9_GUC_FW_RESERVED (128 * 1024) | ||
64 | #define GEN9_GUC_WOPCM_OFFSET (GUC_WOPCM_RESERVED + GEN9_GUC_FW_RESERVED) | ||
65 | |||
66 | /** | ||
67 | * intel_wopcm_init_early() - Early initialization of the WOPCM. | ||
68 | * @wopcm: pointer to intel_wopcm. | ||
69 | * | ||
70 | * Setup the size of WOPCM which will be used by later on WOPCM partitioning. | ||
71 | */ | ||
72 | void intel_wopcm_init_early(struct intel_wopcm *wopcm) | ||
73 | { | ||
74 | wopcm->size = GEN9_WOPCM_SIZE; | ||
75 | |||
76 | DRM_DEBUG_DRIVER("WOPCM size: %uKiB\n", wopcm->size / 1024); | ||
77 | } | ||
78 | |||
79 | static inline u32 context_reserved_size(struct drm_i915_private *i915) | ||
80 | { | ||
81 | if (IS_GEN9_LP(i915)) | ||
82 | return BXT_WOPCM_RC6_CTX_RESERVED; | ||
83 | else if (INTEL_GEN(i915) >= 10) | ||
84 | return CNL_WOPCM_HW_CTX_RESERVED; | ||
85 | else | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int gen9_check_dword_gap(u32 guc_wopcm_base, u32 guc_wopcm_size) | ||
90 | { | ||
91 | u32 offset; | ||
92 | |||
93 | /* | ||
94 | * GuC WOPCM size shall be at least a dword larger than the offset from | ||
95 | * WOPCM base (GuC WOPCM offset from WOPCM base + GEN9_GUC_WOPCM_OFFSET) | ||
96 | * due to hardware limitation on Gen9. | ||
97 | */ | ||
98 | offset = guc_wopcm_base + GEN9_GUC_WOPCM_OFFSET; | ||
99 | if (offset > guc_wopcm_size || | ||
100 | (guc_wopcm_size - offset) < sizeof(u32)) { | ||
101 | DRM_ERROR("GuC WOPCM size %uKiB is too small. %uKiB needed.\n", | ||
102 | guc_wopcm_size / 1024, | ||
103 | (u32)(offset + sizeof(u32)) / 1024); | ||
104 | return -E2BIG; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static inline int gen9_check_huc_fw_fits(u32 guc_wopcm_size, u32 huc_fw_size) | ||
111 | { | ||
112 | /* | ||
113 | * On Gen9 & CNL A0, hardware requires the total available GuC WOPCM | ||
114 | * size to be larger than or equal to HuC firmware size. Otherwise, | ||
115 | * firmware uploading would fail. | ||
116 | */ | ||
117 | if (huc_fw_size > guc_wopcm_size - GUC_WOPCM_RESERVED) { | ||
118 | DRM_ERROR("HuC FW (%uKiB) won't fit in GuC WOPCM (%uKiB).\n", | ||
119 | huc_fw_size / 1024, | ||
120 | (guc_wopcm_size - GUC_WOPCM_RESERVED) / 1024); | ||
121 | return -E2BIG; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static inline int check_hw_restriction(struct drm_i915_private *i915, | ||
128 | u32 guc_wopcm_base, u32 guc_wopcm_size, | ||
129 | u32 huc_fw_size) | ||
130 | { | ||
131 | int err = 0; | ||
132 | |||
133 | if (IS_GEN9(i915)) | ||
134 | err = gen9_check_dword_gap(guc_wopcm_base, guc_wopcm_size); | ||
135 | |||
136 | if (!err && | ||
137 | (IS_GEN9(i915) || IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0))) | ||
138 | err = gen9_check_huc_fw_fits(guc_wopcm_size, huc_fw_size); | ||
139 | |||
140 | return err; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * intel_wopcm_init() - Initialize the WOPCM structure. | ||
145 | * @wopcm: pointer to intel_wopcm. | ||
146 | * | ||
147 | * This function will partition WOPCM space based on GuC and HuC firmware sizes | ||
148 | * and will allocate max remaining for use by GuC. This function will also | ||
149 | * enforce platform dependent hardware restrictions on GuC WOPCM offset and | ||
150 | * size. It will fail the WOPCM init if any of these checks were failed, so that | ||
151 | * the following GuC firmware uploading would be aborted. | ||
152 | * | ||
153 | * Return: 0 on success, non-zero error code on failure. | ||
154 | */ | ||
155 | int intel_wopcm_init(struct intel_wopcm *wopcm) | ||
156 | { | ||
157 | struct drm_i915_private *i915 = wopcm_to_i915(wopcm); | ||
158 | u32 guc_fw_size = intel_uc_fw_get_upload_size(&i915->guc.fw); | ||
159 | u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw); | ||
160 | u32 ctx_rsvd = context_reserved_size(i915); | ||
161 | u32 guc_wopcm_base; | ||
162 | u32 guc_wopcm_size; | ||
163 | u32 guc_wopcm_rsvd; | ||
164 | int err; | ||
165 | |||
166 | GEM_BUG_ON(!wopcm->size); | ||
167 | |||
168 | if (guc_fw_size >= wopcm->size) { | ||
169 | DRM_ERROR("GuC FW (%uKiB) is too big to fit in WOPCM.", | ||
170 | guc_fw_size / 1024); | ||
171 | return -E2BIG; | ||
172 | } | ||
173 | |||
174 | if (huc_fw_size >= wopcm->size) { | ||
175 | DRM_ERROR("HuC FW (%uKiB) is too big to fit in WOPCM.", | ||
176 | huc_fw_size / 1024); | ||
177 | return -E2BIG; | ||
178 | } | ||
179 | |||
180 | guc_wopcm_base = ALIGN(huc_fw_size + WOPCM_RESERVED_SIZE, | ||
181 | GUC_WOPCM_OFFSET_ALIGNMENT); | ||
182 | if ((guc_wopcm_base + ctx_rsvd) >= wopcm->size) { | ||
183 | DRM_ERROR("GuC WOPCM base (%uKiB) is too big.\n", | ||
184 | guc_wopcm_base / 1024); | ||
185 | return -E2BIG; | ||
186 | } | ||
187 | |||
188 | guc_wopcm_size = wopcm->size - guc_wopcm_base - ctx_rsvd; | ||
189 | guc_wopcm_size &= GUC_WOPCM_SIZE_MASK; | ||
190 | |||
191 | DRM_DEBUG_DRIVER("Calculated GuC WOPCM Region: [%uKiB, %uKiB)\n", | ||
192 | guc_wopcm_base / 1024, guc_wopcm_size / 1024); | ||
193 | |||
194 | guc_wopcm_rsvd = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED; | ||
195 | if ((guc_fw_size + guc_wopcm_rsvd) > guc_wopcm_size) { | ||
196 | DRM_ERROR("Need %uKiB WOPCM for GuC, %uKiB available.\n", | ||
197 | (guc_fw_size + guc_wopcm_rsvd) / 1024, | ||
198 | guc_wopcm_size / 1024); | ||
199 | return -E2BIG; | ||
200 | } | ||
201 | |||
202 | err = check_hw_restriction(i915, guc_wopcm_base, guc_wopcm_size, | ||
203 | huc_fw_size); | ||
204 | if (err) | ||
205 | return err; | ||
206 | |||
207 | wopcm->guc.base = guc_wopcm_base; | ||
208 | wopcm->guc.size = guc_wopcm_size; | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static inline int write_and_verify(struct drm_i915_private *dev_priv, | ||
214 | i915_reg_t reg, u32 val, u32 mask, | ||
215 | u32 locked_bit) | ||
216 | { | ||
217 | u32 reg_val; | ||
218 | |||
219 | GEM_BUG_ON(val & ~mask); | ||
220 | |||
221 | I915_WRITE(reg, val); | ||
222 | |||
223 | reg_val = I915_READ(reg); | ||
224 | |||
225 | return (reg_val & mask) != (val | locked_bit) ? -EIO : 0; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * intel_wopcm_init_hw() - Setup GuC WOPCM registers. | ||
230 | * @wopcm: pointer to intel_wopcm. | ||
231 | * | ||
232 | * Setup the GuC WOPCM size and offset registers with the calculated values. It | ||
233 | * will verify the register values to make sure the registers are locked with | ||
234 | * correct values. | ||
235 | * | ||
236 | * Return: 0 on success. -EIO if registers were locked with incorrect values. | ||
237 | */ | ||
238 | int intel_wopcm_init_hw(struct intel_wopcm *wopcm) | ||
239 | { | ||
240 | struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm); | ||
241 | u32 huc_agent; | ||
242 | u32 mask; | ||
243 | int err; | ||
244 | |||
245 | if (!USES_GUC(dev_priv)) | ||
246 | return 0; | ||
247 | |||
248 | GEM_BUG_ON(!HAS_GUC(dev_priv)); | ||
249 | GEM_BUG_ON(!wopcm->guc.size); | ||
250 | GEM_BUG_ON(!wopcm->guc.base); | ||
251 | |||
252 | err = write_and_verify(dev_priv, GUC_WOPCM_SIZE, wopcm->guc.size, | ||
253 | GUC_WOPCM_SIZE_MASK | GUC_WOPCM_SIZE_LOCKED, | ||
254 | GUC_WOPCM_SIZE_LOCKED); | ||
255 | if (err) | ||
256 | goto err_out; | ||
257 | |||
258 | huc_agent = USES_HUC(dev_priv) ? HUC_LOADING_AGENT_GUC : 0; | ||
259 | mask = GUC_WOPCM_OFFSET_MASK | GUC_WOPCM_OFFSET_VALID | huc_agent; | ||
260 | err = write_and_verify(dev_priv, DMA_GUC_WOPCM_OFFSET, | ||
261 | wopcm->guc.base | huc_agent, mask, | ||
262 | GUC_WOPCM_OFFSET_VALID); | ||
263 | if (err) | ||
264 | goto err_out; | ||
265 | |||
266 | return 0; | ||
267 | |||
268 | err_out: | ||
269 | DRM_ERROR("Failed to init WOPCM registers:\n"); | ||
270 | DRM_ERROR("DMA_GUC_WOPCM_OFFSET=%#x\n", | ||
271 | I915_READ(DMA_GUC_WOPCM_OFFSET)); | ||
272 | DRM_ERROR("GUC_WOPCM_SIZE=%#x\n", I915_READ(GUC_WOPCM_SIZE)); | ||
273 | |||
274 | return err; | ||
275 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_wopcm.h b/drivers/gpu/drm/i915/intel_wopcm.h new file mode 100644 index 000000000000..6298910a384c --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wopcm.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2017-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef _INTEL_WOPCM_H_ | ||
8 | #define _INTEL_WOPCM_H_ | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | |||
12 | /** | ||
13 | * struct intel_wopcm - Overall WOPCM info and WOPCM regions. | ||
14 | * @size: Size of overall WOPCM. | ||
15 | * @guc: GuC WOPCM Region info. | ||
16 | * @guc.base: GuC WOPCM base which is offset from WOPCM base. | ||
17 | * @guc.size: Size of the GuC WOPCM region. | ||
18 | */ | ||
19 | struct intel_wopcm { | ||
20 | u32 size; | ||
21 | struct { | ||
22 | u32 base; | ||
23 | u32 size; | ||
24 | } guc; | ||
25 | }; | ||
26 | |||
27 | void intel_wopcm_init_early(struct intel_wopcm *wopcm); | ||
28 | int intel_wopcm_init(struct intel_wopcm *wopcm); | ||
29 | int intel_wopcm_init_hw(struct intel_wopcm *wopcm); | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c new file mode 100644 index 000000000000..bbbf4ed4aa97 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_workarounds.c | |||
@@ -0,0 +1,856 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2014-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "i915_drv.h" | ||
8 | #include "intel_workarounds.h" | ||
9 | |||
10 | /** | ||
11 | * DOC: Hardware workarounds | ||
12 | * | ||
13 | * This file is intended as a central place to implement most [1]_ of the | ||
14 | * required workarounds for hardware to work as originally intended. They fall | ||
15 | * in five basic categories depending on how/when they are applied: | ||
16 | * | ||
17 | * - Workarounds that touch registers that are saved/restored to/from the HW | ||
18 | * context image. The list is emitted (via Load Register Immediate commands) | ||
19 | * everytime a new context is created. | ||
20 | * - GT workarounds. The list of these WAs is applied whenever these registers | ||
21 | * revert to default values (on GPU reset, suspend/resume [2]_, etc..). | ||
22 | * - Display workarounds. The list is applied during display clock-gating | ||
23 | * initialization. | ||
24 | * - Workarounds that whitelist a privileged register, so that UMDs can manage | ||
25 | * them directly. This is just a special case of a MMMIO workaround (as we | ||
26 | * write the list of these to/be-whitelisted registers to some special HW | ||
27 | * registers). | ||
28 | * - Workaround batchbuffers, that get executed automatically by the hardware | ||
29 | * on every HW context restore. | ||
30 | * | ||
31 | * .. [1] Please notice that there are other WAs that, due to their nature, | ||
32 | * cannot be applied from a central place. Those are peppered around the rest | ||
33 | * of the code, as needed. | ||
34 | * | ||
35 | * .. [2] Technically, some registers are powercontext saved & restored, so they | ||
36 | * survive a suspend/resume. In practice, writing them again is not too | ||
37 | * costly and simplifies things. We can revisit this in the future. | ||
38 | * | ||
39 | * Layout | ||
40 | * '''''' | ||
41 | * | ||
42 | * Keep things in this file ordered by WA type, as per the above (context, GT, | ||
43 | * display, register whitelist, batchbuffer). Then, inside each type, keep the | ||
44 | * following order: | ||
45 | * | ||
46 | * - Infrastructure functions and macros | ||
47 | * - WAs per platform in standard gen/chrono order | ||
48 | * - Public functions to init or apply the given workaround type. | ||
49 | */ | ||
50 | |||
51 | static int wa_add(struct drm_i915_private *dev_priv, | ||
52 | i915_reg_t addr, | ||
53 | const u32 mask, const u32 val) | ||
54 | { | ||
55 | const unsigned int idx = dev_priv->workarounds.count; | ||
56 | |||
57 | if (WARN_ON(idx >= I915_MAX_WA_REGS)) | ||
58 | return -ENOSPC; | ||
59 | |||
60 | dev_priv->workarounds.reg[idx].addr = addr; | ||
61 | dev_priv->workarounds.reg[idx].value = val; | ||
62 | dev_priv->workarounds.reg[idx].mask = mask; | ||
63 | |||
64 | dev_priv->workarounds.count++; | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | #define WA_REG(addr, mask, val) do { \ | ||
70 | const int r = wa_add(dev_priv, (addr), (mask), (val)); \ | ||
71 | if (r) \ | ||
72 | return r; \ | ||
73 | } while (0) | ||
74 | |||
75 | #define WA_SET_BIT_MASKED(addr, mask) \ | ||
76 | WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) | ||
77 | |||
78 | #define WA_CLR_BIT_MASKED(addr, mask) \ | ||
79 | WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) | ||
80 | |||
81 | #define WA_SET_FIELD_MASKED(addr, mask, value) \ | ||
82 | WA_REG(addr, (mask), _MASKED_FIELD(mask, value)) | ||
83 | |||
84 | static int gen8_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
85 | { | ||
86 | WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); | ||
87 | |||
88 | /* WaDisableAsyncFlipPerfMode:bdw,chv */ | ||
89 | WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); | ||
90 | |||
91 | /* WaDisablePartialInstShootdown:bdw,chv */ | ||
92 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
93 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); | ||
94 | |||
95 | /* Use Force Non-Coherent whenever executing a 3D context. This is a | ||
96 | * workaround for for a possible hang in the unlikely event a TLB | ||
97 | * invalidation occurs during a PSD flush. | ||
98 | */ | ||
99 | /* WaForceEnableNonCoherent:bdw,chv */ | ||
100 | /* WaHdcDisableFetchWhenMasked:bdw,chv */ | ||
101 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
102 | HDC_DONOT_FETCH_MEM_WHEN_MASKED | | ||
103 | HDC_FORCE_NON_COHERENT); | ||
104 | |||
105 | /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: | ||
106 | * "The Hierarchical Z RAW Stall Optimization allows non-overlapping | ||
107 | * polygons in the same 8x4 pixel/sample area to be processed without | ||
108 | * stalling waiting for the earlier ones to write to Hierarchical Z | ||
109 | * buffer." | ||
110 | * | ||
111 | * This optimization is off by default for BDW and CHV; turn it on. | ||
112 | */ | ||
113 | WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); | ||
114 | |||
115 | /* Wa4x4STCOptimizationDisable:bdw,chv */ | ||
116 | WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); | ||
117 | |||
118 | /* | ||
119 | * BSpec recommends 8x4 when MSAA is used, | ||
120 | * however in practice 16x4 seems fastest. | ||
121 | * | ||
122 | * Note that PS/WM thread counts depend on the WIZ hashing | ||
123 | * disable bit, which we don't touch here, but it's good | ||
124 | * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). | ||
125 | */ | ||
126 | WA_SET_FIELD_MASKED(GEN7_GT_MODE, | ||
127 | GEN6_WIZ_HASHING_MASK, | ||
128 | GEN6_WIZ_HASHING_16x4); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int bdw_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
134 | { | ||
135 | int ret; | ||
136 | |||
137 | ret = gen8_ctx_workarounds_init(dev_priv); | ||
138 | if (ret) | ||
139 | return ret; | ||
140 | |||
141 | /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ | ||
142 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); | ||
143 | |||
144 | /* WaDisableDopClockGating:bdw | ||
145 | * | ||
146 | * Also see the related UCGTCL1 write in broadwell_init_clock_gating() | ||
147 | * to disable EUTC clock gating. | ||
148 | */ | ||
149 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, | ||
150 | DOP_CLOCK_GATING_DISABLE); | ||
151 | |||
152 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
153 | GEN8_SAMPLER_POWER_BYPASS_DIS); | ||
154 | |||
155 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
156 | /* WaForceContextSaveRestoreNonCoherent:bdw */ | ||
157 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | | ||
158 | /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ | ||
159 | (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int chv_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | ret = gen8_ctx_workarounds_init(dev_priv); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | /* WaDisableThreadStallDopClockGating:chv */ | ||
173 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); | ||
174 | |||
175 | /* Improve HiZ throughput on CHV. */ | ||
176 | WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
182 | { | ||
183 | if (HAS_LLC(dev_priv)) { | ||
184 | /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl | ||
185 | * | ||
186 | * Must match Display Engine. See | ||
187 | * WaCompressedResourceDisplayNewHashMode. | ||
188 | */ | ||
189 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
190 | GEN9_PBE_COMPRESSED_HASH_SELECTION); | ||
191 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, | ||
192 | GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR); | ||
193 | } | ||
194 | |||
195 | /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */ | ||
196 | /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */ | ||
197 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
198 | FLOW_CONTROL_ENABLE | | ||
199 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); | ||
200 | |||
201 | /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ | ||
202 | if (!IS_COFFEELAKE(dev_priv)) | ||
203 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
204 | GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); | ||
205 | |||
206 | /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */ | ||
207 | /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */ | ||
208 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, | ||
209 | GEN9_ENABLE_YV12_BUGFIX | | ||
210 | GEN9_ENABLE_GPGPU_PREEMPTION); | ||
211 | |||
212 | /* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk,cfl */ | ||
213 | /* WaDisablePartialResolveInVc:skl,bxt,kbl,cfl */ | ||
214 | WA_SET_BIT_MASKED(CACHE_MODE_1, | ||
215 | GEN8_4x4_STC_OPTIMIZATION_DISABLE | | ||
216 | GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE); | ||
217 | |||
218 | /* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk,cfl */ | ||
219 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, | ||
220 | GEN9_CCS_TLB_PREFETCH_ENABLE); | ||
221 | |||
222 | /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */ | ||
223 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
224 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | | ||
225 | HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); | ||
226 | |||
227 | /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are | ||
228 | * both tied to WaForceContextSaveRestoreNonCoherent | ||
229 | * in some hsds for skl. We keep the tie for all gen9. The | ||
230 | * documentation is a bit hazy and so we want to get common behaviour, | ||
231 | * even though there is no clear evidence we would need both on kbl/bxt. | ||
232 | * This area has been source of system hangs so we play it safe | ||
233 | * and mimic the skl regardless of what bspec says. | ||
234 | * | ||
235 | * Use Force Non-Coherent whenever executing a 3D context. This | ||
236 | * is a workaround for a possible hang in the unlikely event | ||
237 | * a TLB invalidation occurs during a PSD flush. | ||
238 | */ | ||
239 | |||
240 | /* WaForceEnableNonCoherent:skl,bxt,kbl,cfl */ | ||
241 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
242 | HDC_FORCE_NON_COHERENT); | ||
243 | |||
244 | /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */ | ||
245 | if (IS_SKYLAKE(dev_priv) || | ||
246 | IS_KABYLAKE(dev_priv) || | ||
247 | IS_COFFEELAKE(dev_priv)) | ||
248 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | ||
249 | GEN8_SAMPLER_POWER_BYPASS_DIS); | ||
250 | |||
251 | /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */ | ||
252 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); | ||
253 | |||
254 | /* | ||
255 | * Supporting preemption with fine-granularity requires changes in the | ||
256 | * batch buffer programming. Since we can't break old userspace, we | ||
257 | * need to set our default preemption level to safe value. Userspace is | ||
258 | * still able to use more fine-grained preemption levels, since in | ||
259 | * WaEnablePreemptionGranularityControlByUMD we're whitelisting the | ||
260 | * per-ctx register. As such, WaDisable{3D,GPGPU}MidCmdPreemption are | ||
261 | * not real HW workarounds, but merely a way to start using preemption | ||
262 | * while maintaining old contract with userspace. | ||
263 | */ | ||
264 | |||
265 | /* WaDisable3DMidCmdPreemption:skl,bxt,glk,cfl,[cnl] */ | ||
266 | WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); | ||
267 | |||
268 | /* WaDisableGPGPUMidCmdPreemption:skl,bxt,blk,cfl,[cnl] */ | ||
269 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, | ||
270 | GEN9_PREEMPT_GPGPU_LEVEL_MASK, | ||
271 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv) | ||
277 | { | ||
278 | u8 vals[3] = { 0, 0, 0 }; | ||
279 | unsigned int i; | ||
280 | |||
281 | for (i = 0; i < 3; i++) { | ||
282 | u8 ss; | ||
283 | |||
284 | /* | ||
285 | * Only consider slices where one, and only one, subslice has 7 | ||
286 | * EUs | ||
287 | */ | ||
288 | if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) | ||
289 | continue; | ||
290 | |||
291 | /* | ||
292 | * subslice_7eu[i] != 0 (because of the check above) and | ||
293 | * ss_max == 4 (maximum number of subslices possible per slice) | ||
294 | * | ||
295 | * -> 0 <= ss <= 3; | ||
296 | */ | ||
297 | ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; | ||
298 | vals[i] = 3 - ss; | ||
299 | } | ||
300 | |||
301 | if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) | ||
302 | return 0; | ||
303 | |||
304 | /* Tune IZ hashing. See intel_device_info_runtime_init() */ | ||
305 | WA_SET_FIELD_MASKED(GEN7_GT_MODE, | ||
306 | GEN9_IZ_HASHING_MASK(2) | | ||
307 | GEN9_IZ_HASHING_MASK(1) | | ||
308 | GEN9_IZ_HASHING_MASK(0), | ||
309 | GEN9_IZ_HASHING(2, vals[2]) | | ||
310 | GEN9_IZ_HASHING(1, vals[1]) | | ||
311 | GEN9_IZ_HASHING(0, vals[0])); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int skl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
317 | { | ||
318 | int ret; | ||
319 | |||
320 | ret = gen9_ctx_workarounds_init(dev_priv); | ||
321 | if (ret) | ||
322 | return ret; | ||
323 | |||
324 | return skl_tune_iz_hashing(dev_priv); | ||
325 | } | ||
326 | |||
327 | static int bxt_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
328 | { | ||
329 | int ret; | ||
330 | |||
331 | ret = gen9_ctx_workarounds_init(dev_priv); | ||
332 | if (ret) | ||
333 | return ret; | ||
334 | |||
335 | /* WaDisableThreadStallDopClockGating:bxt */ | ||
336 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, | ||
337 | STALL_DOP_GATING_DISABLE); | ||
338 | |||
339 | /* WaToEnableHwFixForPushConstHWBug:bxt */ | ||
340 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
341 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int kbl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
347 | { | ||
348 | int ret; | ||
349 | |||
350 | ret = gen9_ctx_workarounds_init(dev_priv); | ||
351 | if (ret) | ||
352 | return ret; | ||
353 | |||
354 | /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ | ||
355 | if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) | ||
356 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
357 | HDC_FENCE_DEST_SLM_DISABLE); | ||
358 | |||
359 | /* WaToEnableHwFixForPushConstHWBug:kbl */ | ||
360 | if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) | ||
361 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
362 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
363 | |||
364 | /* WaDisableSbeCacheDispatchPortSharing:kbl */ | ||
365 | WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1, | ||
366 | GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int glk_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
372 | { | ||
373 | int ret; | ||
374 | |||
375 | ret = gen9_ctx_workarounds_init(dev_priv); | ||
376 | if (ret) | ||
377 | return ret; | ||
378 | |||
379 | /* WaToEnableHwFixForPushConstHWBug:glk */ | ||
380 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
381 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int cfl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
387 | { | ||
388 | int ret; | ||
389 | |||
390 | ret = gen9_ctx_workarounds_init(dev_priv); | ||
391 | if (ret) | ||
392 | return ret; | ||
393 | |||
394 | /* WaToEnableHwFixForPushConstHWBug:cfl */ | ||
395 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
396 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
397 | |||
398 | /* WaDisableSbeCacheDispatchPortSharing:cfl */ | ||
399 | WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1, | ||
400 | GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
406 | { | ||
407 | /* WaForceContextSaveRestoreNonCoherent:cnl */ | ||
408 | WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, | ||
409 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT); | ||
410 | |||
411 | /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */ | ||
412 | if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) | ||
413 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5); | ||
414 | |||
415 | /* WaDisableReplayBufferBankArbitrationOptimization:cnl */ | ||
416 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
417 | GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | ||
418 | |||
419 | /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */ | ||
420 | if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0)) | ||
421 | WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | ||
422 | GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); | ||
423 | |||
424 | /* WaPushConstantDereferenceHoldDisable:cnl */ | ||
425 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); | ||
426 | |||
427 | /* FtrEnableFastAnisoL1BankingFix:cnl */ | ||
428 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX); | ||
429 | |||
430 | /* WaDisable3DMidCmdPreemption:cnl */ | ||
431 | WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); | ||
432 | |||
433 | /* WaDisableGPGPUMidCmdPreemption:cnl */ | ||
434 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, | ||
435 | GEN9_PREEMPT_GPGPU_LEVEL_MASK, | ||
436 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | ||
437 | |||
438 | /* WaDisableEarlyEOT:cnl */ | ||
439 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
445 | { | ||
446 | int err = 0; | ||
447 | |||
448 | dev_priv->workarounds.count = 0; | ||
449 | |||
450 | if (INTEL_GEN(dev_priv) < 8) | ||
451 | err = 0; | ||
452 | else if (IS_BROADWELL(dev_priv)) | ||
453 | err = bdw_ctx_workarounds_init(dev_priv); | ||
454 | else if (IS_CHERRYVIEW(dev_priv)) | ||
455 | err = chv_ctx_workarounds_init(dev_priv); | ||
456 | else if (IS_SKYLAKE(dev_priv)) | ||
457 | err = skl_ctx_workarounds_init(dev_priv); | ||
458 | else if (IS_BROXTON(dev_priv)) | ||
459 | err = bxt_ctx_workarounds_init(dev_priv); | ||
460 | else if (IS_KABYLAKE(dev_priv)) | ||
461 | err = kbl_ctx_workarounds_init(dev_priv); | ||
462 | else if (IS_GEMINILAKE(dev_priv)) | ||
463 | err = glk_ctx_workarounds_init(dev_priv); | ||
464 | else if (IS_COFFEELAKE(dev_priv)) | ||
465 | err = cfl_ctx_workarounds_init(dev_priv); | ||
466 | else if (IS_CANNONLAKE(dev_priv)) | ||
467 | err = cnl_ctx_workarounds_init(dev_priv); | ||
468 | else | ||
469 | MISSING_CASE(INTEL_GEN(dev_priv)); | ||
470 | if (err) | ||
471 | return err; | ||
472 | |||
473 | DRM_DEBUG_DRIVER("Number of context specific w/a: %d\n", | ||
474 | dev_priv->workarounds.count); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | int intel_ctx_workarounds_emit(struct i915_request *rq) | ||
479 | { | ||
480 | struct i915_workarounds *w = &rq->i915->workarounds; | ||
481 | u32 *cs; | ||
482 | int ret, i; | ||
483 | |||
484 | if (w->count == 0) | ||
485 | return 0; | ||
486 | |||
487 | ret = rq->engine->emit_flush(rq, EMIT_BARRIER); | ||
488 | if (ret) | ||
489 | return ret; | ||
490 | |||
491 | cs = intel_ring_begin(rq, (w->count * 2 + 2)); | ||
492 | if (IS_ERR(cs)) | ||
493 | return PTR_ERR(cs); | ||
494 | |||
495 | *cs++ = MI_LOAD_REGISTER_IMM(w->count); | ||
496 | for (i = 0; i < w->count; i++) { | ||
497 | *cs++ = i915_mmio_reg_offset(w->reg[i].addr); | ||
498 | *cs++ = w->reg[i].value; | ||
499 | } | ||
500 | *cs++ = MI_NOOP; | ||
501 | |||
502 | intel_ring_advance(rq, cs); | ||
503 | |||
504 | ret = rq->engine->emit_flush(rq, EMIT_BARRIER); | ||
505 | if (ret) | ||
506 | return ret; | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static void bdw_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
512 | { | ||
513 | } | ||
514 | |||
515 | static void chv_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
516 | { | ||
517 | } | ||
518 | |||
519 | static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
520 | { | ||
521 | /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ | ||
522 | I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, | ||
523 | _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); | ||
524 | |||
525 | /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ | ||
526 | I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | | ||
527 | GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); | ||
528 | |||
529 | /* WaDisableKillLogic:bxt,skl,kbl */ | ||
530 | if (!IS_COFFEELAKE(dev_priv)) | ||
531 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | ||
532 | ECOCHK_DIS_TLB); | ||
533 | |||
534 | if (HAS_LLC(dev_priv)) { | ||
535 | /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl | ||
536 | * | ||
537 | * Must match Display Engine. See | ||
538 | * WaCompressedResourceDisplayNewHashMode. | ||
539 | */ | ||
540 | I915_WRITE(MMCD_MISC_CTRL, | ||
541 | I915_READ(MMCD_MISC_CTRL) | | ||
542 | MMCD_PCLA | | ||
543 | MMCD_HOTSPOT_EN); | ||
544 | } | ||
545 | |||
546 | /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ | ||
547 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | ||
548 | BDW_DISABLE_HDC_INVALIDATION); | ||
549 | |||
550 | /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ | ||
551 | if (IS_GEN9_LP(dev_priv)) { | ||
552 | u32 val = I915_READ(GEN8_L3SQCREG1); | ||
553 | |||
554 | val &= ~L3_PRIO_CREDITS_MASK; | ||
555 | val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); | ||
556 | I915_WRITE(GEN8_L3SQCREG1, val); | ||
557 | } | ||
558 | |||
559 | /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ | ||
560 | I915_WRITE(GEN8_L3SQCREG4, | ||
561 | I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
562 | |||
563 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ | ||
564 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
565 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
566 | } | ||
567 | |||
568 | static void skl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
569 | { | ||
570 | gen9_gt_workarounds_apply(dev_priv); | ||
571 | |||
572 | /* WaEnableGapsTsvCreditFix:skl */ | ||
573 | I915_WRITE(GEN8_GARBCNTL, | ||
574 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
575 | |||
576 | /* WaDisableGafsUnitClkGating:skl */ | ||
577 | I915_WRITE(GEN7_UCGCTL4, | ||
578 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
579 | |||
580 | /* WaInPlaceDecompressionHang:skl */ | ||
581 | if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) | ||
582 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
583 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
584 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
585 | } | ||
586 | |||
587 | static void bxt_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
588 | { | ||
589 | gen9_gt_workarounds_apply(dev_priv); | ||
590 | |||
591 | /* WaDisablePooledEuLoadBalancingFix:bxt */ | ||
592 | I915_WRITE(FF_SLICE_CS_CHICKEN2, | ||
593 | _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); | ||
594 | |||
595 | /* WaInPlaceDecompressionHang:bxt */ | ||
596 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
597 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
598 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
599 | } | ||
600 | |||
601 | static void kbl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
602 | { | ||
603 | gen9_gt_workarounds_apply(dev_priv); | ||
604 | |||
605 | /* WaEnableGapsTsvCreditFix:kbl */ | ||
606 | I915_WRITE(GEN8_GARBCNTL, | ||
607 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
608 | |||
609 | /* WaDisableDynamicCreditSharing:kbl */ | ||
610 | if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) | ||
611 | I915_WRITE(GAMT_CHKN_BIT_REG, | ||
612 | I915_READ(GAMT_CHKN_BIT_REG) | | ||
613 | GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); | ||
614 | |||
615 | /* WaDisableGafsUnitClkGating:kbl */ | ||
616 | I915_WRITE(GEN7_UCGCTL4, | ||
617 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
618 | |||
619 | /* WaInPlaceDecompressionHang:kbl */ | ||
620 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
621 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
622 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
623 | } | ||
624 | |||
625 | static void glk_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
626 | { | ||
627 | gen9_gt_workarounds_apply(dev_priv); | ||
628 | } | ||
629 | |||
630 | static void cfl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
631 | { | ||
632 | gen9_gt_workarounds_apply(dev_priv); | ||
633 | |||
634 | /* WaEnableGapsTsvCreditFix:cfl */ | ||
635 | I915_WRITE(GEN8_GARBCNTL, | ||
636 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
637 | |||
638 | /* WaDisableGafsUnitClkGating:cfl */ | ||
639 | I915_WRITE(GEN7_UCGCTL4, | ||
640 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
641 | |||
642 | /* WaInPlaceDecompressionHang:cfl */ | ||
643 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
644 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
645 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
646 | } | ||
647 | |||
648 | static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
649 | { | ||
650 | /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ | ||
651 | if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) | ||
652 | I915_WRITE(GAMT_CHKN_BIT_REG, | ||
653 | I915_READ(GAMT_CHKN_BIT_REG) | | ||
654 | GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); | ||
655 | |||
656 | /* WaInPlaceDecompressionHang:cnl */ | ||
657 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | ||
658 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
659 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
660 | |||
661 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ | ||
662 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
663 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
664 | } | ||
665 | |||
666 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
667 | { | ||
668 | if (INTEL_GEN(dev_priv) < 8) | ||
669 | return; | ||
670 | else if (IS_BROADWELL(dev_priv)) | ||
671 | bdw_gt_workarounds_apply(dev_priv); | ||
672 | else if (IS_CHERRYVIEW(dev_priv)) | ||
673 | chv_gt_workarounds_apply(dev_priv); | ||
674 | else if (IS_SKYLAKE(dev_priv)) | ||
675 | skl_gt_workarounds_apply(dev_priv); | ||
676 | else if (IS_BROXTON(dev_priv)) | ||
677 | bxt_gt_workarounds_apply(dev_priv); | ||
678 | else if (IS_KABYLAKE(dev_priv)) | ||
679 | kbl_gt_workarounds_apply(dev_priv); | ||
680 | else if (IS_GEMINILAKE(dev_priv)) | ||
681 | glk_gt_workarounds_apply(dev_priv); | ||
682 | else if (IS_COFFEELAKE(dev_priv)) | ||
683 | cfl_gt_workarounds_apply(dev_priv); | ||
684 | else if (IS_CANNONLAKE(dev_priv)) | ||
685 | cnl_gt_workarounds_apply(dev_priv); | ||
686 | else | ||
687 | MISSING_CASE(INTEL_GEN(dev_priv)); | ||
688 | } | ||
689 | |||
690 | static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, | ||
691 | i915_reg_t reg) | ||
692 | { | ||
693 | struct drm_i915_private *dev_priv = engine->i915; | ||
694 | struct i915_workarounds *wa = &dev_priv->workarounds; | ||
695 | const unsigned int index = wa->hw_whitelist_count[engine->id]; | ||
696 | |||
697 | if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) | ||
698 | return -EINVAL; | ||
699 | |||
700 | I915_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), | ||
701 | i915_mmio_reg_offset(reg)); | ||
702 | wa->hw_whitelist_count[engine->id]++; | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static int bdw_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
708 | { | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | static int chv_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
713 | { | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static int gen9_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
718 | { | ||
719 | int ret; | ||
720 | |||
721 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ | ||
722 | ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); | ||
723 | if (ret) | ||
724 | return ret; | ||
725 | |||
726 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ | ||
727 | ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | ||
728 | if (ret) | ||
729 | return ret; | ||
730 | |||
731 | /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */ | ||
732 | ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); | ||
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int skl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
740 | { | ||
741 | int ret; | ||
742 | |||
743 | ret = gen9_whitelist_workarounds_apply(engine); | ||
744 | if (ret) | ||
745 | return ret; | ||
746 | |||
747 | /* WaDisableLSQCROPERFforOCL:skl */ | ||
748 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | ||
749 | if (ret) | ||
750 | return ret; | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int bxt_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
756 | { | ||
757 | int ret; | ||
758 | |||
759 | ret = gen9_whitelist_workarounds_apply(engine); | ||
760 | if (ret) | ||
761 | return ret; | ||
762 | |||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static int kbl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
767 | { | ||
768 | int ret; | ||
769 | |||
770 | ret = gen9_whitelist_workarounds_apply(engine); | ||
771 | if (ret) | ||
772 | return ret; | ||
773 | |||
774 | /* WaDisableLSQCROPERFforOCL:kbl */ | ||
775 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | ||
776 | if (ret) | ||
777 | return ret; | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | static int glk_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
783 | { | ||
784 | int ret; | ||
785 | |||
786 | ret = gen9_whitelist_workarounds_apply(engine); | ||
787 | if (ret) | ||
788 | return ret; | ||
789 | |||
790 | /* WA #0862: Userspace has to set "Barrier Mode" to avoid hangs. */ | ||
791 | ret = wa_ring_whitelist_reg(engine, GEN9_SLICE_COMMON_ECO_CHICKEN1); | ||
792 | if (ret) | ||
793 | return ret; | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int cfl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
799 | { | ||
800 | int ret; | ||
801 | |||
802 | ret = gen9_whitelist_workarounds_apply(engine); | ||
803 | if (ret) | ||
804 | return ret; | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | static int cnl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
810 | { | ||
811 | int ret; | ||
812 | |||
813 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ | ||
814 | ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | ||
815 | if (ret) | ||
816 | return ret; | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | int intel_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
822 | { | ||
823 | struct drm_i915_private *dev_priv = engine->i915; | ||
824 | int err = 0; | ||
825 | |||
826 | WARN_ON(engine->id != RCS); | ||
827 | |||
828 | dev_priv->workarounds.hw_whitelist_count[engine->id] = 0; | ||
829 | |||
830 | if (INTEL_GEN(dev_priv) < 8) | ||
831 | err = 0; | ||
832 | else if (IS_BROADWELL(dev_priv)) | ||
833 | err = bdw_whitelist_workarounds_apply(engine); | ||
834 | else if (IS_CHERRYVIEW(dev_priv)) | ||
835 | err = chv_whitelist_workarounds_apply(engine); | ||
836 | else if (IS_SKYLAKE(dev_priv)) | ||
837 | err = skl_whitelist_workarounds_apply(engine); | ||
838 | else if (IS_BROXTON(dev_priv)) | ||
839 | err = bxt_whitelist_workarounds_apply(engine); | ||
840 | else if (IS_KABYLAKE(dev_priv)) | ||
841 | err = kbl_whitelist_workarounds_apply(engine); | ||
842 | else if (IS_GEMINILAKE(dev_priv)) | ||
843 | err = glk_whitelist_workarounds_apply(engine); | ||
844 | else if (IS_COFFEELAKE(dev_priv)) | ||
845 | err = cfl_whitelist_workarounds_apply(engine); | ||
846 | else if (IS_CANNONLAKE(dev_priv)) | ||
847 | err = cnl_whitelist_workarounds_apply(engine); | ||
848 | else | ||
849 | MISSING_CASE(INTEL_GEN(dev_priv)); | ||
850 | if (err) | ||
851 | return err; | ||
852 | |||
853 | DRM_DEBUG_DRIVER("%s: Number of whitelist w/a: %d\n", engine->name, | ||
854 | dev_priv->workarounds.hw_whitelist_count[engine->id]); | ||
855 | return 0; | ||
856 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h new file mode 100644 index 000000000000..d9b0cc5afb4a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_workarounds.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2014-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef _I915_WORKAROUNDS_H_ | ||
8 | #define _I915_WORKAROUNDS_H_ | ||
9 | |||
10 | int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv); | ||
11 | int intel_ctx_workarounds_emit(struct i915_request *rq); | ||
12 | |||
13 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv); | ||
14 | |||
15 | int intel_whitelist_workarounds_apply(struct intel_engine_cs *engine); | ||
16 | |||
17 | #endif | ||
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 9c76f0305b6a..8bf6aa573226 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h | |||
@@ -20,4 +20,5 @@ selftest(evict, i915_gem_evict_live_selftests) | |||
20 | selftest(hugepages, i915_gem_huge_page_live_selftests) | 20 | selftest(hugepages, i915_gem_huge_page_live_selftests) |
21 | selftest(contexts, i915_gem_context_live_selftests) | 21 | selftest(contexts, i915_gem_context_live_selftests) |
22 | selftest(hangcheck, intel_hangcheck_live_selftests) | 22 | selftest(hangcheck, intel_hangcheck_live_selftests) |
23 | selftest(execlists, intel_execlists_live_selftests) | ||
23 | selftest(guc, intel_guc_live_selftest) | 24 | selftest(guc, intel_guc_live_selftest) |
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index 9a48aa441743..d16d74178e9d 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h | |||
@@ -14,6 +14,7 @@ selftest(fence, i915_sw_fence_mock_selftests) | |||
14 | selftest(scatterlist, scatterlist_mock_selftests) | 14 | selftest(scatterlist, scatterlist_mock_selftests) |
15 | selftest(syncmap, i915_syncmap_mock_selftests) | 15 | selftest(syncmap, i915_syncmap_mock_selftests) |
16 | selftest(uncore, intel_uncore_mock_selftests) | 16 | selftest(uncore, intel_uncore_mock_selftests) |
17 | selftest(engine, intel_engine_cs_mock_selftests) | ||
17 | selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) | 18 | selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) |
18 | selftest(timelines, i915_gem_timeline_mock_selftests) | 19 | selftest(timelines, i915_gem_timeline_mock_selftests) |
19 | selftest(requests, i915_request_mock_selftests) | 20 | selftest(requests, i915_request_mock_selftests) |
diff --git a/drivers/gpu/drm/i915/selftests/intel_engine_cs.c b/drivers/gpu/drm/i915/selftests/intel_engine_cs.c new file mode 100644 index 000000000000..cfaa6b296835 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_engine_cs.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: GPL-2.0 | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "../i915_selftest.h" | ||
8 | |||
9 | static int intel_mmio_bases_check(void *arg) | ||
10 | { | ||
11 | int i, j; | ||
12 | |||
13 | for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { | ||
14 | const struct engine_info *info = &intel_engines[i]; | ||
15 | char name[INTEL_ENGINE_CS_MAX_NAME]; | ||
16 | u8 prev = U8_MAX; | ||
17 | |||
18 | __sprint_engine_name(name, info); | ||
19 | |||
20 | for (j = 0; j < MAX_MMIO_BASES; j++) { | ||
21 | u8 gen = info->mmio_bases[j].gen; | ||
22 | u32 base = info->mmio_bases[j].base; | ||
23 | |||
24 | if (gen >= prev) { | ||
25 | pr_err("%s: %s: mmio base for gen %x " | ||
26 | "is before the one for gen %x\n", | ||
27 | __func__, name, prev, gen); | ||
28 | return -EINVAL; | ||
29 | } | ||
30 | |||
31 | if (gen == 0) | ||
32 | break; | ||
33 | |||
34 | if (!base) { | ||
35 | pr_err("%s: %s: invalid mmio base (%x) " | ||
36 | "for gen %x at entry %u\n", | ||
37 | __func__, name, base, gen, j); | ||
38 | return -EINVAL; | ||
39 | } | ||
40 | |||
41 | prev = gen; | ||
42 | } | ||
43 | |||
44 | pr_info("%s: min gen supported for %s = %d\n", | ||
45 | __func__, name, prev); | ||
46 | } | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | int intel_engine_cs_mock_selftests(void) | ||
52 | { | ||
53 | static const struct i915_subtest tests[] = { | ||
54 | SUBTEST(intel_mmio_bases_check), | ||
55 | }; | ||
56 | |||
57 | return i915_subtests(tests, NULL); | ||
58 | } | ||
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index df7898c8edcb..24f913f26a7b 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
26 | 26 | ||
27 | #include "../i915_selftest.h" | 27 | #include "../i915_selftest.h" |
28 | #include "i915_random.h" | ||
28 | 29 | ||
29 | #include "mock_context.h" | 30 | #include "mock_context.h" |
30 | #include "mock_drm.h" | 31 | #include "mock_drm.h" |
@@ -260,8 +261,11 @@ static void wedge_me(struct work_struct *work) | |||
260 | { | 261 | { |
261 | struct wedge_me *w = container_of(work, typeof(*w), work.work); | 262 | struct wedge_me *w = container_of(work, typeof(*w), work.work); |
262 | 263 | ||
263 | pr_err("%pS timed out, cancelling all further testing.\n", | 264 | pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); |
264 | w->symbol); | 265 | |
266 | GEM_TRACE("%pS timed out.\n", w->symbol); | ||
267 | GEM_TRACE_DUMP(); | ||
268 | |||
265 | i915_gem_set_wedged(w->i915); | 269 | i915_gem_set_wedged(w->i915); |
266 | } | 270 | } |
267 | 271 | ||
@@ -318,7 +322,7 @@ static void hang_fini(struct hang *h) | |||
318 | flush_test(h->i915, I915_WAIT_LOCKED); | 322 | flush_test(h->i915, I915_WAIT_LOCKED); |
319 | } | 323 | } |
320 | 324 | ||
321 | static bool wait_for_hang(struct hang *h, struct i915_request *rq) | 325 | static bool wait_until_running(struct hang *h, struct i915_request *rq) |
322 | { | 326 | { |
323 | return !(wait_for_us(i915_seqno_passed(hws_seqno(h, rq), | 327 | return !(wait_for_us(i915_seqno_passed(hws_seqno(h, rq), |
324 | rq->fence.seqno), | 328 | rq->fence.seqno), |
@@ -433,7 +437,7 @@ static int igt_global_reset(void *arg) | |||
433 | mutex_lock(&i915->drm.struct_mutex); | 437 | mutex_lock(&i915->drm.struct_mutex); |
434 | reset_count = i915_reset_count(&i915->gpu_error); | 438 | reset_count = i915_reset_count(&i915->gpu_error); |
435 | 439 | ||
436 | i915_reset(i915, I915_RESET_QUIET); | 440 | i915_reset(i915, ALL_ENGINES, NULL); |
437 | 441 | ||
438 | if (i915_reset_count(&i915->gpu_error) == reset_count) { | 442 | if (i915_reset_count(&i915->gpu_error) == reset_count) { |
439 | pr_err("No GPU reset recorded!\n"); | 443 | pr_err("No GPU reset recorded!\n"); |
@@ -483,6 +487,8 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
483 | 487 | ||
484 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 488 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
485 | do { | 489 | do { |
490 | u32 seqno = intel_engine_get_seqno(engine); | ||
491 | |||
486 | if (active) { | 492 | if (active) { |
487 | struct i915_request *rq; | 493 | struct i915_request *rq; |
488 | 494 | ||
@@ -498,7 +504,7 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
498 | __i915_request_add(rq, true); | 504 | __i915_request_add(rq, true); |
499 | mutex_unlock(&i915->drm.struct_mutex); | 505 | mutex_unlock(&i915->drm.struct_mutex); |
500 | 506 | ||
501 | if (!wait_for_hang(&h, rq)) { | 507 | if (!wait_until_running(&h, rq)) { |
502 | struct drm_printer p = drm_info_printer(i915->drm.dev); | 508 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
503 | 509 | ||
504 | pr_err("%s: Failed to start request %x, at %x\n", | 510 | pr_err("%s: Failed to start request %x, at %x\n", |
@@ -511,14 +517,12 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
511 | break; | 517 | break; |
512 | } | 518 | } |
513 | 519 | ||
520 | GEM_BUG_ON(!rq->global_seqno); | ||
521 | seqno = rq->global_seqno - 1; | ||
514 | i915_request_put(rq); | 522 | i915_request_put(rq); |
515 | } | 523 | } |
516 | 524 | ||
517 | engine->hangcheck.stalled = true; | 525 | err = i915_reset_engine(engine, NULL); |
518 | engine->hangcheck.seqno = | ||
519 | intel_engine_get_seqno(engine); | ||
520 | |||
521 | err = i915_reset_engine(engine, I915_RESET_QUIET); | ||
522 | if (err) { | 526 | if (err) { |
523 | pr_err("i915_reset_engine failed\n"); | 527 | pr_err("i915_reset_engine failed\n"); |
524 | break; | 528 | break; |
@@ -538,8 +542,6 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
538 | err = -EINVAL; | 542 | err = -EINVAL; |
539 | break; | 543 | break; |
540 | } | 544 | } |
541 | |||
542 | engine->hangcheck.stalled = false; | ||
543 | } while (time_before(jiffies, end_time)); | 545 | } while (time_before(jiffies, end_time)); |
544 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 546 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
545 | 547 | ||
@@ -573,11 +575,25 @@ static int igt_reset_active_engine(void *arg) | |||
573 | return __igt_reset_engine(arg, true); | 575 | return __igt_reset_engine(arg, true); |
574 | } | 576 | } |
575 | 577 | ||
578 | struct active_engine { | ||
579 | struct task_struct *task; | ||
580 | struct intel_engine_cs *engine; | ||
581 | unsigned long resets; | ||
582 | unsigned int flags; | ||
583 | }; | ||
584 | |||
585 | #define TEST_ACTIVE BIT(0) | ||
586 | #define TEST_OTHERS BIT(1) | ||
587 | #define TEST_SELF BIT(2) | ||
588 | #define TEST_PRIORITY BIT(3) | ||
589 | |||
576 | static int active_engine(void *data) | 590 | static int active_engine(void *data) |
577 | { | 591 | { |
578 | struct intel_engine_cs *engine = data; | 592 | I915_RND_STATE(prng); |
579 | struct i915_request *rq[2] = {}; | 593 | struct active_engine *arg = data; |
580 | struct i915_gem_context *ctx[2]; | 594 | struct intel_engine_cs *engine = arg->engine; |
595 | struct i915_request *rq[8] = {}; | ||
596 | struct i915_gem_context *ctx[ARRAY_SIZE(rq)]; | ||
581 | struct drm_file *file; | 597 | struct drm_file *file; |
582 | unsigned long count = 0; | 598 | unsigned long count = 0; |
583 | int err = 0; | 599 | int err = 0; |
@@ -586,25 +602,20 @@ static int active_engine(void *data) | |||
586 | if (IS_ERR(file)) | 602 | if (IS_ERR(file)) |
587 | return PTR_ERR(file); | 603 | return PTR_ERR(file); |
588 | 604 | ||
589 | mutex_lock(&engine->i915->drm.struct_mutex); | 605 | for (count = 0; count < ARRAY_SIZE(ctx); count++) { |
590 | ctx[0] = live_context(engine->i915, file); | 606 | mutex_lock(&engine->i915->drm.struct_mutex); |
591 | mutex_unlock(&engine->i915->drm.struct_mutex); | 607 | ctx[count] = live_context(engine->i915, file); |
592 | if (IS_ERR(ctx[0])) { | 608 | mutex_unlock(&engine->i915->drm.struct_mutex); |
593 | err = PTR_ERR(ctx[0]); | 609 | if (IS_ERR(ctx[count])) { |
594 | goto err_file; | 610 | err = PTR_ERR(ctx[count]); |
595 | } | 611 | while (--count) |
596 | 612 | i915_gem_context_put(ctx[count]); | |
597 | mutex_lock(&engine->i915->drm.struct_mutex); | 613 | goto err_file; |
598 | ctx[1] = live_context(engine->i915, file); | 614 | } |
599 | mutex_unlock(&engine->i915->drm.struct_mutex); | ||
600 | if (IS_ERR(ctx[1])) { | ||
601 | err = PTR_ERR(ctx[1]); | ||
602 | i915_gem_context_put(ctx[0]); | ||
603 | goto err_file; | ||
604 | } | 615 | } |
605 | 616 | ||
606 | while (!kthread_should_stop()) { | 617 | while (!kthread_should_stop()) { |
607 | unsigned int idx = count++ & 1; | 618 | unsigned int idx = count++ & (ARRAY_SIZE(rq) - 1); |
608 | struct i915_request *old = rq[idx]; | 619 | struct i915_request *old = rq[idx]; |
609 | struct i915_request *new; | 620 | struct i915_request *new; |
610 | 621 | ||
@@ -616,14 +627,28 @@ static int active_engine(void *data) | |||
616 | break; | 627 | break; |
617 | } | 628 | } |
618 | 629 | ||
630 | if (arg->flags & TEST_PRIORITY) | ||
631 | ctx[idx]->priority = | ||
632 | i915_prandom_u32_max_state(512, &prng); | ||
633 | |||
619 | rq[idx] = i915_request_get(new); | 634 | rq[idx] = i915_request_get(new); |
620 | i915_request_add(new); | 635 | i915_request_add(new); |
621 | mutex_unlock(&engine->i915->drm.struct_mutex); | 636 | mutex_unlock(&engine->i915->drm.struct_mutex); |
622 | 637 | ||
623 | if (old) { | 638 | if (old) { |
624 | i915_request_wait(old, 0, MAX_SCHEDULE_TIMEOUT); | 639 | if (i915_request_wait(old, 0, HZ) < 0) { |
640 | GEM_TRACE("%s timed out.\n", engine->name); | ||
641 | GEM_TRACE_DUMP(); | ||
642 | |||
643 | i915_gem_set_wedged(engine->i915); | ||
644 | i915_request_put(old); | ||
645 | err = -EIO; | ||
646 | break; | ||
647 | } | ||
625 | i915_request_put(old); | 648 | i915_request_put(old); |
626 | } | 649 | } |
650 | |||
651 | cond_resched(); | ||
627 | } | 652 | } |
628 | 653 | ||
629 | for (count = 0; count < ARRAY_SIZE(rq); count++) | 654 | for (count = 0; count < ARRAY_SIZE(rq); count++) |
@@ -634,8 +659,9 @@ err_file: | |||
634 | return err; | 659 | return err; |
635 | } | 660 | } |
636 | 661 | ||
637 | static int __igt_reset_engine_others(struct drm_i915_private *i915, | 662 | static int __igt_reset_engines(struct drm_i915_private *i915, |
638 | bool active) | 663 | const char *test_name, |
664 | unsigned int flags) | ||
639 | { | 665 | { |
640 | struct intel_engine_cs *engine, *other; | 666 | struct intel_engine_cs *engine, *other; |
641 | enum intel_engine_id id, tmp; | 667 | enum intel_engine_id id, tmp; |
@@ -649,50 +675,61 @@ static int __igt_reset_engine_others(struct drm_i915_private *i915, | |||
649 | if (!intel_has_reset_engine(i915)) | 675 | if (!intel_has_reset_engine(i915)) |
650 | return 0; | 676 | return 0; |
651 | 677 | ||
652 | if (active) { | 678 | if (flags & TEST_ACTIVE) { |
653 | mutex_lock(&i915->drm.struct_mutex); | 679 | mutex_lock(&i915->drm.struct_mutex); |
654 | err = hang_init(&h, i915); | 680 | err = hang_init(&h, i915); |
655 | mutex_unlock(&i915->drm.struct_mutex); | 681 | mutex_unlock(&i915->drm.struct_mutex); |
656 | if (err) | 682 | if (err) |
657 | return err; | 683 | return err; |
684 | |||
685 | if (flags & TEST_PRIORITY) | ||
686 | h.ctx->priority = 1024; | ||
658 | } | 687 | } |
659 | 688 | ||
660 | for_each_engine(engine, i915, id) { | 689 | for_each_engine(engine, i915, id) { |
661 | struct task_struct *threads[I915_NUM_ENGINES] = {}; | 690 | struct active_engine threads[I915_NUM_ENGINES] = {}; |
662 | unsigned long resets[I915_NUM_ENGINES]; | ||
663 | unsigned long global = i915_reset_count(&i915->gpu_error); | 691 | unsigned long global = i915_reset_count(&i915->gpu_error); |
664 | unsigned long count = 0; | 692 | unsigned long count = 0, reported; |
665 | IGT_TIMEOUT(end_time); | 693 | IGT_TIMEOUT(end_time); |
666 | 694 | ||
667 | if (active && !intel_engine_can_store_dword(engine)) | 695 | if (flags & TEST_ACTIVE && |
696 | !intel_engine_can_store_dword(engine)) | ||
668 | continue; | 697 | continue; |
669 | 698 | ||
670 | memset(threads, 0, sizeof(threads)); | 699 | memset(threads, 0, sizeof(threads)); |
671 | for_each_engine(other, i915, tmp) { | 700 | for_each_engine(other, i915, tmp) { |
672 | struct task_struct *tsk; | 701 | struct task_struct *tsk; |
673 | 702 | ||
674 | resets[tmp] = i915_reset_engine_count(&i915->gpu_error, | 703 | threads[tmp].resets = |
675 | other); | 704 | i915_reset_engine_count(&i915->gpu_error, |
705 | other); | ||
676 | 706 | ||
677 | if (other == engine) | 707 | if (!(flags & TEST_OTHERS)) |
678 | continue; | 708 | continue; |
679 | 709 | ||
680 | tsk = kthread_run(active_engine, other, | 710 | if (other == engine && !(flags & TEST_SELF)) |
711 | continue; | ||
712 | |||
713 | threads[tmp].engine = other; | ||
714 | threads[tmp].flags = flags; | ||
715 | |||
716 | tsk = kthread_run(active_engine, &threads[tmp], | ||
681 | "igt/%s", other->name); | 717 | "igt/%s", other->name); |
682 | if (IS_ERR(tsk)) { | 718 | if (IS_ERR(tsk)) { |
683 | err = PTR_ERR(tsk); | 719 | err = PTR_ERR(tsk); |
684 | goto unwind; | 720 | goto unwind; |
685 | } | 721 | } |
686 | 722 | ||
687 | threads[tmp] = tsk; | 723 | threads[tmp].task = tsk; |
688 | get_task_struct(tsk); | 724 | get_task_struct(tsk); |
689 | } | 725 | } |
690 | 726 | ||
691 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 727 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
692 | do { | 728 | do { |
693 | if (active) { | 729 | u32 seqno = intel_engine_get_seqno(engine); |
694 | struct i915_request *rq; | 730 | struct i915_request *rq = NULL; |
695 | 731 | ||
732 | if (flags & TEST_ACTIVE) { | ||
696 | mutex_lock(&i915->drm.struct_mutex); | 733 | mutex_lock(&i915->drm.struct_mutex); |
697 | rq = hang_create_request(&h, engine); | 734 | rq = hang_create_request(&h, engine); |
698 | if (IS_ERR(rq)) { | 735 | if (IS_ERR(rq)) { |
@@ -705,7 +742,7 @@ static int __igt_reset_engine_others(struct drm_i915_private *i915, | |||
705 | __i915_request_add(rq, true); | 742 | __i915_request_add(rq, true); |
706 | mutex_unlock(&i915->drm.struct_mutex); | 743 | mutex_unlock(&i915->drm.struct_mutex); |
707 | 744 | ||
708 | if (!wait_for_hang(&h, rq)) { | 745 | if (!wait_until_running(&h, rq)) { |
709 | struct drm_printer p = drm_info_printer(i915->drm.dev); | 746 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
710 | 747 | ||
711 | pr_err("%s: Failed to start request %x, at %x\n", | 748 | pr_err("%s: Failed to start request %x, at %x\n", |
@@ -718,33 +755,34 @@ static int __igt_reset_engine_others(struct drm_i915_private *i915, | |||
718 | break; | 755 | break; |
719 | } | 756 | } |
720 | 757 | ||
721 | i915_request_put(rq); | 758 | GEM_BUG_ON(!rq->global_seqno); |
759 | seqno = rq->global_seqno - 1; | ||
722 | } | 760 | } |
723 | 761 | ||
724 | engine->hangcheck.stalled = true; | 762 | err = i915_reset_engine(engine, NULL); |
725 | engine->hangcheck.seqno = | ||
726 | intel_engine_get_seqno(engine); | ||
727 | |||
728 | err = i915_reset_engine(engine, I915_RESET_QUIET); | ||
729 | if (err) { | 763 | if (err) { |
730 | pr_err("i915_reset_engine(%s:%s) failed, err=%d\n", | 764 | pr_err("i915_reset_engine(%s:%s): failed, err=%d\n", |
731 | engine->name, active ? "active" : "idle", err); | 765 | engine->name, test_name, err); |
732 | break; | 766 | break; |
733 | } | 767 | } |
734 | 768 | ||
735 | engine->hangcheck.stalled = false; | ||
736 | count++; | 769 | count++; |
770 | |||
771 | if (rq) { | ||
772 | i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); | ||
773 | i915_request_put(rq); | ||
774 | } | ||
737 | } while (time_before(jiffies, end_time)); | 775 | } while (time_before(jiffies, end_time)); |
738 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 776 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
739 | pr_info("i915_reset_engine(%s:%s): %lu resets\n", | 777 | pr_info("i915_reset_engine(%s:%s): %lu resets\n", |
740 | engine->name, active ? "active" : "idle", count); | 778 | engine->name, test_name, count); |
741 | 779 | ||
742 | if (i915_reset_engine_count(&i915->gpu_error, engine) - | 780 | reported = i915_reset_engine_count(&i915->gpu_error, engine); |
743 | resets[engine->id] != (active ? count : 0)) { | 781 | reported -= threads[engine->id].resets; |
744 | pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu\n", | 782 | if (reported != (flags & TEST_ACTIVE ? count : 0)) { |
745 | engine->name, active ? "active" : "idle", count, | 783 | pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu, expected %lu reported\n", |
746 | i915_reset_engine_count(&i915->gpu_error, | 784 | engine->name, test_name, count, reported, |
747 | engine) - resets[engine->id]); | 785 | (flags & TEST_ACTIVE ? count : 0)); |
748 | if (!err) | 786 | if (!err) |
749 | err = -EINVAL; | 787 | err = -EINVAL; |
750 | } | 788 | } |
@@ -753,24 +791,26 @@ unwind: | |||
753 | for_each_engine(other, i915, tmp) { | 791 | for_each_engine(other, i915, tmp) { |
754 | int ret; | 792 | int ret; |
755 | 793 | ||
756 | if (!threads[tmp]) | 794 | if (!threads[tmp].task) |
757 | continue; | 795 | continue; |
758 | 796 | ||
759 | ret = kthread_stop(threads[tmp]); | 797 | ret = kthread_stop(threads[tmp].task); |
760 | if (ret) { | 798 | if (ret) { |
761 | pr_err("kthread for other engine %s failed, err=%d\n", | 799 | pr_err("kthread for other engine %s failed, err=%d\n", |
762 | other->name, ret); | 800 | other->name, ret); |
763 | if (!err) | 801 | if (!err) |
764 | err = ret; | 802 | err = ret; |
765 | } | 803 | } |
766 | put_task_struct(threads[tmp]); | 804 | put_task_struct(threads[tmp].task); |
767 | 805 | ||
768 | if (resets[tmp] != i915_reset_engine_count(&i915->gpu_error, | 806 | if (other != engine && |
769 | other)) { | 807 | threads[tmp].resets != |
808 | i915_reset_engine_count(&i915->gpu_error, other)) { | ||
770 | pr_err("Innocent engine %s was reset (count=%ld)\n", | 809 | pr_err("Innocent engine %s was reset (count=%ld)\n", |
771 | other->name, | 810 | other->name, |
772 | i915_reset_engine_count(&i915->gpu_error, | 811 | i915_reset_engine_count(&i915->gpu_error, |
773 | other) - resets[tmp]); | 812 | other) - |
813 | threads[tmp].resets); | ||
774 | if (!err) | 814 | if (!err) |
775 | err = -EINVAL; | 815 | err = -EINVAL; |
776 | } | 816 | } |
@@ -794,7 +834,7 @@ unwind: | |||
794 | if (i915_terminally_wedged(&i915->gpu_error)) | 834 | if (i915_terminally_wedged(&i915->gpu_error)) |
795 | err = -EIO; | 835 | err = -EIO; |
796 | 836 | ||
797 | if (active) { | 837 | if (flags & TEST_ACTIVE) { |
798 | mutex_lock(&i915->drm.struct_mutex); | 838 | mutex_lock(&i915->drm.struct_mutex); |
799 | hang_fini(&h); | 839 | hang_fini(&h); |
800 | mutex_unlock(&i915->drm.struct_mutex); | 840 | mutex_unlock(&i915->drm.struct_mutex); |
@@ -803,27 +843,56 @@ unwind: | |||
803 | return err; | 843 | return err; |
804 | } | 844 | } |
805 | 845 | ||
806 | static int igt_reset_idle_engine_others(void *arg) | 846 | static int igt_reset_engines(void *arg) |
807 | { | 847 | { |
808 | return __igt_reset_engine_others(arg, false); | 848 | static const struct { |
809 | } | 849 | const char *name; |
850 | unsigned int flags; | ||
851 | } phases[] = { | ||
852 | { "idle", 0 }, | ||
853 | { "active", TEST_ACTIVE }, | ||
854 | { "others-idle", TEST_OTHERS }, | ||
855 | { "others-active", TEST_OTHERS | TEST_ACTIVE }, | ||
856 | { | ||
857 | "others-priority", | ||
858 | TEST_OTHERS | TEST_ACTIVE | TEST_PRIORITY | ||
859 | }, | ||
860 | { | ||
861 | "self-priority", | ||
862 | TEST_OTHERS | TEST_ACTIVE | TEST_PRIORITY | TEST_SELF, | ||
863 | }, | ||
864 | { } | ||
865 | }; | ||
866 | struct drm_i915_private *i915 = arg; | ||
867 | typeof(*phases) *p; | ||
868 | int err; | ||
810 | 869 | ||
811 | static int igt_reset_active_engine_others(void *arg) | 870 | for (p = phases; p->name; p++) { |
812 | { | 871 | if (p->flags & TEST_PRIORITY) { |
813 | return __igt_reset_engine_others(arg, true); | 872 | if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY)) |
873 | continue; | ||
874 | } | ||
875 | |||
876 | err = __igt_reset_engines(arg, p->name, p->flags); | ||
877 | if (err) | ||
878 | return err; | ||
879 | } | ||
880 | |||
881 | return 0; | ||
814 | } | 882 | } |
815 | 883 | ||
816 | static u32 fake_hangcheck(struct i915_request *rq) | 884 | static u32 fake_hangcheck(struct i915_request *rq, u32 mask) |
817 | { | 885 | { |
818 | u32 reset_count; | 886 | struct i915_gpu_error *error = &rq->i915->gpu_error; |
887 | u32 reset_count = i915_reset_count(error); | ||
819 | 888 | ||
820 | rq->engine->hangcheck.stalled = true; | 889 | error->stalled_mask = mask; |
821 | rq->engine->hangcheck.seqno = intel_engine_get_seqno(rq->engine); | ||
822 | 890 | ||
823 | reset_count = i915_reset_count(&rq->i915->gpu_error); | 891 | /* set_bit() must be after we have setup the backchannel (mask) */ |
892 | smp_mb__before_atomic(); | ||
893 | set_bit(I915_RESET_HANDOFF, &error->flags); | ||
824 | 894 | ||
825 | set_bit(I915_RESET_HANDOFF, &rq->i915->gpu_error.flags); | 895 | wake_up_all(&error->wait_queue); |
826 | wake_up_all(&rq->i915->gpu_error.wait_queue); | ||
827 | 896 | ||
828 | return reset_count; | 897 | return reset_count; |
829 | } | 898 | } |
@@ -858,21 +927,20 @@ static int igt_wait_reset(void *arg) | |||
858 | i915_request_get(rq); | 927 | i915_request_get(rq); |
859 | __i915_request_add(rq, true); | 928 | __i915_request_add(rq, true); |
860 | 929 | ||
861 | if (!wait_for_hang(&h, rq)) { | 930 | if (!wait_until_running(&h, rq)) { |
862 | struct drm_printer p = drm_info_printer(i915->drm.dev); | 931 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
863 | 932 | ||
864 | pr_err("%s: Failed to start request %x, at %x\n", | 933 | pr_err("%s: Failed to start request %x, at %x\n", |
865 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); | 934 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); |
866 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); | 935 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); |
867 | 936 | ||
868 | i915_reset(i915, 0); | ||
869 | i915_gem_set_wedged(i915); | 937 | i915_gem_set_wedged(i915); |
870 | 938 | ||
871 | err = -EIO; | 939 | err = -EIO; |
872 | goto out_rq; | 940 | goto out_rq; |
873 | } | 941 | } |
874 | 942 | ||
875 | reset_count = fake_hangcheck(rq); | 943 | reset_count = fake_hangcheck(rq, ALL_ENGINES); |
876 | 944 | ||
877 | timeout = i915_request_wait(rq, I915_WAIT_LOCKED, 10); | 945 | timeout = i915_request_wait(rq, I915_WAIT_LOCKED, 10); |
878 | if (timeout < 0) { | 946 | if (timeout < 0) { |
@@ -903,6 +971,23 @@ unlock: | |||
903 | return err; | 971 | return err; |
904 | } | 972 | } |
905 | 973 | ||
974 | static int wait_for_others(struct drm_i915_private *i915, | ||
975 | struct intel_engine_cs *exclude) | ||
976 | { | ||
977 | struct intel_engine_cs *engine; | ||
978 | enum intel_engine_id id; | ||
979 | |||
980 | for_each_engine(engine, i915, id) { | ||
981 | if (engine == exclude) | ||
982 | continue; | ||
983 | |||
984 | if (wait_for(intel_engine_is_idle(engine), 10)) | ||
985 | return -EIO; | ||
986 | } | ||
987 | |||
988 | return 0; | ||
989 | } | ||
990 | |||
906 | static int igt_reset_queue(void *arg) | 991 | static int igt_reset_queue(void *arg) |
907 | { | 992 | { |
908 | struct drm_i915_private *i915 = arg; | 993 | struct drm_i915_private *i915 = arg; |
@@ -951,27 +1036,49 @@ static int igt_reset_queue(void *arg) | |||
951 | i915_request_get(rq); | 1036 | i915_request_get(rq); |
952 | __i915_request_add(rq, true); | 1037 | __i915_request_add(rq, true); |
953 | 1038 | ||
954 | if (!wait_for_hang(&h, prev)) { | 1039 | /* |
1040 | * XXX We don't handle resetting the kernel context | ||
1041 | * very well. If we trigger a device reset twice in | ||
1042 | * quick succession while the kernel context is | ||
1043 | * executing, we may end up skipping the breadcrumb. | ||
1044 | * This is really only a problem for the selftest as | ||
1045 | * normally there is a large interlude between resets | ||
1046 | * (hangcheck), or we focus on resetting just one | ||
1047 | * engine and so avoid repeatedly resetting innocents. | ||
1048 | */ | ||
1049 | err = wait_for_others(i915, engine); | ||
1050 | if (err) { | ||
1051 | pr_err("%s(%s): Failed to idle other inactive engines after device reset\n", | ||
1052 | __func__, engine->name); | ||
1053 | i915_request_put(rq); | ||
1054 | i915_request_put(prev); | ||
1055 | |||
1056 | GEM_TRACE_DUMP(); | ||
1057 | i915_gem_set_wedged(i915); | ||
1058 | goto fini; | ||
1059 | } | ||
1060 | |||
1061 | if (!wait_until_running(&h, prev)) { | ||
955 | struct drm_printer p = drm_info_printer(i915->drm.dev); | 1062 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
956 | 1063 | ||
957 | pr_err("%s: Failed to start request %x, at %x\n", | 1064 | pr_err("%s(%s): Failed to start request %x, at %x\n", |
958 | __func__, prev->fence.seqno, hws_seqno(&h, prev)); | 1065 | __func__, engine->name, |
959 | intel_engine_dump(prev->engine, &p, | 1066 | prev->fence.seqno, hws_seqno(&h, prev)); |
960 | "%s\n", prev->engine->name); | 1067 | intel_engine_dump(engine, &p, |
1068 | "%s\n", engine->name); | ||
961 | 1069 | ||
962 | i915_request_put(rq); | 1070 | i915_request_put(rq); |
963 | i915_request_put(prev); | 1071 | i915_request_put(prev); |
964 | 1072 | ||
965 | i915_reset(i915, 0); | ||
966 | i915_gem_set_wedged(i915); | 1073 | i915_gem_set_wedged(i915); |
967 | 1074 | ||
968 | err = -EIO; | 1075 | err = -EIO; |
969 | goto fini; | 1076 | goto fini; |
970 | } | 1077 | } |
971 | 1078 | ||
972 | reset_count = fake_hangcheck(prev); | 1079 | reset_count = fake_hangcheck(prev, ENGINE_MASK(id)); |
973 | 1080 | ||
974 | i915_reset(i915, I915_RESET_QUIET); | 1081 | i915_reset(i915, ENGINE_MASK(id), NULL); |
975 | 1082 | ||
976 | GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, | 1083 | GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, |
977 | &i915->gpu_error.flags)); | 1084 | &i915->gpu_error.flags)); |
@@ -1044,7 +1151,7 @@ static int igt_handle_error(void *arg) | |||
1044 | if (!intel_has_reset_engine(i915)) | 1151 | if (!intel_has_reset_engine(i915)) |
1045 | return 0; | 1152 | return 0; |
1046 | 1153 | ||
1047 | if (!intel_engine_can_store_dword(i915->engine[RCS])) | 1154 | if (!engine || !intel_engine_can_store_dword(engine)) |
1048 | return 0; | 1155 | return 0; |
1049 | 1156 | ||
1050 | mutex_lock(&i915->drm.struct_mutex); | 1157 | mutex_lock(&i915->drm.struct_mutex); |
@@ -1062,14 +1169,13 @@ static int igt_handle_error(void *arg) | |||
1062 | i915_request_get(rq); | 1169 | i915_request_get(rq); |
1063 | __i915_request_add(rq, true); | 1170 | __i915_request_add(rq, true); |
1064 | 1171 | ||
1065 | if (!wait_for_hang(&h, rq)) { | 1172 | if (!wait_until_running(&h, rq)) { |
1066 | struct drm_printer p = drm_info_printer(i915->drm.dev); | 1173 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
1067 | 1174 | ||
1068 | pr_err("%s: Failed to start request %x, at %x\n", | 1175 | pr_err("%s: Failed to start request %x, at %x\n", |
1069 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); | 1176 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); |
1070 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); | 1177 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); |
1071 | 1178 | ||
1072 | i915_reset(i915, 0); | ||
1073 | i915_gem_set_wedged(i915); | 1179 | i915_gem_set_wedged(i915); |
1074 | 1180 | ||
1075 | err = -EIO; | 1181 | err = -EIO; |
@@ -1081,10 +1187,7 @@ static int igt_handle_error(void *arg) | |||
1081 | /* Temporarily disable error capture */ | 1187 | /* Temporarily disable error capture */ |
1082 | error = xchg(&i915->gpu_error.first_error, (void *)-1); | 1188 | error = xchg(&i915->gpu_error.first_error, (void *)-1); |
1083 | 1189 | ||
1084 | engine->hangcheck.stalled = true; | 1190 | i915_handle_error(i915, ENGINE_MASK(engine->id), 0, NULL); |
1085 | engine->hangcheck.seqno = intel_engine_get_seqno(engine); | ||
1086 | |||
1087 | i915_handle_error(i915, intel_engine_flag(engine), "%s", __func__); | ||
1088 | 1191 | ||
1089 | xchg(&i915->gpu_error.first_error, error); | 1192 | xchg(&i915->gpu_error.first_error, error); |
1090 | 1193 | ||
@@ -1112,8 +1215,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) | |||
1112 | SUBTEST(igt_hang_sanitycheck), | 1215 | SUBTEST(igt_hang_sanitycheck), |
1113 | SUBTEST(igt_reset_idle_engine), | 1216 | SUBTEST(igt_reset_idle_engine), |
1114 | SUBTEST(igt_reset_active_engine), | 1217 | SUBTEST(igt_reset_active_engine), |
1115 | SUBTEST(igt_reset_idle_engine_others), | 1218 | SUBTEST(igt_reset_engines), |
1116 | SUBTEST(igt_reset_active_engine_others), | ||
1117 | SUBTEST(igt_wait_reset), | 1219 | SUBTEST(igt_wait_reset), |
1118 | SUBTEST(igt_reset_queue), | 1220 | SUBTEST(igt_reset_queue), |
1119 | SUBTEST(igt_handle_error), | 1221 | SUBTEST(igt_handle_error), |
@@ -1129,6 +1231,10 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) | |||
1129 | 1231 | ||
1130 | err = i915_subtests(tests, i915); | 1232 | err = i915_subtests(tests, i915); |
1131 | 1233 | ||
1234 | mutex_lock(&i915->drm.struct_mutex); | ||
1235 | flush_test(i915, I915_WAIT_LOCKED); | ||
1236 | mutex_unlock(&i915->drm.struct_mutex); | ||
1237 | |||
1132 | i915_modparams.enable_hangcheck = saved_hangcheck; | 1238 | i915_modparams.enable_hangcheck = saved_hangcheck; |
1133 | intel_runtime_pm_put(i915); | 1239 | intel_runtime_pm_put(i915); |
1134 | 1240 | ||
diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c new file mode 100644 index 000000000000..0481e2e01146 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c | |||
@@ -0,0 +1,507 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "../i915_selftest.h" | ||
8 | |||
9 | #include "mock_context.h" | ||
10 | |||
11 | struct spinner { | ||
12 | struct drm_i915_private *i915; | ||
13 | struct drm_i915_gem_object *hws; | ||
14 | struct drm_i915_gem_object *obj; | ||
15 | u32 *batch; | ||
16 | void *seqno; | ||
17 | }; | ||
18 | |||
19 | static int spinner_init(struct spinner *spin, struct drm_i915_private *i915) | ||
20 | { | ||
21 | unsigned int mode; | ||
22 | void *vaddr; | ||
23 | int err; | ||
24 | |||
25 | GEM_BUG_ON(INTEL_GEN(i915) < 8); | ||
26 | |||
27 | memset(spin, 0, sizeof(*spin)); | ||
28 | spin->i915 = i915; | ||
29 | |||
30 | spin->hws = i915_gem_object_create_internal(i915, PAGE_SIZE); | ||
31 | if (IS_ERR(spin->hws)) { | ||
32 | err = PTR_ERR(spin->hws); | ||
33 | goto err; | ||
34 | } | ||
35 | |||
36 | spin->obj = i915_gem_object_create_internal(i915, PAGE_SIZE); | ||
37 | if (IS_ERR(spin->obj)) { | ||
38 | err = PTR_ERR(spin->obj); | ||
39 | goto err_hws; | ||
40 | } | ||
41 | |||
42 | i915_gem_object_set_cache_level(spin->hws, I915_CACHE_LLC); | ||
43 | vaddr = i915_gem_object_pin_map(spin->hws, I915_MAP_WB); | ||
44 | if (IS_ERR(vaddr)) { | ||
45 | err = PTR_ERR(vaddr); | ||
46 | goto err_obj; | ||
47 | } | ||
48 | spin->seqno = memset(vaddr, 0xff, PAGE_SIZE); | ||
49 | |||
50 | mode = HAS_LLC(i915) ? I915_MAP_WB : I915_MAP_WC; | ||
51 | vaddr = i915_gem_object_pin_map(spin->obj, mode); | ||
52 | if (IS_ERR(vaddr)) { | ||
53 | err = PTR_ERR(vaddr); | ||
54 | goto err_unpin_hws; | ||
55 | } | ||
56 | spin->batch = vaddr; | ||
57 | |||
58 | return 0; | ||
59 | |||
60 | err_unpin_hws: | ||
61 | i915_gem_object_unpin_map(spin->hws); | ||
62 | err_obj: | ||
63 | i915_gem_object_put(spin->obj); | ||
64 | err_hws: | ||
65 | i915_gem_object_put(spin->hws); | ||
66 | err: | ||
67 | return err; | ||
68 | } | ||
69 | |||
70 | static unsigned int seqno_offset(u64 fence) | ||
71 | { | ||
72 | return offset_in_page(sizeof(u32) * fence); | ||
73 | } | ||
74 | |||
75 | static u64 hws_address(const struct i915_vma *hws, | ||
76 | const struct i915_request *rq) | ||
77 | { | ||
78 | return hws->node.start + seqno_offset(rq->fence.context); | ||
79 | } | ||
80 | |||
81 | static int emit_recurse_batch(struct spinner *spin, | ||
82 | struct i915_request *rq, | ||
83 | u32 arbitration_command) | ||
84 | { | ||
85 | struct i915_address_space *vm = &rq->ctx->ppgtt->base; | ||
86 | struct i915_vma *hws, *vma; | ||
87 | u32 *batch; | ||
88 | int err; | ||
89 | |||
90 | vma = i915_vma_instance(spin->obj, vm, NULL); | ||
91 | if (IS_ERR(vma)) | ||
92 | return PTR_ERR(vma); | ||
93 | |||
94 | hws = i915_vma_instance(spin->hws, vm, NULL); | ||
95 | if (IS_ERR(hws)) | ||
96 | return PTR_ERR(hws); | ||
97 | |||
98 | err = i915_vma_pin(vma, 0, 0, PIN_USER); | ||
99 | if (err) | ||
100 | return err; | ||
101 | |||
102 | err = i915_vma_pin(hws, 0, 0, PIN_USER); | ||
103 | if (err) | ||
104 | goto unpin_vma; | ||
105 | |||
106 | i915_vma_move_to_active(vma, rq, 0); | ||
107 | if (!i915_gem_object_has_active_reference(vma->obj)) { | ||
108 | i915_gem_object_get(vma->obj); | ||
109 | i915_gem_object_set_active_reference(vma->obj); | ||
110 | } | ||
111 | |||
112 | i915_vma_move_to_active(hws, rq, 0); | ||
113 | if (!i915_gem_object_has_active_reference(hws->obj)) { | ||
114 | i915_gem_object_get(hws->obj); | ||
115 | i915_gem_object_set_active_reference(hws->obj); | ||
116 | } | ||
117 | |||
118 | batch = spin->batch; | ||
119 | |||
120 | *batch++ = MI_STORE_DWORD_IMM_GEN4; | ||
121 | *batch++ = lower_32_bits(hws_address(hws, rq)); | ||
122 | *batch++ = upper_32_bits(hws_address(hws, rq)); | ||
123 | *batch++ = rq->fence.seqno; | ||
124 | |||
125 | *batch++ = arbitration_command; | ||
126 | |||
127 | *batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; | ||
128 | *batch++ = lower_32_bits(vma->node.start); | ||
129 | *batch++ = upper_32_bits(vma->node.start); | ||
130 | *batch++ = MI_BATCH_BUFFER_END; /* not reached */ | ||
131 | |||
132 | i915_gem_chipset_flush(spin->i915); | ||
133 | |||
134 | err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); | ||
135 | |||
136 | i915_vma_unpin(hws); | ||
137 | unpin_vma: | ||
138 | i915_vma_unpin(vma); | ||
139 | return err; | ||
140 | } | ||
141 | |||
142 | static struct i915_request * | ||
143 | spinner_create_request(struct spinner *spin, | ||
144 | struct i915_gem_context *ctx, | ||
145 | struct intel_engine_cs *engine, | ||
146 | u32 arbitration_command) | ||
147 | { | ||
148 | struct i915_request *rq; | ||
149 | int err; | ||
150 | |||
151 | rq = i915_request_alloc(engine, ctx); | ||
152 | if (IS_ERR(rq)) | ||
153 | return rq; | ||
154 | |||
155 | err = emit_recurse_batch(spin, rq, arbitration_command); | ||
156 | if (err) { | ||
157 | __i915_request_add(rq, false); | ||
158 | return ERR_PTR(err); | ||
159 | } | ||
160 | |||
161 | return rq; | ||
162 | } | ||
163 | |||
164 | static u32 hws_seqno(const struct spinner *spin, const struct i915_request *rq) | ||
165 | { | ||
166 | u32 *seqno = spin->seqno + seqno_offset(rq->fence.context); | ||
167 | |||
168 | return READ_ONCE(*seqno); | ||
169 | } | ||
170 | |||
171 | struct wedge_me { | ||
172 | struct delayed_work work; | ||
173 | struct drm_i915_private *i915; | ||
174 | const void *symbol; | ||
175 | }; | ||
176 | |||
177 | static void wedge_me(struct work_struct *work) | ||
178 | { | ||
179 | struct wedge_me *w = container_of(work, typeof(*w), work.work); | ||
180 | |||
181 | pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); | ||
182 | |||
183 | GEM_TRACE("%pS timed out.\n", w->symbol); | ||
184 | GEM_TRACE_DUMP(); | ||
185 | |||
186 | i915_gem_set_wedged(w->i915); | ||
187 | } | ||
188 | |||
189 | static void __init_wedge(struct wedge_me *w, | ||
190 | struct drm_i915_private *i915, | ||
191 | long timeout, | ||
192 | const void *symbol) | ||
193 | { | ||
194 | w->i915 = i915; | ||
195 | w->symbol = symbol; | ||
196 | |||
197 | INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me); | ||
198 | schedule_delayed_work(&w->work, timeout); | ||
199 | } | ||
200 | |||
201 | static void __fini_wedge(struct wedge_me *w) | ||
202 | { | ||
203 | cancel_delayed_work_sync(&w->work); | ||
204 | destroy_delayed_work_on_stack(&w->work); | ||
205 | w->i915 = NULL; | ||
206 | } | ||
207 | |||
208 | #define wedge_on_timeout(W, DEV, TIMEOUT) \ | ||
209 | for (__init_wedge((W), (DEV), (TIMEOUT), __builtin_return_address(0)); \ | ||
210 | (W)->i915; \ | ||
211 | __fini_wedge((W))) | ||
212 | |||
213 | static noinline int | ||
214 | flush_test(struct drm_i915_private *i915, unsigned int flags) | ||
215 | { | ||
216 | struct wedge_me w; | ||
217 | |||
218 | cond_resched(); | ||
219 | |||
220 | wedge_on_timeout(&w, i915, HZ) | ||
221 | i915_gem_wait_for_idle(i915, flags); | ||
222 | |||
223 | return i915_terminally_wedged(&i915->gpu_error) ? -EIO : 0; | ||
224 | } | ||
225 | |||
226 | static void spinner_end(struct spinner *spin) | ||
227 | { | ||
228 | *spin->batch = MI_BATCH_BUFFER_END; | ||
229 | i915_gem_chipset_flush(spin->i915); | ||
230 | } | ||
231 | |||
232 | static void spinner_fini(struct spinner *spin) | ||
233 | { | ||
234 | spinner_end(spin); | ||
235 | |||
236 | i915_gem_object_unpin_map(spin->obj); | ||
237 | i915_gem_object_put(spin->obj); | ||
238 | |||
239 | i915_gem_object_unpin_map(spin->hws); | ||
240 | i915_gem_object_put(spin->hws); | ||
241 | } | ||
242 | |||
243 | static bool wait_for_spinner(struct spinner *spin, struct i915_request *rq) | ||
244 | { | ||
245 | if (!wait_event_timeout(rq->execute, | ||
246 | READ_ONCE(rq->global_seqno), | ||
247 | msecs_to_jiffies(10))) | ||
248 | return false; | ||
249 | |||
250 | return !(wait_for_us(i915_seqno_passed(hws_seqno(spin, rq), | ||
251 | rq->fence.seqno), | ||
252 | 10) && | ||
253 | wait_for(i915_seqno_passed(hws_seqno(spin, rq), | ||
254 | rq->fence.seqno), | ||
255 | 1000)); | ||
256 | } | ||
257 | |||
258 | static int live_sanitycheck(void *arg) | ||
259 | { | ||
260 | struct drm_i915_private *i915 = arg; | ||
261 | struct intel_engine_cs *engine; | ||
262 | struct i915_gem_context *ctx; | ||
263 | enum intel_engine_id id; | ||
264 | struct spinner spin; | ||
265 | int err = -ENOMEM; | ||
266 | |||
267 | if (!HAS_LOGICAL_RING_CONTEXTS(i915)) | ||
268 | return 0; | ||
269 | |||
270 | mutex_lock(&i915->drm.struct_mutex); | ||
271 | |||
272 | if (spinner_init(&spin, i915)) | ||
273 | goto err_unlock; | ||
274 | |||
275 | ctx = kernel_context(i915); | ||
276 | if (!ctx) | ||
277 | goto err_spin; | ||
278 | |||
279 | for_each_engine(engine, i915, id) { | ||
280 | struct i915_request *rq; | ||
281 | |||
282 | rq = spinner_create_request(&spin, ctx, engine, MI_NOOP); | ||
283 | if (IS_ERR(rq)) { | ||
284 | err = PTR_ERR(rq); | ||
285 | goto err_ctx; | ||
286 | } | ||
287 | |||
288 | i915_request_add(rq); | ||
289 | if (!wait_for_spinner(&spin, rq)) { | ||
290 | GEM_TRACE("spinner failed to start\n"); | ||
291 | GEM_TRACE_DUMP(); | ||
292 | i915_gem_set_wedged(i915); | ||
293 | err = -EIO; | ||
294 | goto err_ctx; | ||
295 | } | ||
296 | |||
297 | spinner_end(&spin); | ||
298 | if (flush_test(i915, I915_WAIT_LOCKED)) { | ||
299 | err = -EIO; | ||
300 | goto err_ctx; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | err = 0; | ||
305 | err_ctx: | ||
306 | kernel_context_close(ctx); | ||
307 | err_spin: | ||
308 | spinner_fini(&spin); | ||
309 | err_unlock: | ||
310 | flush_test(i915, I915_WAIT_LOCKED); | ||
311 | mutex_unlock(&i915->drm.struct_mutex); | ||
312 | return err; | ||
313 | } | ||
314 | |||
315 | static int live_preempt(void *arg) | ||
316 | { | ||
317 | struct drm_i915_private *i915 = arg; | ||
318 | struct i915_gem_context *ctx_hi, *ctx_lo; | ||
319 | struct spinner spin_hi, spin_lo; | ||
320 | struct intel_engine_cs *engine; | ||
321 | enum intel_engine_id id; | ||
322 | int err = -ENOMEM; | ||
323 | |||
324 | if (!HAS_LOGICAL_RING_PREEMPTION(i915)) | ||
325 | return 0; | ||
326 | |||
327 | mutex_lock(&i915->drm.struct_mutex); | ||
328 | |||
329 | if (spinner_init(&spin_hi, i915)) | ||
330 | goto err_unlock; | ||
331 | |||
332 | if (spinner_init(&spin_lo, i915)) | ||
333 | goto err_spin_hi; | ||
334 | |||
335 | ctx_hi = kernel_context(i915); | ||
336 | if (!ctx_hi) | ||
337 | goto err_spin_lo; | ||
338 | ctx_hi->priority = I915_CONTEXT_MAX_USER_PRIORITY; | ||
339 | |||
340 | ctx_lo = kernel_context(i915); | ||
341 | if (!ctx_lo) | ||
342 | goto err_ctx_hi; | ||
343 | ctx_lo->priority = I915_CONTEXT_MIN_USER_PRIORITY; | ||
344 | |||
345 | for_each_engine(engine, i915, id) { | ||
346 | struct i915_request *rq; | ||
347 | |||
348 | rq = spinner_create_request(&spin_lo, ctx_lo, engine, | ||
349 | MI_ARB_CHECK); | ||
350 | if (IS_ERR(rq)) { | ||
351 | err = PTR_ERR(rq); | ||
352 | goto err_ctx_lo; | ||
353 | } | ||
354 | |||
355 | i915_request_add(rq); | ||
356 | if (!wait_for_spinner(&spin_lo, rq)) { | ||
357 | GEM_TRACE("lo spinner failed to start\n"); | ||
358 | GEM_TRACE_DUMP(); | ||
359 | i915_gem_set_wedged(i915); | ||
360 | err = -EIO; | ||
361 | goto err_ctx_lo; | ||
362 | } | ||
363 | |||
364 | rq = spinner_create_request(&spin_hi, ctx_hi, engine, | ||
365 | MI_ARB_CHECK); | ||
366 | if (IS_ERR(rq)) { | ||
367 | spinner_end(&spin_lo); | ||
368 | err = PTR_ERR(rq); | ||
369 | goto err_ctx_lo; | ||
370 | } | ||
371 | |||
372 | i915_request_add(rq); | ||
373 | if (!wait_for_spinner(&spin_hi, rq)) { | ||
374 | GEM_TRACE("hi spinner failed to start\n"); | ||
375 | GEM_TRACE_DUMP(); | ||
376 | i915_gem_set_wedged(i915); | ||
377 | err = -EIO; | ||
378 | goto err_ctx_lo; | ||
379 | } | ||
380 | |||
381 | spinner_end(&spin_hi); | ||
382 | spinner_end(&spin_lo); | ||
383 | if (flush_test(i915, I915_WAIT_LOCKED)) { | ||
384 | err = -EIO; | ||
385 | goto err_ctx_lo; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | err = 0; | ||
390 | err_ctx_lo: | ||
391 | kernel_context_close(ctx_lo); | ||
392 | err_ctx_hi: | ||
393 | kernel_context_close(ctx_hi); | ||
394 | err_spin_lo: | ||
395 | spinner_fini(&spin_lo); | ||
396 | err_spin_hi: | ||
397 | spinner_fini(&spin_hi); | ||
398 | err_unlock: | ||
399 | flush_test(i915, I915_WAIT_LOCKED); | ||
400 | mutex_unlock(&i915->drm.struct_mutex); | ||
401 | return err; | ||
402 | } | ||
403 | |||
404 | static int live_late_preempt(void *arg) | ||
405 | { | ||
406 | struct drm_i915_private *i915 = arg; | ||
407 | struct i915_gem_context *ctx_hi, *ctx_lo; | ||
408 | struct spinner spin_hi, spin_lo; | ||
409 | struct intel_engine_cs *engine; | ||
410 | enum intel_engine_id id; | ||
411 | int err = -ENOMEM; | ||
412 | |||
413 | if (!HAS_LOGICAL_RING_PREEMPTION(i915)) | ||
414 | return 0; | ||
415 | |||
416 | mutex_lock(&i915->drm.struct_mutex); | ||
417 | |||
418 | if (spinner_init(&spin_hi, i915)) | ||
419 | goto err_unlock; | ||
420 | |||
421 | if (spinner_init(&spin_lo, i915)) | ||
422 | goto err_spin_hi; | ||
423 | |||
424 | ctx_hi = kernel_context(i915); | ||
425 | if (!ctx_hi) | ||
426 | goto err_spin_lo; | ||
427 | |||
428 | ctx_lo = kernel_context(i915); | ||
429 | if (!ctx_lo) | ||
430 | goto err_ctx_hi; | ||
431 | |||
432 | for_each_engine(engine, i915, id) { | ||
433 | struct i915_request *rq; | ||
434 | |||
435 | rq = spinner_create_request(&spin_lo, ctx_lo, engine, | ||
436 | MI_ARB_CHECK); | ||
437 | if (IS_ERR(rq)) { | ||
438 | err = PTR_ERR(rq); | ||
439 | goto err_ctx_lo; | ||
440 | } | ||
441 | |||
442 | i915_request_add(rq); | ||
443 | if (!wait_for_spinner(&spin_lo, rq)) { | ||
444 | pr_err("First context failed to start\n"); | ||
445 | goto err_wedged; | ||
446 | } | ||
447 | |||
448 | rq = spinner_create_request(&spin_hi, ctx_hi, engine, MI_NOOP); | ||
449 | if (IS_ERR(rq)) { | ||
450 | spinner_end(&spin_lo); | ||
451 | err = PTR_ERR(rq); | ||
452 | goto err_ctx_lo; | ||
453 | } | ||
454 | |||
455 | i915_request_add(rq); | ||
456 | if (wait_for_spinner(&spin_hi, rq)) { | ||
457 | pr_err("Second context overtook first?\n"); | ||
458 | goto err_wedged; | ||
459 | } | ||
460 | |||
461 | engine->schedule(rq, I915_PRIORITY_MAX); | ||
462 | |||
463 | if (!wait_for_spinner(&spin_hi, rq)) { | ||
464 | pr_err("High priority context failed to preempt the low priority context\n"); | ||
465 | GEM_TRACE_DUMP(); | ||
466 | goto err_wedged; | ||
467 | } | ||
468 | |||
469 | spinner_end(&spin_hi); | ||
470 | spinner_end(&spin_lo); | ||
471 | if (flush_test(i915, I915_WAIT_LOCKED)) { | ||
472 | err = -EIO; | ||
473 | goto err_ctx_lo; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | err = 0; | ||
478 | err_ctx_lo: | ||
479 | kernel_context_close(ctx_lo); | ||
480 | err_ctx_hi: | ||
481 | kernel_context_close(ctx_hi); | ||
482 | err_spin_lo: | ||
483 | spinner_fini(&spin_lo); | ||
484 | err_spin_hi: | ||
485 | spinner_fini(&spin_hi); | ||
486 | err_unlock: | ||
487 | flush_test(i915, I915_WAIT_LOCKED); | ||
488 | mutex_unlock(&i915->drm.struct_mutex); | ||
489 | return err; | ||
490 | |||
491 | err_wedged: | ||
492 | spinner_end(&spin_hi); | ||
493 | spinner_end(&spin_lo); | ||
494 | i915_gem_set_wedged(i915); | ||
495 | err = -EIO; | ||
496 | goto err_ctx_lo; | ||
497 | } | ||
498 | |||
499 | int intel_execlists_live_selftests(struct drm_i915_private *i915) | ||
500 | { | ||
501 | static const struct i915_subtest tests[] = { | ||
502 | SUBTEST(live_sanitycheck), | ||
503 | SUBTEST(live_preempt), | ||
504 | SUBTEST(live_late_preempt), | ||
505 | }; | ||
506 | return i915_subtests(tests, i915); | ||
507 | } | ||
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 62903bae0221..91c9bcd4196f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -478,6 +478,7 @@ | |||
478 | # define DP_PSR_FRAME_CAPTURE (1 << 3) | 478 | # define DP_PSR_FRAME_CAPTURE (1 << 3) |
479 | # define DP_PSR_SELECTIVE_UPDATE (1 << 4) | 479 | # define DP_PSR_SELECTIVE_UPDATE (1 << 4) |
480 | # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) | 480 | # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) |
481 | # define DP_PSR_ENABLE_PSR2 (1 << 6) /* eDP 1.4a */ | ||
481 | 482 | ||
482 | #define DP_ADAPTER_CTRL 0x1a0 | 483 | #define DP_ADAPTER_CTRL 0x1a0 |
483 | # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) | 484 | # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) |
@@ -794,6 +795,15 @@ | |||
794 | # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) | 795 | # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) |
795 | # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_SHIFT 4 | 796 | # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_SHIFT 4 |
796 | 797 | ||
798 | #define DP_LAST_RECEIVED_PSR_SDP 0x200a /* eDP 1.2 */ | ||
799 | # define DP_PSR_STATE_BIT (1 << 0) /* eDP 1.2 */ | ||
800 | # define DP_UPDATE_RFB_BIT (1 << 1) /* eDP 1.2 */ | ||
801 | # define DP_CRC_VALID_BIT (1 << 2) /* eDP 1.2 */ | ||
802 | # define DP_SU_VALID (1 << 3) /* eDP 1.4 */ | ||
803 | # define DP_FIRST_SCAN_LINE_SU_REGION (1 << 4) /* eDP 1.4 */ | ||
804 | # define DP_LAST_SCAN_LINE_SU_REGION (1 << 5) /* eDP 1.4 */ | ||
805 | # define DP_Y_COORDINATE_VALID (1 << 6) /* eDP 1.4a */ | ||
806 | |||
797 | #define DP_RECEIVER_ALPM_STATUS 0x200b /* eDP 1.4 */ | 807 | #define DP_RECEIVER_ALPM_STATUS 0x200b /* eDP 1.4 */ |
798 | # define DP_ALPM_LOCK_TIMEOUT_ERROR (1 << 0) | 808 | # define DP_ALPM_LOCK_TIMEOUT_ERROR (1 << 0) |
799 | 809 | ||