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)
Unified · Split
| @@ -58,6 +58,12 @@ Intel GVT-g Host Support(vGPU device model) · 57 unmodified lines | ||
| 58 | 58 | .. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c |
| 59 | 59 | :internal: |
| 60 | 60 | |
| 61 | +Workarounds | |
| 62 | +----------- | |
| 63 | + | |
| 64 | +.. kernel-doc:: drivers/gpu/drm/i915/intel_workarounds.c | |
| 65 | + :doc: Hardware workarounds | |
| 66 | + | |
| 61 | 67 | Display Hardware Handling |
| 62 | 68 | ========================= |
| 63 | 69 | |
| @@ -249,6 +255,103 @@ Memory Management and Command Submission · 185 unmodified lines | ||
| 249 | 255 | This sections covers all things related to the GEM implementation in the |
| 250 | 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 | 355 | Batchbuffer Parsing |
| 253 | 356 | ------------------- |
| 254 | 357 | |
| @@ -267,6 +370,12 @@ Batchbuffer Pools · 12 unmodified lines | ||
| 267 | 370 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_batch_pool.c |
| 268 | 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 | 379 | Logical Rings, Logical Ring Contexts and Execlists |
| 271 | 380 | -------------------------------------------------- |
| 272 | 381 | |
| @@ -312,28 +421,14 @@ Object Tiling IOCTLs · 39 unmodified lines | ||
| 312 | 421 | .. kernel-doc:: drivers/gpu/drm/i915/i915_gem_tiling.c |
| 313 | 422 | :doc: buffer object tiling |
| 314 | 423 | |
| 315 | −Buffer Object Eviction | |
| 316 | −---------------------- | |
| 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 | −------------------------------ | |
| 424 | +WOPCM | |
| 425 | +===== | |
| 329 | 426 | |
| 330 | −This section documents the interface function for shrinking memory usage | |
| 331 | −of buffer object caches. Shrinking is used to make main memory | |
| 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. | |
| 427 | +WOPCM Layout | |
| 428 | +------------ | |
| 334 | 429 | |
| 335 | −.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_shrinker.c | |
| 336 | − :internal: | |
| 430 | +.. kernel-doc:: drivers/gpu/drm/i915/intel_wopcm.c | |
| 431 | + :doc: WOPCM Layout | |
| 337 | 432 | |
| 338 | 433 | GuC |
| 339 | 434 | === |
| @@ -359,6 +454,12 @@ GuC Firmware Layout · 19 unmodified lines | ||
| 359 | 454 | .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_fwif.h |
| 360 | 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 | 463 | Tracing |
| 363 | 464 | ======= |
| 364 | 465 | |
| @@ -25,6 +25,7 @@ config DRM_I915_DEBUG · 24 unmodified lines | ||
| 25 | 25 | select X86_MSR # used by igt/pm_rpm |
| 26 | 26 | select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) |
| 27 | 27 | select DRM_DEBUG_MM if DRM=y |
| 28 | + select STACKDEPOT if DRM=y # for DRM_DEBUG_MM | |
| 28 | 29 | select DRM_DEBUG_MM_SELFTEST |
| 29 | 30 | select SW_SYNC # signaling validation framework (igt/syncobj*) |
| 30 | 31 | select DRM_I915_SW_FENCE_DEBUG_OBJECTS |
| @@ -89,6 +90,18 @@ config DRM_I915_SW_FENCE_CHECK_DAG · 58 unmodified lines | ||
| 89 | 90 | |
| 90 | 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 | 105 | config DRM_I915_SELFTEST |
| 93 | 106 | bool "Enable selftests upon driver load" |
| 94 | 107 | depends on DRM_I915 |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | # Note the danger in using -Wall -Wextra is that when CI updates gcc we |
| 13 | 13 | # will most likely get a sudden build breakage... Hopefully we will fix |
| 14 | 14 | # new warnings before CI updates! |
| 15 | −subdir-ccflags-y := -Wall -Wextra | |
| 15 | +subdir-ccflags-y := -Wall -Wextra -Wvla | |
| 16 | 16 | subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) |
| 17 | 17 | subdir-ccflags-y += $(call cc-disable-warning, type-limits) |
| 18 | 18 | subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) |
| @@ -43,7 +43,8 @@ i915-y := i915_drv.o \ · 24 unmodified lines | ||
| 43 | 43 | intel_csr.o \ |
| 44 | 44 | intel_device_info.o \ |
| 45 | 45 | intel_pm.o \ |
| 46 | − intel_runtime_pm.o | |
| 46 | + intel_runtime_pm.o \ | |
| 47 | + intel_workarounds.o | |
| 47 | 48 | |
| 48 | 49 | i915-$(CONFIG_COMPAT) += i915_ioc32.o |
| 49 | 50 | i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o |
| @@ -79,7 +80,8 @@ i915-y += i915_cmd_parser.o \ · 29 unmodified lines | ||
| 79 | 80 | intel_lrc.o \ |
| 80 | 81 | intel_mocs.o \ |
| 81 | 82 | intel_ringbuffer.o \ |
| 82 | − intel_uncore.o | |
| 83 | + intel_uncore.o \ | |
| 84 | + intel_wopcm.o | |
| 83 | 85 | |
| 84 | 86 | # general-purpose microcontroller (GuC) support |
| 85 | 87 | i915-y += intel_uc.o \ |
| @@ -171,7 +173,8 @@ i915-y += i915_perf.o \ · 85 unmodified lines | ||
| 171 | 173 | i915_oa_glk.o \ |
| 172 | 174 | i915_oa_cflgt2.o \ |
| 173 | 175 | i915_oa_cflgt3.o \ |
| 174 | − i915_oa_cnl.o | |
| 176 | + i915_oa_cnl.o \ | |
| 177 | + i915_oa_icl.o | |
| 175 | 178 | |
| 176 | 179 | ifeq ($(CONFIG_DRM_I915_GVT),y) |
| 177 | 180 | i915-y += intel_gvt.o |
| @@ -122,18 +122,7 @@ static int vgpu_mmio_diff_show(struct seq_file *s, void *unused) · 121 unmodified lines | ||
| 122 | 122 | seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff); |
| 123 | 123 | return 0; |
| 124 | 124 | } |
| 125 | − | |
| 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 | −}; | |
| 125 | +DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff); | |
| 137 | 126 | |
| 138 | 127 | /** |
| 139 | 128 | * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU |
| @@ -1215,20 +1215,20 @@ static int i915_frequency_info(struct seq_file *m, void *unused) · 1214 unmodified lines | ||
| 1215 | 1215 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 : |
| 1216 | 1216 | rp_state_cap >> 16) & 0xff; |
| 1217 | 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 | 1219 | seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", |
| 1220 | 1220 | intel_gpu_freq(dev_priv, max_freq)); |
| 1221 | 1221 | |
| 1222 | 1222 | max_freq = (rp_state_cap & 0xff00) >> 8; |
| 1223 | 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 | 1225 | seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", |
| 1226 | 1226 | intel_gpu_freq(dev_priv, max_freq)); |
| 1227 | 1227 | |
| 1228 | 1228 | max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 16 : |
| 1229 | 1229 | rp_state_cap >> 0) & 0xff; |
| 1230 | 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 | 1232 | seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", |
| 1233 | 1233 | intel_gpu_freq(dev_priv, max_freq)); |
| 1234 | 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) · 561 unmodified lines | ||
| 1796 | 1796 | { |
| 1797 | 1797 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 1798 | 1798 | struct intel_rps *rps = &dev_priv->gt_pm.rps; |
| 1799 | − int ret = 0; | |
| 1800 | − int gpu_freq, ia_freq; | |
| 1801 | 1799 | unsigned int max_gpu_freq, min_gpu_freq; |
| 1800 | + int gpu_freq, ia_freq; | |
| 1801 | + int ret; | |
| 1802 | 1802 | |
| 1803 | 1803 | if (!HAS_LLC(dev_priv)) |
| 1804 | 1804 | return -ENODEV; |
| @@ -1809,13 +1809,12 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) · 4 unmodified lines | ||
| 1809 | 1809 | if (ret) |
| 1810 | 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 | 1815 | /* Convert GT frequency to 50 HZ units */ |
| 1814 | − min_gpu_freq = rps->min_freq_softlimit / GEN9_FREQ_SCALER; | |
| 1815 | − max_gpu_freq = rps->max_freq_softlimit / GEN9_FREQ_SCALER; | |
| 1816 | − } else { | |
| 1817 | − min_gpu_freq = rps->min_freq_softlimit; | |
| 1818 | − max_gpu_freq = rps->max_freq_softlimit; | |
| 1816 | + min_gpu_freq /= GEN9_FREQ_SCALER; | |
| 1817 | + max_gpu_freq /= GEN9_FREQ_SCALER; | |
| 1819 | 1818 | } |
| 1820 | 1819 | |
| 1821 | 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) · 6 unmodified lines | ||
| 1828 | 1827 | seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", |
| 1829 | 1828 | intel_gpu_freq(dev_priv, (gpu_freq * |
| 1830 | 1829 | (IS_GEN9_BC(dev_priv) || |
| 1831 | − IS_CANNONLAKE(dev_priv) ? | |
| 1830 | + INTEL_GEN(dev_priv) >= 10 ? | |
| 1832 | 1831 | GEN9_FREQ_SCALER : 1))), |
| 1833 | 1832 | ((ia_freq >> 0) & 0xff) * 100, |
| 1834 | 1833 | ((ia_freq >> 8) & 0xff) * 100); |
| @@ -1923,8 +1922,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) · 88 unmodified lines | ||
| 1923 | 1922 | |
| 1924 | 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)", | |
| 1927 | − ring->space, ring->head, ring->tail); | |
| 1925 | + seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u, emit: %u)", | |
| 1926 | + ring->space, ring->head, ring->tail, ring->emit); | |
| 1928 | 1927 | } |
| 1929 | 1928 | |
| 1930 | 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) · 395 unmodified lines | ||
| 2326 | 2325 | return 0; |
| 2327 | 2326 | } |
| 2328 | 2327 | |
| 2329 | −static void i915_guc_log_info(struct seq_file *m, | |
| 2330 | − struct drm_i915_private *dev_priv) | |
| 2328 | +static const char * | |
| 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", | |
| 2337 | − guc->log.flush_count[GUC_ISR_LOG_BUFFER], | |
| 2338 | − guc->log.total_overflow_count[GUC_ISR_LOG_BUFFER]); | |
| 2345 | +static void i915_guc_log_info(struct seq_file *m, | |
| 2346 | + struct drm_i915_private *dev_priv) | |
| 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", | |
| 2341 | − guc->log.flush_count[GUC_DPC_LOG_BUFFER], | |
| 2342 | − guc->log.total_overflow_count[GUC_DPC_LOG_BUFFER]); | |
| 2351 | + if (!intel_guc_log_relay_enabled(log)) { | |
| 2352 | + seq_puts(m, "GuC log relay disabled\n"); | |
| 2353 | + return; | |
| 2354 | + } | |
| 2343 | 2355 | |
| 2344 | − seq_printf(m, "\tCRASH: flush count %10u, overflow count %10u\n", | |
| 2345 | − guc->log.flush_count[GUC_CRASH_DUMP_LOG_BUFFER], | |
| 2346 | − guc->log.total_overflow_count[GUC_CRASH_DUMP_LOG_BUFFER]); | |
| 2356 | + seq_puts(m, "GuC logging stats:\n"); | |
| 2347 | 2357 | |
| 2348 | − seq_printf(m, "\tTotal flush interrupt count: %u\n", | |
| 2349 | − guc->log.flush_interrupt_count); | |
| 2358 | + seq_printf(m, "\tRelay full count: %u\n", | |
| 2359 | + log->relay.full_count); | |
| 2350 | 2360 | |
| 2351 | − seq_printf(m, "\tCapture miss count: %u\n", | |
| 2352 | − guc->log.capture_miss_count); | |
| 2361 | + for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { | |
| 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 | 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) · 23 unmodified lines | ||
| 2379 | 2393 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 2380 | 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 | 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 | 2404 | GEM_BUG_ON(!guc->execbuf_client); |
| 2386 | 2405 | |
| 2387 | − seq_printf(m, "Doorbell map:\n"); | |
| 2406 | + seq_printf(m, "\nDoorbell map:\n"); | |
| 2388 | 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 | 2410 | seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); |
| 2392 | 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) · 3 unmodified lines | ||
| 2396 | 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 | 2418 | /* Add more as required ... */ |
| 2402 | 2419 | |
| 2403 | 2420 | return 0; |
| @@ -2496,35 +2513,73 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) · 92 unmodified lines | ||
| 2496 | 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 | 2518 | struct drm_i915_private *dev_priv = data; |
| 2502 | 2519 | |
| 2503 | − if (!HAS_GUC(dev_priv)) | |
| 2520 | + if (!USES_GUC(dev_priv)) | |
| 2504 | 2521 | return -ENODEV; |
| 2505 | 2522 | |
| 2506 | − if (!dev_priv->guc.log.vma) | |
| 2507 | − return -EINVAL; | |
| 2508 | − | |
| 2509 | − *val = i915_modparams.guc_log_level; | |
| 2523 | + *val = intel_guc_log_level_get(&dev_priv->guc.log); | |
| 2510 | 2524 | |
| 2511 | 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 | 2530 | struct drm_i915_private *dev_priv = data; |
| 2517 | 2531 | |
| 2518 | − if (!HAS_GUC(dev_priv)) | |
| 2532 | + if (!USES_GUC(dev_priv)) | |
| 2519 | 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, | |
| 2525 | − i915_guc_log_control_get, i915_guc_log_control_set, | |
| 2538 | +DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_level_fops, | |
| 2539 | + i915_guc_log_level_get, i915_guc_log_level_set, | |
| 2526 | 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 | 2583 | static const char *psr2_live_status(u32 val) |
| 2529 | 2584 | { |
| 2530 | 2585 | static const char * const live_status[] = { |
| @@ -2569,14 +2624,13 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) · 38 unmodified lines | ||
| 2569 | 2624 | |
| 2570 | 2625 | mutex_lock(&dev_priv->psr.lock); |
| 2571 | 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 | 2627 | seq_printf(m, "Busy frontbuffer bits: 0x%03x\n", |
| 2574 | 2628 | dev_priv->psr.busy_frontbuffer_bits); |
| 2575 | 2629 | seq_printf(m, "Re-enable work scheduled: %s\n", |
| 2576 | 2630 | yesno(work_busy(&dev_priv->psr.work.work))); |
| 2577 | 2631 | |
| 2578 | 2632 | if (HAS_DDI(dev_priv)) { |
| 2579 | − if (dev_priv->psr.psr2_support) | |
| 2633 | + if (dev_priv->psr.psr2_enabled) | |
| 2580 | 2634 | enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE; |
| 2581 | 2635 | else |
| 2582 | 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) · 41 unmodified lines | ||
| 2624 | 2678 | |
| 2625 | 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 | 2682 | u32 psr2 = I915_READ(EDP_PSR2_STATUS); |
| 2629 | 2683 | |
| 2630 | 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) · 600 unmodified lines | ||
| 3231 | 3285 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
| 3232 | 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 | 3290 | seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n", |
| 3236 | 3291 | pll->state.crtc_mask, pll->active_mask, yesno(pll->on)); |
| 3237 | 3292 | seq_printf(m, " tracked hardware state:\n"); |
| @@ -3567,7 +3622,8 @@ static ssize_t i915_displayport_test_active_write(struct file *file, · 329 unmodified lines | ||
| 3567 | 3622 | |
| 3568 | 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 | 3627 | struct drm_connector *connector; |
| 3572 | 3628 | struct drm_connector_list_iter conn_iter; |
| 3573 | 3629 | struct intel_dp *intel_dp; |
| @@ -3601,10 +3657,8 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data) · 27 unmodified lines | ||
| 3601 | 3657 | static int i915_displayport_test_active_open(struct inode *inode, |
| 3602 | 3658 | struct file *file) |
| 3603 | 3659 | { |
| 3604 | − struct drm_i915_private *dev_priv = inode->i_private; | |
| 3605 | − | |
| 3606 | 3660 | return single_open(file, i915_displayport_test_active_show, |
| 3607 | − &dev_priv->drm); | |
| 3661 | + inode->i_private); | |
| 3608 | 3662 | } |
| 3609 | 3663 | |
| 3610 | 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 = { · 7 unmodified lines | ||
| 3618 | 3672 | |
| 3619 | 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 | 3677 | struct drm_connector *connector; |
| 3623 | 3678 | struct drm_connector_list_iter conn_iter; |
| 3624 | 3679 | struct intel_dp *intel_dp; |
| @@ -3657,26 +3712,12 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data) · 32 unmodified lines | ||
| 3657 | 3712 | |
| 3658 | 3713 | return 0; |
| 3659 | 3714 | } |
| 3660 | −static int i915_displayport_test_data_open(struct inode *inode, | |
| 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 | −}; | |
| 3715 | +DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data); | |
| 3676 | 3716 | |
| 3677 | 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 | 3721 | struct drm_connector *connector; |
| 3681 | 3722 | struct drm_connector_list_iter conn_iter; |
| 3682 | 3723 | struct intel_dp *intel_dp; |
| @@ -3703,23 +3744,7 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data) · 20 unmodified lines | ||
| 3703 | 3744 | |
| 3704 | 3745 | return 0; |
| 3705 | 3746 | } |
| 3706 | − | |
| 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 | −}; | |
| 3747 | +DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type); | |
| 3723 | 3748 | |
| 3724 | 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) · 261 unmodified lines | ||
| 3987 | 4012 | engine->hangcheck.stalled = true; |
| 3988 | 4013 | } |
| 3989 | 4014 | |
| 3990 | − i915_handle_error(i915, val, "Manually set wedged engine mask = %llx", | |
| 3991 | − val); | |
| 4015 | + i915_handle_error(i915, val, I915_ERROR_CAPTURE, | |
| 4016 | + "Manually set wedged engine mask = %llx", val); | |
| 3992 | 4017 | |
| 3993 | 4018 | wait_on_bit(&i915->gpu_error.flags, |
| 3994 | 4019 | I915_RESET_HANDOFF, |
| @@ -4316,9 +4341,10 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, · 321 unmodified lines | ||
| 4316 | 4341 | static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, |
| 4317 | 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 | 4347 | int ss; |
| 4321 | − u32 sig1[ss_max], sig2[ss_max]; | |
| 4322 | 4348 | |
| 4323 | 4349 | sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); |
| 4324 | 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, · 17 unmodified lines | ||
| 4342 | 4368 | sseu->eu_per_subslice = max_t(unsigned int, |
| 4343 | 4369 | sseu->eu_per_subslice, eu_cnt); |
| 4344 | 4370 | } |
| 4371 | +#undef SS_MAX | |
| 4345 | 4372 | } |
| 4346 | 4373 | |
| 4347 | 4374 | static void gen10_sseu_device_status(struct drm_i915_private *dev_priv, |
| 4348 | 4375 | struct sseu_dev_info *sseu) |
| 4349 | 4376 | { |
| 4377 | +#define SS_MAX 6 | |
| 4350 | 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 | 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 | 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, · 40 unmodified lines | ||
| 4397 | 4424 | eu_cnt); |
| 4398 | 4425 | } |
| 4399 | 4426 | } |
| 4427 | +#undef SS_MAX | |
| 4400 | 4428 | } |
| 4401 | 4429 | |
| 4402 | 4430 | static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, |
| 4403 | 4431 | struct sseu_dev_info *sseu) |
| 4404 | 4432 | { |
| 4433 | +#define SS_MAX 3 | |
| 4405 | 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 | 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 | 4438 | for (s = 0; s < info->sseu.max_slices; s++) { |
| 4411 | 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, · 40 unmodified lines | ||
| 4452 | 4480 | eu_cnt); |
| 4453 | 4481 | } |
| 4454 | 4482 | } |
| 4483 | +#undef SS_MAX | |
| 4455 | 4484 | } |
| 4456 | 4485 | |
| 4457 | 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) · 245 unmodified lines | ||
| 4703 | 4732 | |
| 4704 | 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 | 4796 | static const struct drm_info_list i915_debugfs_list[] = { |
| 4707 | 4797 | {"i915_capabilities", i915_capabilities, 0}, |
| 4708 | 4798 | {"i915_gem_objects", i915_gem_object_info, 0}, |
| @@ -4770,6 +4860,7 @@ static const struct i915_debugfs_files { · 61 unmodified lines | ||
| 4770 | 4860 | {"i915_error_state", &i915_error_state_fops}, |
| 4771 | 4861 | {"i915_gpu_info", &i915_gpu_info_fops}, |
| 4772 | 4862 | #endif |
| 4863 | + {"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops}, | |
| 4773 | 4864 | {"i915_next_seqno", &i915_next_seqno_fops}, |
| 4774 | 4865 | {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, |
| 4775 | 4866 | {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, |
| @@ -4779,7 +4870,8 @@ static const struct i915_debugfs_files { · 3 unmodified lines | ||
| 4779 | 4870 | {"i915_dp_test_data", &i915_displayport_test_data_fops}, |
| 4780 | 4871 | {"i915_dp_test_type", &i915_displayport_test_type_fops}, |
| 4781 | 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 | 4875 | {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, |
| 4784 | 4876 | {"i915_ipc_status", &i915_ipc_status_fops}, |
| 4785 | 4877 | {"i915_drrs_ctl", &i915_drrs_ctl_fops} |
| @@ -4876,19 +4968,7 @@ static int i915_dpcd_show(struct seq_file *m, void *data) · 90 unmodified lines | ||
| 4876 | 4968 | |
| 4877 | 4969 | return 0; |
| 4878 | 4970 | } |
| 4879 | − | |
| 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 | −}; | |
| 4971 | +DEFINE_SHOW_ATTRIBUTE(i915_dpcd); | |
| 4892 | 4972 | |
| 4893 | 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) · 15 unmodified lines | ||
| 4910 | 4990 | |
| 4911 | 4991 | return 0; |
| 4912 | 4992 | } |
| 4913 | − | |
| 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 | −}; | |
| 4993 | +DEFINE_SHOW_ATTRIBUTE(i915_panel); | |
| 4926 | 4994 | |
| 4927 | 4995 | /** |
| 4928 | 4996 | * i915_debugfs_connector_add - add i915 specific connector debugfs files |
| @@ -377,9 +377,9 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data, · 376 unmodified lines | ||
| 377 | 377 | value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; |
| 378 | 378 | break; |
| 379 | 379 | case I915_PARAM_HUC_STATUS: |
| 380 | − intel_runtime_pm_get(dev_priv); | |
| 381 | − value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; | |
| 382 | − intel_runtime_pm_put(dev_priv); | |
| 380 | + value = intel_huc_check_status(&dev_priv->huc); | |
| 381 | + if (value < 0) | |
| 382 | + return value; | |
| 383 | 383 | break; |
| 384 | 384 | case I915_PARAM_MMAP_GTT_VERSION: |
| 385 | 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) · 309 unmodified lines | ||
| 695 | 695 | if (ret) |
| 696 | 696 | goto cleanup_irq; |
| 697 | 697 | |
| 698 | − intel_uc_init_fw(dev_priv); | |
| 699 | − | |
| 700 | 698 | ret = i915_gem_init(dev_priv); |
| 701 | 699 | if (ret) |
| 702 | − goto cleanup_uc; | |
| 700 | + goto cleanup_irq; | |
| 703 | 701 | |
| 704 | 702 | intel_setup_overlay(dev_priv); |
| 705 | 703 | |
| @@ -719,8 +717,6 @@ cleanup_gem: · 13 unmodified lines | ||
| 719 | 717 | if (i915_gem_suspend(dev_priv)) |
| 720 | 718 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); |
| 721 | 719 | i915_gem_fini(dev_priv); |
| 722 | −cleanup_uc: | |
| 723 | − intel_uc_fini_fw(dev_priv); | |
| 724 | 720 | cleanup_irq: |
| 725 | 721 | drm_irq_uninstall(dev); |
| 726 | 722 | intel_teardown_gmbus(dev_priv); |
| @@ -922,16 +918,21 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, · 195 unmodified lines | ||
| 922 | 918 | mutex_init(&dev_priv->wm.wm_mutex); |
| 923 | 919 | mutex_init(&dev_priv->pps_mutex); |
| 924 | 920 | |
| 925 | − intel_uc_init_early(dev_priv); | |
| 926 | 921 | i915_memcpy_init_early(dev_priv); |
| 927 | 922 | |
| 928 | 923 | ret = i915_workqueues_init(dev_priv); |
| 929 | 924 | if (ret < 0) |
| 930 | 925 | goto err_engines; |
| 931 | 926 | |
| 927 | + ret = i915_gem_init_early(dev_priv); | |
| 928 | + if (ret < 0) | |
| 929 | + goto err_workqueues; | |
| 930 | + | |
| 932 | 931 | /* This must be called before any calls to HAS_PCH_* */ |
| 933 | 932 | intel_detect_pch(dev_priv); |
| 934 | 933 | |
| 934 | + intel_wopcm_init_early(&dev_priv->wopcm); | |
| 935 | + intel_uc_init_early(dev_priv); | |
| 935 | 936 | intel_pm_setup(dev_priv); |
| 936 | 937 | intel_init_dpio(dev_priv); |
| 937 | 938 | intel_power_domains_init(dev_priv); |
| @@ -940,18 +941,13 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 940 | 941 | intel_init_display_hooks(dev_priv); |
| 941 | 942 | intel_init_clock_gating_hooks(dev_priv); |
| 942 | 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 | 944 | intel_display_crc_init(dev_priv); |
| 948 | 945 | |
| 949 | 946 | intel_detect_preproduction_hw(dev_priv); |
| 950 | 947 | |
| 951 | 948 | return 0; |
| 952 | 949 | |
| 953 | −err_irq: | |
| 954 | − intel_irq_fini(dev_priv); | |
| 950 | +err_workqueues: | |
| 955 | 951 | i915_workqueues_cleanup(dev_priv); |
| 956 | 952 | err_engines: |
| 957 | 953 | i915_engines_cleanup(dev_priv); |
| @@ -964,8 +960,9 @@ err_engines: · 6 unmodified lines | ||
| 964 | 960 | */ |
| 965 | 961 | static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) |
| 966 | 962 | { |
| 967 | − i915_gem_load_cleanup(dev_priv); | |
| 968 | 963 | intel_irq_fini(dev_priv); |
| 964 | + intel_uc_cleanup_early(dev_priv); | |
| 965 | + i915_gem_cleanup_early(dev_priv); | |
| 969 | 966 | i915_workqueues_cleanup(dev_priv); |
| 970 | 967 | i915_engines_cleanup(dev_priv); |
| 971 | 968 | } |
| @@ -1035,6 +1032,10 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) · 63 unmodified lines | ||
| 1035 | 1032 | |
| 1036 | 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 | 1039 | intel_uc_init_mmio(dev_priv); |
| 1039 | 1040 | |
| 1040 | 1041 | ret = intel_engines_init_mmio(dev_priv); |
| @@ -1077,8 +1078,6 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) · 36 unmodified lines | ||
| 1077 | 1078 | i915_modparams.enable_ppgtt); |
| 1078 | 1079 | DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); |
| 1079 | 1080 | |
| 1080 | − intel_uc_sanitize_options(dev_priv); | |
| 1081 | − | |
| 1082 | 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) · 159 unmodified lines | ||
| 1244 | 1243 | /* Reveal our presence to userspace */ |
| 1245 | 1244 | if (drm_dev_register(dev, 0) == 0) { |
| 1246 | 1245 | i915_debugfs_register(dev_priv); |
| 1247 | − i915_guc_log_register(dev_priv); | |
| 1248 | 1246 | i915_setup_sysfs(dev_priv); |
| 1249 | 1247 | |
| 1250 | 1248 | /* Depends on sysfs having been initialized */ |
| @@ -1304,7 +1302,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) · 53 unmodified lines | ||
| 1304 | 1302 | i915_pmu_unregister(dev_priv); |
| 1305 | 1303 | |
| 1306 | 1304 | i915_teardown_sysfs(dev_priv); |
| 1307 | − i915_guc_log_unregister(dev_priv); | |
| 1308 | 1305 | drm_dev_unregister(&dev_priv->drm); |
| 1309 | 1306 | |
| 1310 | 1307 | i915_gem_shrinker_unregister(dev_priv); |
| @@ -1463,7 +1460,6 @@ void i915_driver_unload(struct drm_device *dev) · 152 unmodified lines | ||
| 1463 | 1460 | i915_reset_error_state(dev_priv); |
| 1464 | 1461 | |
| 1465 | 1462 | i915_gem_fini(dev_priv); |
| 1466 | − intel_uc_fini_fw(dev_priv); | |
| 1467 | 1463 | intel_fbc_cleanup_cfb(dev_priv); |
| 1468 | 1464 | |
| 1469 | 1465 | intel_power_domains_fini(dev_priv); |
| @@ -1876,7 +1872,8 @@ static int i915_resume_switcheroo(struct drm_device *dev) · 406 unmodified lines | ||
| 1876 | 1872 | /** |
| 1877 | 1873 | * i915_reset - reset chip after a hang |
| 1878 | 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 | 1878 | * Reset the chip. Useful if a hang is detected. Marks the device as wedged |
| 1882 | 1879 | * on failure. |
| @@ -1891,12 +1888,16 @@ static int i915_resume_switcheroo(struct drm_device *dev) · 8 unmodified lines | ||
| 1891 | 1888 | * - re-init interrupt state |
| 1892 | 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 | 1895 | struct i915_gpu_error *error = &i915->gpu_error; |
| 1897 | 1896 | int ret; |
| 1898 | 1897 | int i; |
| 1899 | 1898 | |
| 1899 | + GEM_TRACE("flags=%lx\n", error->flags); | |
| 1900 | + | |
| 1900 | 1901 | might_sleep(); |
| 1901 | 1902 | lockdep_assert_held(&i915->drm.struct_mutex); |
| 1902 | 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) · 5 unmodified lines | ||
| 1908 | 1909 | if (!i915_gem_unset_wedged(i915)) |
| 1909 | 1910 | goto wakeup; |
| 1910 | 1911 | |
| 1911 | − if (!(flags & I915_RESET_QUIET)) | |
| 1912 | − dev_notice(i915->drm.dev, "Resetting chip after gpu hang\n"); | |
| 1912 | + if (reason) | |
| 1913 | + dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason); | |
| 1913 | 1914 | error->reset_count++; |
| 1914 | 1915 | |
| 1915 | 1916 | disable_irq(i915->drm.irq); |
| @@ -1952,7 +1953,7 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) · 36 unmodified lines | ||
| 1952 | 1953 | goto error; |
| 1953 | 1954 | } |
| 1954 | 1955 | |
| 1955 | − i915_gem_reset(i915); | |
| 1956 | + i915_gem_reset(i915, stalled_mask); | |
| 1956 | 1957 | intel_overlay_reset(i915); |
| 1957 | 1958 | |
| 1958 | 1959 | /* |
| @@ -1998,7 +1999,6 @@ taint: · 39 unmodified lines | ||
| 1998 | 1999 | error: |
| 1999 | 2000 | i915_gem_set_wedged(i915); |
| 2000 | 2001 | i915_retire_requests(i915); |
| 2001 | − intel_gpu_reset(i915, ALL_ENGINES); | |
| 2002 | 2002 | goto finish; |
| 2003 | 2003 | } |
| 2004 | 2004 | |
| @@ -2011,7 +2011,7 @@ static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv, · 6 unmodified lines | ||
| 2011 | 2011 | /** |
| 2012 | 2012 | * i915_reset_engine - reset GPU engine to recover from a hang |
| 2013 | 2013 | * @engine: engine to reset |
| 2014 | − * @flags: options | |
| 2014 | + * @msg: reason for GPU reset; or NULL for no dev_notice() | |
| 2015 | 2015 | * |
| 2016 | 2016 | * Reset a specific GPU engine. Useful if a hang is detected. |
| 2017 | 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, · 3 unmodified lines | ||
| 2021 | 2021 | * - reset engine (which will force the engine to idle) |
| 2022 | 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 | 2026 | struct i915_gpu_error *error = &engine->i915->gpu_error; |
| 2027 | 2027 | struct i915_request *active_request; |
| 2028 | 2028 | int ret; |
| 2029 | 2029 | |
| 2030 | + GEM_TRACE("%s flags=%lx\n", engine->name, error->flags); | |
| 2030 | 2031 | GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); |
| 2031 | 2032 | |
| 2032 | 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) · 3 unmodified lines | ||
| 2036 | 2037 | goto out; |
| 2037 | 2038 | } |
| 2038 | 2039 | |
| 2039 | − if (!(flags & I915_RESET_QUIET)) { | |
| 2040 | + if (msg) | |
| 2040 | 2041 | dev_notice(engine->i915->drm.dev, |
| 2041 | − "Resetting %s after gpu hang\n", engine->name); | |
| 2042 | − } | |
| 2042 | + "Resetting %s for %s\n", engine->name, msg); | |
| 2043 | 2043 | error->reset_engine_count[engine->id]++; |
| 2044 | 2044 | |
| 2045 | 2045 | if (!engine->i915->guc.execbuf_client) |
| @@ -2059,7 +2059,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) · 13 unmodified lines | ||
| 2059 | 2059 | * active request and can drop it, adjust head to skip the offending |
| 2060 | 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 | 2065 | * The engine and its registers (and workarounds in case of render) |
| @@ -64,6 +64,7 @@ · 63 unmodified lines | ||
| 64 | 64 | #include "intel_opregion.h" |
| 65 | 65 | #include "intel_ringbuffer.h" |
| 66 | 66 | #include "intel_uncore.h" |
| 67 | +#include "intel_wopcm.h" | |
| 67 | 68 | #include "intel_uc.h" |
| 68 | 69 | |
| 69 | 70 | #include "i915_gem.h" |
| @@ -72,7 +73,7 @@ · 2 unmodified lines | ||
| 72 | 73 | #include "i915_gem_object.h" |
| 73 | 74 | #include "i915_gem_gtt.h" |
| 74 | 75 | #include "i915_gem_timeline.h" |
| 75 | − | |
| 76 | +#include "i915_gpu_error.h" | |
| 76 | 77 | #include "i915_request.h" |
| 77 | 78 | #include "i915_vma.h" |
| 78 | 79 | |
| @@ -83,8 +84,8 @@ · 4 unmodified lines | ||
| 83 | 84 | |
| 84 | 85 | #define DRIVER_NAME "i915" |
| 85 | 86 | #define DRIVER_DESC "Intel Graphics" |
| 86 | −#define DRIVER_DATE "20180308" | |
| 87 | −#define DRIVER_TIMESTAMP 1520513379 | |
| 87 | +#define DRIVER_DATE "20180413" | |
| 88 | +#define DRIVER_TIMESTAMP 1523611258 | |
| 88 | 89 | |
| 89 | 90 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and |
| 90 | 91 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions |
| @@ -261,6 +262,7 @@ enum hpd_pin { · 170 unmodified lines | ||
| 261 | 262 | HPD_PORT_C, |
| 262 | 263 | HPD_PORT_D, |
| 263 | 264 | HPD_PORT_E, |
| 265 | + HPD_PORT_F, | |
| 264 | 266 | HPD_NUM_PINS |
| 265 | 267 | }; |
| 266 | 268 | |
| @@ -453,172 +455,6 @@ struct intel_csr { · 186 unmodified lines | ||
| 453 | 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 | 458 | enum i915_cache_level { |
| 623 | 459 | I915_CACHE_NONE = 0, |
| 624 | 460 | I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */ |
| @@ -766,12 +602,13 @@ struct i915_psr { · 141 unmodified lines | ||
| 766 | 602 | bool active; |
| 767 | 603 | struct delayed_work work; |
| 768 | 604 | unsigned busy_frontbuffer_bits; |
| 769 | − bool psr2_support; | |
| 770 | − bool aux_frame_sync; | |
| 605 | + bool sink_psr2_support; | |
| 771 | 606 | bool link_standby; |
| 772 | − bool y_cord_support; | |
| 773 | 607 | bool colorimetry_support; |
| 774 | 608 | bool alpm; |
| 609 | + bool has_hw_tracking; | |
| 610 | + bool psr2_enabled; | |
| 611 | + u8 sink_sync_latency; | |
| 775 | 612 | |
| 776 | 613 | void (*enable_source)(struct intel_dp *, |
| 777 | 614 | const struct intel_crtc_state *); |
| @@ -1146,16 +983,6 @@ struct i915_gem_mm { · 368 unmodified lines | ||
| 1146 | 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 | 986 | #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ |
| 1160 | 987 | |
| 1161 | 988 | #define I915_RESET_TIMEOUT (10 * HZ) /* 10s */ |
| @@ -1164,102 +991,6 @@ struct drm_i915_error_state_buf { · 2 unmodified lines | ||
| 1164 | 991 | #define I915_ENGINE_DEAD_TIMEOUT (4 * HZ) /* Seqno, head and subunits dead */ |
| 1165 | 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 | 994 | enum modeset_restore { |
| 1264 | 995 | MODESET_ON_LID_OPEN, |
| 1265 | 996 | MODESET_DONE, |
| @@ -1451,11 +1182,12 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, · 185 unmodified lines | ||
| 1451 | 1182 | } |
| 1452 | 1183 | |
| 1453 | 1184 | struct skl_ddb_allocation { |
| 1454 | − struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ | |
| 1455 | − struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; | |
| 1185 | + /* packed/y */ | |
| 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 | 1191 | unsigned dirty_pipes; |
| 1460 | 1192 | struct skl_ddb_allocation ddb; |
| 1461 | 1193 | }; |
| @@ -1470,6 +1202,7 @@ struct skl_wm_level { · 8 unmodified lines | ||
| 1470 | 1202 | struct skl_wm_params { |
| 1471 | 1203 | bool x_tiled, y_tiled; |
| 1472 | 1204 | bool rc_surface; |
| 1205 | + bool is_planar; | |
| 1473 | 1206 | uint32_t width; |
| 1474 | 1207 | uint8_t cpp; |
| 1475 | 1208 | uint32_t plane_pixel_rate; |
| @@ -1860,6 +1593,8 @@ struct drm_i915_private { · 384 unmodified lines | ||
| 1860 | 1593 | |
| 1861 | 1594 | struct intel_gvt *gvt; |
| 1862 | 1595 | |
| 1596 | + struct intel_wopcm wopcm; | |
| 1597 | + | |
| 1863 | 1598 | struct intel_huc huc; |
| 1864 | 1599 | struct intel_guc guc; |
| 1865 | 1600 | |
| @@ -2152,7 +1887,7 @@ struct drm_i915_private { · 286 unmodified lines | ||
| 2152 | 1887 | /* current hardware state */ |
| 2153 | 1888 | union { |
| 2154 | 1889 | struct ilk_wm_values hw; |
| 2155 | − struct skl_wm_values skl_hw; | |
| 1890 | + struct skl_ddb_values skl_hw; | |
| 2156 | 1891 | struct vlv_wm_values vlv; |
| 2157 | 1892 | struct g4x_wm_values g4x; |
| 2158 | 1893 | }; |
| @@ -2392,6 +2127,11 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev) · 233 unmodified lines | ||
| 2392 | 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 | 2135 | static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) |
| 2396 | 2136 | { |
| 2397 | 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) · 13 unmodified lines | ||
| 2411 | 2151 | |
| 2412 | 2152 | /* Iterator over subset of engines selected by mask */ |
| 2413 | 2153 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ |
| 2414 | − for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ | |
| 2415 | − tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) | |
| 2154 | + for ((tmp__) = (mask__) & INTEL_INFO(dev_priv__)->ring_mask; \ | |
| 2155 | + (tmp__) ? \ | |
| 2156 | + ((engine__) = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : \ | |
| 2157 | + 0;) | |
| 2416 | 2158 | |
| 2417 | 2159 | enum hdmi_force_audio { |
| 2418 | 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); · 544 unmodified lines | ||
| 2963 | 2705 | extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); |
| 2964 | 2706 | extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); |
| 2965 | 2707 | |
| 2966 | −#define I915_RESET_QUIET BIT(0) | |
| 2967 | −extern void i915_reset(struct drm_i915_private *i915, unsigned int flags); | |
| 2708 | +extern void i915_reset(struct drm_i915_private *i915, | |
| 2709 | + unsigned int stalled_mask, | |
| 2710 | + const char *reason); | |
| 2968 | 2711 | extern int i915_reset_engine(struct intel_engine_cs *engine, |
| 2969 | − unsigned int flags); | |
| 2712 | + const char *reason); | |
| 2970 | 2713 | |
| 2971 | 2714 | extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv); |
| 2972 | 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) · 41 unmodified lines | ||
| 3014 | 2757 | &dev_priv->gpu_error.hangcheck_work, delay); |
| 3015 | 2758 | } |
| 3016 | 2759 | |
| 3017 | −__printf(3, 4) | |
| 2760 | +__printf(4, 5) | |
| 3018 | 2761 | void i915_handle_error(struct drm_i915_private *dev_priv, |
| 3019 | 2762 | u32 engine_mask, |
| 2763 | + unsigned long flags, | |
| 3020 | 2764 | const char *fmt, ...); |
| 2765 | +#define I915_ERROR_CAPTURE BIT(0) | |
| 3021 | 2766 | |
| 3022 | 2767 | extern void intel_irq_init(struct drm_i915_private *dev_priv); |
| 3023 | 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, · 108 unmodified lines | ||
| 3132 | 2877 | int i915_gem_wait_ioctl(struct drm_device *dev, void *data, |
| 3133 | 2878 | struct drm_file *file_priv); |
| 3134 | 2879 | void i915_gem_sanitize(struct drm_i915_private *i915); |
| 3135 | −int i915_gem_load_init(struct drm_i915_private *dev_priv); | |
| 3136 | −void i915_gem_load_cleanup(struct drm_i915_private *dev_priv); | |
| 2880 | +int i915_gem_init_early(struct drm_i915_private *dev_priv); | |
| 2881 | +void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); | |
| 3137 | 2882 | void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); |
| 3138 | 2883 | int i915_gem_freeze(struct drm_i915_private *dev_priv); |
| 3139 | 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, · 248 unmodified lines | ||
| 3388 | 3133 | struct i915_request * |
| 3389 | 3134 | i915_gem_reset_prepare_engine(struct intel_engine_cs *engine); |
| 3390 | 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 | 3138 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine); |
| 3393 | 3139 | void i915_gem_reset_finish(struct drm_i915_private *dev_priv); |
| 3394 | 3140 | void i915_gem_set_wedged(struct drm_i915_private *dev_priv); |
| 3395 | 3141 | bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv); |
| 3396 | 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 | 3146 | void i915_gem_init_mmio(struct drm_i915_private *i915); |
| 3400 | 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) · 188 unmodified lines | ||
| 3589 | 3336 | static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {} |
| 3590 | 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 | 3339 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type); |
| 3651 | 3340 | |
| 3652 | 3341 | /* i915_cmd_parser.c */ |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include "intel_drv.h" |
| 36 | 36 | #include "intel_frontbuffer.h" |
| 37 | 37 | #include "intel_mocs.h" |
| 38 | +#include "intel_workarounds.h" | |
| 38 | 39 | #include "i915_gemfs.h" |
| 39 | 40 | #include <linux/dma-fence-array.h> |
| 40 | 41 | #include <linux/kthread.h> |
| @@ -136,6 +137,100 @@ int i915_mutex_lock_interruptible(struct drm_device *dev) · 95 unmodified lines | ||
| 136 | 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 | 234 | int |
| 140 | 235 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
| 141 | 236 | struct drm_file *file) |
| @@ -2896,20 +2991,6 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) · 2754 unmodified lines | ||
| 2896 | 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 | 2995 | * Ensure irq handler finishes, and not run again. |
| 2915 | 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) · 82 unmodified lines | ||
| 2998 | 3079 | } |
| 2999 | 3080 | |
| 3000 | 3081 | i915_gem_revoke_fences(dev_priv); |
| 3082 | + intel_uc_sanitize(dev_priv); | |
| 3001 | 3083 | |
| 3002 | 3084 | return err; |
| 3003 | 3085 | } |
| @@ -3047,7 +3129,8 @@ static void engine_skip_context(struct i915_request *request) · 43 unmodified lines | ||
| 3047 | 3129 | /* Returns the request if it was guilty of the hang */ |
| 3048 | 3130 | static struct i915_request * |
| 3049 | 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 | 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, · 16 unmodified lines | ||
| 3070 | 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 | 3165 | i915_gem_context_mark_guilty(request->ctx); |
| 3075 | 3166 | skip_request(request); |
| 3076 | 3167 | |
| @@ -3101,7 +3192,8 @@ i915_gem_reset_request(struct intel_engine_cs *engine, · 24 unmodified lines | ||
| 3101 | 3192 | } |
| 3102 | 3193 | |
| 3103 | 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 | 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, · 3 unmodified lines | ||
| 3111 | 3203 | smp_store_mb(engine->irq_posted, 0); |
| 3112 | 3204 | |
| 3113 | 3205 | if (request) |
| 3114 | − request = i915_gem_reset_request(engine, request); | |
| 3206 | + request = i915_gem_reset_request(engine, request, stalled); | |
| 3115 | 3207 | |
| 3116 | 3208 | if (request) { |
| 3117 | 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, · 4 unmodified lines | ||
| 3122 | 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 | 3220 | struct intel_engine_cs *engine; |
| 3128 | 3221 | enum intel_engine_id id; |
| @@ -3134,7 +3227,9 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) · 5 unmodified lines | ||
| 3134 | 3227 | for_each_engine(engine, dev_priv, id) { |
| 3135 | 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 | 3233 | ctx = fetch_and_zero(&engine->last_retired_context); |
| 3139 | 3234 | if (ctx) |
| 3140 | 3235 | engine->context_unpin(engine, ctx); |
| @@ -3160,13 +3255,6 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) · 19 unmodified lines | ||
| 3160 | 3255 | } |
| 3161 | 3256 | |
| 3162 | 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 | 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) · 19 unmodified lines | ||
| 3192 | 3280 | |
| 3193 | 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 | 3286 | dma_fence_set_error(&request->fence, -EIO); |
| 3196 | 3287 | |
| 3197 | 3288 | i915_request_submit(request); |
| @@ -3201,6 +3292,9 @@ static void nop_complete_submit_request(struct i915_request *request) · 3 unmodified lines | ||
| 3201 | 3292 | { |
| 3202 | 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 | 3298 | dma_fence_set_error(&request->fence, -EIO); |
| 3205 | 3299 | |
| 3206 | 3300 | spin_lock_irqsave(&request->engine->timeline->lock, flags); |
| @@ -3214,6 +3308,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) · 7 unmodified lines | ||
| 3214 | 3308 | struct intel_engine_cs *engine; |
| 3215 | 3309 | enum intel_engine_id id; |
| 3216 | 3310 | |
| 3311 | + GEM_TRACE("start\n"); | |
| 3312 | + | |
| 3217 | 3313 | if (drm_debug & DRM_UT_DRIVER) { |
| 3218 | 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) · 17 unmodified lines | ||
| 3237 | 3333 | } |
| 3238 | 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 | 3340 | * Make sure no one is running the old callback before we proceed with |
| 3242 | 3341 | * cancelling requests and resetting the completion tracking. Otherwise |
| @@ -3278,6 +3377,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) · 35 unmodified lines | ||
| 3278 | 3377 | i915_gem_reset_finish_engine(engine); |
| 3279 | 3378 | } |
| 3280 | 3379 | |
| 3380 | + GEM_TRACE("end\n"); | |
| 3381 | + | |
| 3281 | 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) · 6 unmodified lines | ||
| 3290 | 3391 | if (!test_bit(I915_WEDGED, &i915->gpu_error.flags)) |
| 3291 | 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 | 3398 | * are flushed and errored out - we may have requests waiting upon |
| 3295 | 3399 | * third party fences. We marked all inflight requests as EIO, and |
| 3296 | 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) · 11 unmodified lines | ||
| 3308 | 3412 | if (!rq) |
| 3309 | 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 | 3417 | * avoid recursively trying to handle the current |
| 3313 | 3418 | * reset. The basic dma_fence_default_wait() installs |
| 3314 | 3419 | * a callback for dma_fence_signal(), which is |
| @@ -3323,8 +3428,11 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) · 8 unmodified lines | ||
| 3323 | 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 | 3436 | * being queued (by disallowing execbuf whilst wedged) so having |
| 3329 | 3437 | * waited for all active requests above, we know the system is idle |
| 3330 | 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) · 4 unmodified lines | ||
| 3335 | 3443 | intel_engines_reset_default_submission(i915); |
| 3336 | 3444 | i915_gem_contexts_lost(i915); |
| 3337 | 3445 | |
| 3446 | + GEM_TRACE("end\n"); | |
| 3447 | + | |
| 3338 | 3448 | smp_mb__before_atomic(); /* complete takeover before enabling execbuf */ |
| 3339 | 3449 | clear_bit(I915_WEDGED, &i915->gpu_error.flags); |
| 3340 | 3450 | |
| @@ -3473,36 +3583,9 @@ i915_gem_idle_work_handler(struct work_struct *work) · 132 unmodified lines | ||
| 3473 | 3583 | if (new_requests_since_last_retire(dev_priv)) |
| 3474 | 3584 | goto out_unlock; |
| 3475 | 3585 | |
| 3476 | − /* | |
| 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); | |
| 3586 | + epoch = __i915_gem_park(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 | 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 | 3589 | out_unlock: |
| 3507 | 3590 | mutex_unlock(&dev_priv->drm.struct_mutex); |
| 3508 | 3591 | |
| @@ -3666,16 +3749,7 @@ static int wait_for_engines(struct drm_i915_private *i915) · 157 unmodified lines | ||
| 3666 | 3749 | if (wait_for(intel_engines_are_idle(i915), I915_IDLE_ENGINES_TIMEOUT)) { |
| 3667 | 3750 | dev_err(i915->drm.dev, |
| 3668 | 3751 | "Failed to idle engines, declaring wedged!\n"); |
| 3669 | − if (drm_debug & DRM_UT_DRIVER) { | |
| 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 | − | |
| 3752 | + GEM_TRACE_DUMP(); | |
| 3679 | 3753 | i915_gem_set_wedged(i915); |
| 3680 | 3754 | return -EIO; |
| 3681 | 3755 | } |
| @@ -4088,9 +4162,10 @@ out: · 406 unmodified lines | ||
| 4088 | 4162 | } |
| 4089 | 4163 | |
| 4090 | 4164 | /* |
| 4091 | − * Prepare buffer for display plane (scanout, cursors, etc). | |
| 4092 | − * Can be called from an uninterruptible phase (modesetting) and allows | |
| 4093 | − * any flushes to be pipelined (for pageflips). | |
| 4165 | + * Prepare buffer for display plane (scanout, cursors, etc). Can be called from | |
| 4166 | + * an uninterruptible phase (modesetting) and allows any flushes to be pipelined | |
| 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 | 4170 | struct i915_vma * |
| 4096 | 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, · 49 unmodified lines | ||
| 4146 | 4221 | |
| 4147 | 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 | 4224 | __i915_gem_object_flush_for_display(obj); |
| 4151 | − intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | |
| 4152 | 4225 | |
| 4153 | 4226 | /* It should now be out of any other write domains, and we can update |
| 4154 | 4227 | * the domain values for our changes. |
| @@ -4973,6 +5046,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) · 818 unmodified lines | ||
| 4973 | 5046 | * machines is a good idea, we don't - just in case it leaves the |
| 4974 | 5047 | * machine in an unusable condition. |
| 4975 | 5048 | */ |
| 5049 | + intel_uc_sanitize(dev_priv); | |
| 4976 | 5050 | i915_gem_sanitize(dev_priv); |
| 4977 | 5051 | |
| 4978 | 5052 | intel_runtime_pm_put(dev_priv); |
| @@ -5118,6 +5192,8 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) · 139 unmodified lines | ||
| 5118 | 5192 | } |
| 5119 | 5193 | } |
| 5120 | 5194 | |
| 5195 | + intel_gt_workarounds_apply(dev_priv); | |
| 5196 | + | |
| 5121 | 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) · 16 unmodified lines | ||
| 5140 | 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 | 5225 | /* We can't enable contexts until all firmware is loaded */ |
| 5144 | 5226 | ret = intel_uc_init_hw(dev_priv); |
| 5145 | 5227 | if (ret) { |
| @@ -5297,6 +5379,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 151 unmodified lines | ||
| 5297 | 5379 | if (ret) |
| 5298 | 5380 | return ret; |
| 5299 | 5381 | |
| 5382 | + ret = intel_wopcm_init(&dev_priv->wopcm); | |
| 5383 | + if (ret) | |
| 5384 | + return ret; | |
| 5385 | + | |
| 5300 | 5386 | ret = intel_uc_init_misc(dev_priv); |
| 5301 | 5387 | if (ret) |
| 5302 | 5388 | return ret; |
| @@ -5478,8 +5564,7 @@ static void i915_gem_init__mm(struct drm_i915_private *i915) · 175 unmodified lines | ||
| 5478 | 5564 | INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); |
| 5479 | 5565 | } |
| 5480 | 5566 | |
| 5481 | −int | |
| 5482 | −i915_gem_load_init(struct drm_i915_private *dev_priv) | |
| 5567 | +int i915_gem_init_early(struct drm_i915_private *dev_priv) | |
| 5483 | 5568 | { |
| 5484 | 5569 | int err = -ENOMEM; |
| 5485 | 5570 | |
| @@ -5554,7 +5639,7 @@ err_out: · 68 unmodified lines | ||
| 5554 | 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 | 5644 | i915_gem_drain_freed_objects(dev_priv); |
| 5560 | 5645 | GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); |
| @@ -27,6 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include <linux/bug.h> |
| 29 | 29 | |
| 30 | +struct drm_i915_private; | |
| 31 | + | |
| 30 | 32 | #ifdef CONFIG_DRM_I915_DEBUG_GEM |
| 31 | 33 | #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ |
| 32 | 34 | pr_err("%s:%d GEM_BUG_ON(%s)\n", \ |
| @@ -53,10 +55,15 @@ · 20 unmodified lines | ||
| 53 | 55 | |
| 54 | 56 | #if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM) |
| 55 | 57 | #define GEM_TRACE(...) trace_printk(__VA_ARGS__) |
| 58 | +#define GEM_TRACE_DUMP() ftrace_dump(DUMP_ALL) | |
| 56 | 59 | #else |
| 57 | 60 | #define GEM_TRACE(...) do { } while (0) |
| 61 | +#define GEM_TRACE_DUMP() do { } while (0) | |
| 58 | 62 | #endif |
| 59 | 63 | |
| 60 | 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 | 69 | #endif /* __I915_GEM_H__ */ |
| @@ -1,29 +1,11 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright © 2014 Intel Corporation | |
| 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. | |
| 2 | + * SPDX-License-Identifier: MIT | |
| 22 | 3 | * |
| 4 | + * Copyright © 2014-2018 Intel Corporation | |
| 23 | 5 | */ |
| 24 | 6 | |
| 25 | −#include "i915_drv.h" | |
| 26 | 7 | #include "i915_gem_batch_pool.h" |
| 8 | +#include "i915_drv.h" | |
| 27 | 9 | |
| 28 | 10 | /** |
| 29 | 11 | * DOC: batch pool |
| @@ -41,11 +23,11 @@ · 11 unmodified lines | ||
| 41 | 23 | |
| 42 | 24 | /** |
| 43 | 25 | * i915_gem_batch_pool_init() - initialize a batch buffer pool |
| 44 | − * @engine: the associated request submission engine | |
| 45 | 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, | |
| 48 | − struct i915_gem_batch_pool *pool) | |
| 29 | +void i915_gem_batch_pool_init(struct i915_gem_batch_pool *pool, | |
| 30 | + struct intel_engine_cs *engine) | |
| 49 | 31 | { |
| 50 | 32 | int n; |
| 51 | 33 | |
| @@ -1,31 +1,13 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright © 2014 Intel Corporation | |
| 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. | |
| 2 | + * SPDX-License-Identifier: MIT | |
| 22 | 3 | * |
| 4 | + * Copyright © 2014-2018 Intel Corporation | |
| 23 | 5 | */ |
| 24 | 6 | |
| 25 | 7 | #ifndef I915_GEM_BATCH_POOL_H |
| 26 | 8 | #define I915_GEM_BATCH_POOL_H |
| 27 | 9 | |
| 28 | −#include "i915_drv.h" | |
| 10 | +#include <linux/types.h> | |
| 29 | 11 | |
| 30 | 12 | struct intel_engine_cs; |
| 31 | 13 | |
| @@ -34,9 +16,8 @@ struct i915_gem_batch_pool { · 2 unmodified lines | ||
| 34 | 16 | struct list_head cache_list[4]; |
| 35 | 17 | }; |
| 36 | 18 | |
| 37 | −/* i915_gem_batch_pool.c */ | |
| 38 | −void i915_gem_batch_pool_init(struct intel_engine_cs *engine, | |
| 39 | − struct i915_gem_batch_pool *pool); | |
| 19 | +void i915_gem_batch_pool_init(struct i915_gem_batch_pool *pool, | |
| 20 | + struct intel_engine_cs *engine); | |
| 40 | 21 | void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); |
| 41 | 22 | struct drm_i915_gem_object* |
| 42 | 23 | i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); |
| @@ -90,6 +90,7 @@ · 89 unmodified lines | ||
| 90 | 90 | #include <drm/i915_drm.h> |
| 91 | 91 | #include "i915_drv.h" |
| 92 | 92 | #include "i915_trace.h" |
| 93 | +#include "intel_workarounds.h" | |
| 93 | 94 | |
| 94 | 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, · 222 unmodified lines | ||
| 318 | 319 | ctx->desc_template = |
| 319 | 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 | 324 | * present or not in use we still need a small bias as ring wraparound |
| 323 | 325 | * at offset 0 sometimes hangs. No idea why. |
| 324 | 326 | */ |
| 325 | 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 | 329 | else |
| 328 | 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) · 128 unmodified lines | ||
| 458 | 460 | int i915_gem_contexts_init(struct drm_i915_private *dev_priv) |
| 459 | 461 | { |
| 460 | 462 | struct i915_gem_context *ctx; |
| 463 | + int ret; | |
| 461 | 464 | |
| 462 | 465 | /* Reassure ourselves we are only called once */ |
| 463 | 466 | GEM_BUG_ON(dev_priv->kernel_context); |
| 464 | 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 | 473 | INIT_LIST_HEAD(&dev_priv->contexts.list); |
| 467 | 474 | INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); |
| 468 | 475 | init_llist_head(&dev_priv->contexts.free_list); |
| @@ -81,6 +81,35 @@ enum { · 80 unmodified lines | ||
| 81 | 81 | * but this remains just a hint as the kernel may choose a new location for |
| 82 | 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 | 113 | * Processing an execbuf ioctl is conceptually split up into a few phases. |
| 85 | 114 | * |
| 86 | 115 | * 1. Validation - Ensure all the pointers, handles and flags are valid. |
| @@ -121,8 +121,8 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, · 120 unmodified lines | ||
| 121 | 121 | |
| 122 | 122 | if (stolen[0].start != stolen[1].start || |
| 123 | 123 | stolen[0].end != stolen[1].end) { |
| 124 | − DRM_DEBUG_KMS("GTT within stolen memory at %pR\n", &ggtt_res); | |
| 125 | − DRM_DEBUG_KMS("Stolen memory adjusted to %pR\n", dsm); | |
| 124 | + DRM_DEBUG_DRIVER("GTT within stolen memory at %pR\n", &ggtt_res); | |
| 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) · 45 unmodified lines | ||
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 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 | − CTG_STOLEN_RESERVED : | |
| 181 | − ELK_STOLEN_RESERVED); | |
| 180 | + u32 reg_val = I915_READ(IS_GM45(dev_priv) ? | |
| 181 | + CTG_STOLEN_RESERVED : | |
| 182 | + ELK_STOLEN_RESERVED); | |
| 182 | 183 | resource_size_t stolen_top = dev_priv->dsm.end + 1; |
| 183 | 184 | |
| 184 | − if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) { | |
| 185 | − *base = 0; | |
| 186 | − *size = 0; | |
| 185 | + DRM_DEBUG_DRIVER("%s_STOLEN_RESERVED = %08x\n", | |
| 186 | + IS_GM45(dev_priv) ? "CTG" : "ELK", reg_val); | |
| 187 | + | |
| 188 | + if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) | |
| 187 | 189 | return; |
| 188 | − } | |
| 189 | 190 | |
| 190 | 191 | /* |
| 191 | 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, · 1 unmodified line | ||
| 193 | 194 | */ |
| 194 | 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 | 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 | |
| 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; | |
| 203 | + *size = stolen_top - *base; | |
| 208 | 204 | } |
| 209 | 205 | |
| 210 | 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) { | |
| 216 | − *base = 0; | |
| 217 | − *size = 0; | |
| 214 | + if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) | |
| 218 | 215 | return; |
| 219 | − } | |
| 220 | 216 | |
| 221 | 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, · 16 unmodified lines | ||
| 239 | 235 | } |
| 240 | 236 | } |
| 241 | 237 | |
| 242 | −static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, | |
| 243 | − resource_size_t *base, resource_size_t *size) | |
| 238 | +static void vlv_get_stolen_reserved(struct drm_i915_private *dev_priv, | |
| 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) { | |
| 248 | − *base = 0; | |
| 249 | − *size = 0; | |
| 245 | + DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); | |
| 246 | + | |
| 247 | + if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) | |
| 250 | 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 | 276 | *base = reg_val & GEN7_STOLEN_RESERVED_ADDR_MASK; |
| 254 | 277 | |
| 255 | 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, · 10 unmodified lines | ||
| 266 | 289 | } |
| 267 | 290 | |
| 268 | 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) { | |
| 274 | − *base = 0; | |
| 275 | − *size = 0; | |
| 297 | + DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); | |
| 298 | + | |
| 299 | + if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) | |
| 276 | 300 | return; |
| 277 | − } | |
| 278 | 301 | |
| 279 | 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, · 17 unmodified lines | ||
| 298 | 321 | } |
| 299 | 322 | |
| 300 | 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); | |
| 304 | − resource_size_t stolen_top; | |
| 327 | + u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); | |
| 328 | + resource_size_t stolen_top = dev_priv->dsm.end + 1; | |
| 305 | 329 | |
| 306 | − if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | |
| 307 | − *base = 0; | |
| 308 | − *size = 0; | |
| 330 | + DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); | |
| 331 | + | |
| 332 | + if (!(reg_val & GEN6_STOLEN_RESERVED_ENABLE)) | |
| 309 | 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 | 338 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
| 315 | − | |
| 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; | |
| 339 | + *size = stolen_top - *base; | |
| 324 | 340 | } |
| 325 | 341 | |
| 326 | 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) · 26 unmodified lines | ||
| 353 | 369 | GEM_BUG_ON(dev_priv->dsm.end <= dev_priv->dsm.start); |
| 354 | 370 | |
| 355 | 371 | stolen_top = dev_priv->dsm.end + 1; |
| 356 | − reserved_base = 0; | |
| 372 | + reserved_base = stolen_top; | |
| 357 | 373 | reserved_size = 0; |
| 358 | 374 | |
| 359 | 375 | switch (INTEL_GEN(dev_priv)) { |
| @@ -373,8 +389,12 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) · 13 unmodified lines | ||
| 373 | 389 | &reserved_base, &reserved_size); |
| 374 | 390 | break; |
| 375 | 391 | case 7: |
| 376 | − gen7_get_stolen_reserved(dev_priv, | |
| 377 | − &reserved_base, &reserved_size); | |
| 392 | + if (IS_VALLEYVIEW(dev_priv)) | |
| 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 | 398 | break; |
| 379 | 399 | default: |
| 380 | 400 | if (IS_LP(dev_priv)) |
| @@ -386,11 +406,16 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) · 5 unmodified lines | ||
| 386 | 406 | break; |
| 387 | 407 | } |
| 388 | 408 | |
| 389 | − /* It is possible for the reserved base to be zero, but the register | |
| 390 | − * field for size doesn't have a zero option. */ | |
| 391 | − if (reserved_base == 0) { | |
| 392 | − reserved_size = 0; | |
| 409 | + /* | |
| 410 | + * Our expectation is that the reserved space is at the top of the | |
| 411 | + * stolen region and *never* at the bottom. If we see !reserved_base, | |
| 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 | 417 | reserved_base = stolen_top; |
| 418 | + reserved_size = 0; | |
| 394 | 419 | } |
| 395 | 420 | |
| 396 | 421 | dev_priv->dsm_reserved = |
| @@ -406,9 +431,9 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 406 | 431 | * memory, so just consider the start. */ |
| 407 | 432 | reserved_total = stolen_top - reserved_base; |
| 408 | 433 | |
| 409 | − DRM_DEBUG_KMS("Memory reserved for graphics device: %lluK, usable: %lluK\n", | |
| 410 | − (u64)resource_size(&dev_priv->dsm) >> 10, | |
| 411 | − ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); | |
| 434 | + DRM_DEBUG_DRIVER("Memory reserved for graphics device: %lluK, usable: %lluK\n", | |
| 435 | + (u64)resource_size(&dev_priv->dsm) >> 10, | |
| 436 | + ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); | |
| 412 | 437 | |
| 413 | 438 | stolen_usable_start = 0; |
| 414 | 439 | /* WaSkipStolenMemoryFirstPage:bdw+ */ |
| @@ -580,8 +605,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv · 165 unmodified lines | ||
| 580 | 605 | |
| 581 | 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", | |
| 584 | − &stolen_offset, >t_offset, &size); | |
| 608 | + DRM_DEBUG_DRIVER("creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", | |
| 609 | + &stolen_offset, >t_offset, &size); | |
| 585 | 610 | |
| 586 | 611 | /* KISS and expect everything to be page-aligned */ |
| 587 | 612 | if (WARN_ON(size == 0) || |
| @@ -599,14 +624,14 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv · 11 unmodified lines | ||
| 599 | 624 | ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen); |
| 600 | 625 | mutex_unlock(&dev_priv->mm.stolen_lock); |
| 601 | 626 | if (ret) { |
| 602 | − DRM_DEBUG_KMS("failed to allocate stolen space\n"); | |
| 627 | + DRM_DEBUG_DRIVER("failed to allocate stolen space\n"); | |
| 603 | 628 | kfree(stolen); |
| 604 | 629 | return NULL; |
| 605 | 630 | } |
| 606 | 631 | |
| 607 | 632 | obj = _i915_gem_object_create_stolen(dev_priv, stolen); |
| 608 | 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 | 635 | i915_gem_stolen_remove_node(dev_priv, stolen); |
| 611 | 636 | kfree(stolen); |
| 612 | 637 | return NULL; |
| @@ -635,7 +660,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv · 22 unmodified lines | ||
| 635 | 660 | size, gtt_offset, obj->cache_level, |
| 636 | 661 | 0); |
| 637 | 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 | 664 | goto err_pages; |
| 640 | 665 | } |
| 641 | 666 | |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <linux/zlib.h> |
| 33 | 33 | #include <drm/drm_print.h> |
| 34 | 34 | |
| 35 | +#include "i915_gpu_error.h" | |
| 35 | 36 | #include "i915_drv.h" |
| 36 | 37 | |
| 37 | 38 | static inline const struct intel_engine_cs * |
| @@ -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_ */ | |
| @@ -243,6 +243,41 @@ void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, · 242 unmodified lines | ||
| 243 | 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 | 282 | * ilk_update_display_irq - update DEIMR |
| 248 | 283 | * @dev_priv: driver private |
| @@ -308,17 +343,29 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) · 59 unmodified lines | ||
| 308 | 343 | |
| 309 | 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 | 348 | return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; |
| 312 | 349 | } |
| 313 | 350 | |
| 314 | 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 | 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 · 75 unmodified lines | ||
| 400 | 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 | 462 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) |
| 404 | 463 | { |
| 405 | 464 | spin_lock_irq(&dev_priv->irq_lock); |
| @@ -415,12 +474,14 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 415 | 474 | if (READ_ONCE(rps->interrupts_enabled)) |
| 416 | 475 | return; |
| 417 | 476 | |
| 418 | − if (WARN_ON_ONCE(IS_GEN11(dev_priv))) | |
| 419 | − return; | |
| 420 | − | |
| 421 | 477 | spin_lock_irq(&dev_priv->irq_lock); |
| 422 | 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 | 485 | rps->interrupts_enabled = true; |
| 425 | 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) · 7 unmodified lines | ||
| 434 | 495 | if (!READ_ONCE(rps->interrupts_enabled)) |
| 435 | 496 | return; |
| 436 | 497 | |
| 437 | − if (WARN_ON_ONCE(IS_GEN11(dev_priv))) | |
| 438 | − return; | |
| 439 | − | |
| 440 | 498 | spin_lock_irq(&dev_priv->irq_lock); |
| 441 | 499 | rps->interrupts_enabled = false; |
| 442 | 500 | |
| @@ -453,7 +511,10 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) · 10 unmodified lines | ||
| 453 | 511 | * state of the worker can be discarded. |
| 454 | 512 | */ |
| 455 | 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 | 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, · 939 unmodified lines | ||
| 1399 | 1460 | } |
| 1400 | 1461 | |
| 1401 | 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 | 1465 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 1405 | 1466 | bool tasklet = false; |
| 1406 | 1467 | |
| 1407 | − if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { | |
| 1408 | − if (READ_ONCE(engine->execlists.active)) { | |
| 1409 | − __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | |
| 1410 | − tasklet = true; | |
| 1411 | − } | |
| 1468 | + if (iir & GT_CONTEXT_SWITCH_INTERRUPT) { | |
| 1469 | + if (READ_ONCE(engine->execlists.active)) | |
| 1470 | + tasklet = !test_and_set_bit(ENGINE_IRQ_EXECLIST, | |
| 1471 | + &engine->irq_posted); | |
| 1412 | 1472 | } |
| 1413 | 1473 | |
| 1414 | − if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { | |
| 1474 | + if (iir & GT_RENDER_USER_INTERRUPT) { | |
| 1415 | 1475 | notify_ring(engine); |
| 1416 | 1476 | tasklet |= USES_GUC_SUBMISSION(engine->i915); |
| 1417 | 1477 | } |
| @@ -1466,21 +1526,21 @@ static void gen8_gt_irq_handler(struct drm_i915_private *i915, · 48 unmodified lines | ||
| 1466 | 1526 | { |
| 1467 | 1527 | if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { |
| 1468 | 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 | 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 | 1534 | if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { |
| 1475 | 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 | 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 | 1541 | if (master_ctl & GEN8_GT_VECS_IRQ) { |
| 1482 | 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 | 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, · 140 unmodified lines | ||
| 1627 | 1687 | int head, tail; |
| 1628 | 1688 | |
| 1629 | 1689 | spin_lock(&pipe_crc->lock); |
| 1630 | − if (pipe_crc->source) { | |
| 1690 | + if (pipe_crc->source && !crtc->base.crc.opened) { | |
| 1631 | 1691 | if (!pipe_crc->entries) { |
| 1632 | 1692 | spin_unlock(&pipe_crc->lock); |
| 1633 | 1693 | DRM_DEBUG_KMS("spurious interrupt\n"); |
| @@ -1667,7 +1727,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, · 33 unmodified lines | ||
| 1667 | 1727 | * On GEN8+ sometimes the second CRC is bonkers as well, so |
| 1668 | 1728 | * don't trust that one either. |
| 1669 | 1729 | */ |
| 1670 | − if (pipe_crc->skipped == 0 || | |
| 1730 | + if (pipe_crc->skipped <= 0 || | |
| 1671 | 1731 | (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { |
| 1672 | 1732 | pipe_crc->skipped++; |
| 1673 | 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) · 92 unmodified lines | ||
| 1766 | 1826 | |
| 1767 | 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) { | |
| 1770 | − /* Sample the log buffer flush related bits & clear them out now | |
| 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 | − } | |
| 1829 | + if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) | |
| 1830 | + intel_guc_to_host_event_handler(&dev_priv->guc); | |
| 1800 | 1831 | } |
| 1801 | 1832 | |
| 1802 | 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) · 959 unmodified lines | ||
| 2762 | 2793 | (W)->i915; \ |
| 2763 | 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 | 2796 | static u32 |
| 2810 | −gen11_gt_engine_intr(struct drm_i915_private * const i915, | |
| 2811 | − const unsigned int bank, const unsigned int bit) | |
| 2797 | +gen11_gt_engine_identity(struct drm_i915_private * const i915, | |
| 2798 | + const unsigned int bank, const unsigned int bit) | |
| 2812 | 2799 | { |
| 2813 | 2800 | void __iomem * const regs = i915->regs; |
| 2814 | 2801 | u32 timeout_ts; |
| 2815 | 2802 | u32 ident; |
| 2816 | 2803 | |
| 2804 | + lockdep_assert_held(&i915->irq_lock); | |
| 2805 | + | |
| 2817 | 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, · 15 unmodified lines | ||
| 2835 | 2824 | raw_reg_write(regs, GEN11_INTR_IDENTITY_REG(bank), |
| 2836 | 2825 | GEN11_INTR_DATA_VALID); |
| 2837 | 2826 | |
| 2838 | − return ident & GEN11_INTR_ENGINE_MASK; | |
| 2827 | + return ident; | |
| 2839 | 2828 | } |
| 2840 | 2829 | |
| 2841 | 2830 | static void |
| 2842 | −gen11_gt_irq_handler(struct drm_i915_private * const i915, | |
| 2843 | − const u32 master_ctl) | |
| 2831 | +gen11_other_irq_handler(struct drm_i915_private * const i915, | |
| 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 | 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++) { | |
| 2849 | − unsigned long intr_dw; | |
| 2850 | − unsigned int bit; | |
| 2888 | + lockdep_assert_held(&i915->irq_lock); | |
| 2851 | 2889 | |
| 2852 | − if (!(master_ctl & GEN11_GT_DW_IRQ(bank))) | |
| 2853 | − continue; | |
| 2890 | + intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); | |
| 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)) { | |
| 2858 | − DRM_ERROR("GT_INTR_DW%u blank!\n", bank); | |
| 2859 | − continue; | |
| 2860 | − } | |
| 2897 | + for_each_set_bit(bit, &intr_dw, 32) { | |
| 2898 | + const u32 ident = gen11_gt_engine_identity(i915, | |
| 2899 | + bank, bit); | |
| 2861 | 2900 | |
| 2862 | − for_each_set_bit(bit, &intr_dw, 32) { | |
| 2863 | − const u16 iir = gen11_gt_engine_intr(i915, bank, bit); | |
| 2901 | + gen11_gt_identity_handler(i915, ident); | |
| 2902 | + } | |
| 2864 | 2903 | |
| 2865 | − if (unlikely(!iir)) | |
| 2866 | − continue; | |
| 2904 | + /* Clear must be after shared has been served for engine */ | |
| 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); | |
| 2869 | − } | |
| 2908 | +static void | |
| 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 */ | |
| 2872 | − raw_reg_write(regs, GEN11_GT_INTR_DW(bank), intr_dw); | |
| 2914 | + spin_lock(&i915->irq_lock); | |
| 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 | 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) · 35 unmodified lines | ||
| 2912 | 2960 | return IRQ_HANDLED; |
| 2913 | 2961 | } |
| 2914 | 2962 | |
| 2915 | −/** | |
| 2916 | − * i915_reset_device - do process context error handling work | |
| 2917 | − * @dev_priv: i915 device private | |
| 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) | |
| 2963 | +static void i915_reset_device(struct drm_i915_private *dev_priv, | |
| 2964 | + u32 engine_mask, | |
| 2965 | + const char *reason) | |
| 2923 | 2966 | { |
| 2967 | + struct i915_gpu_error *error = &dev_priv->gpu_error; | |
| 2924 | 2968 | struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; |
| 2925 | 2969 | char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; |
| 2926 | 2970 | char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; |
| @@ -2936,29 +2980,35 @@ static void i915_reset_device(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 2936 | 2980 | i915_wedge_on_timeout(&w, dev_priv, 5*HZ) { |
| 2937 | 2981 | intel_prepare_reset(dev_priv); |
| 2938 | 2982 | |
| 2983 | + error->reason = reason; | |
| 2984 | + error->stalled_mask = engine_mask; | |
| 2985 | + | |
| 2939 | 2986 | /* Signal that locked waiters should reset the GPU */ |
| 2940 | − set_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags); | |
| 2941 | − wake_up_all(&dev_priv->gpu_error.wait_queue); | |
| 2987 | + smp_mb__before_atomic(); | |
| 2988 | + set_bit(I915_RESET_HANDOFF, &error->flags); | |
| 2989 | + wake_up_all(&error->wait_queue); | |
| 2942 | 2990 | |
| 2943 | 2991 | /* Wait for anyone holding the lock to wakeup, without |
| 2944 | 2992 | * blocking indefinitely on struct_mutex. |
| 2945 | 2993 | */ |
| 2946 | 2994 | do { |
| 2947 | 2995 | if (mutex_trylock(&dev_priv->drm.struct_mutex)) { |
| 2948 | − i915_reset(dev_priv, 0); | |
| 2996 | + i915_reset(dev_priv, engine_mask, reason); | |
| 2949 | 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 | 3000 | I915_RESET_HANDOFF, |
| 2953 | 3001 | TASK_UNINTERRUPTIBLE, |
| 2954 | 3002 | 1)); |
| 2955 | 3003 | |
| 3004 | + error->stalled_mask = 0; | |
| 3005 | + error->reason = NULL; | |
| 3006 | + | |
| 2956 | 3007 | intel_finish_reset(dev_priv); |
| 2957 | 3008 | } |
| 2958 | 3009 | |
| 2959 | − if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) | |
| 2960 | − kobject_uevent_env(kobj, | |
| 2961 | − KOBJ_CHANGE, reset_done_event); | |
| 3010 | + if (!test_bit(I915_WEDGED, &error->flags)) | |
| 3011 | + kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); | |
| 2962 | 3012 | } |
| 2963 | 3013 | |
| 2964 | 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) · 25 unmodified lines | ||
| 2990 | 3040 | * i915_handle_error - handle a gpu error |
| 2991 | 3041 | * @dev_priv: i915 device private |
| 2992 | 3042 | * @engine_mask: mask representing engines that are hung |
| 3043 | + * @flags: control flags | |
| 2993 | 3044 | * @fmt: Error message format string |
| 2994 | 3045 | * |
| 2995 | 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) · 4 unmodified lines | ||
| 3000 | 3051 | */ |
| 3001 | 3052 | void i915_handle_error(struct drm_i915_private *dev_priv, |
| 3002 | 3053 | u32 engine_mask, |
| 3054 | + unsigned long flags, | |
| 3003 | 3055 | const char *fmt, ...) |
| 3004 | 3056 | { |
| 3005 | 3057 | struct intel_engine_cs *engine; |
| 3006 | 3058 | unsigned int tmp; |
| 3007 | − va_list args; | |
| 3008 | 3059 | char error_msg[80]; |
| 3060 | + char *msg = NULL; | |
| 3009 | 3061 | |
| 3010 | − va_start(args, fmt); | |
| 3011 | − vscnprintf(error_msg, sizeof(error_msg), fmt, args); | |
| 3012 | − va_end(args); | |
| 3062 | + if (fmt) { | |
| 3063 | + va_list 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 | 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, · 4 unmodified lines | ||
| 3020 | 3078 | */ |
| 3021 | 3079 | intel_runtime_pm_get(dev_priv); |
| 3022 | 3080 | |
| 3023 | − i915_capture_error_state(dev_priv, engine_mask, error_msg); | |
| 3024 | − i915_clear_error_registers(dev_priv); | |
| 3081 | + engine_mask &= INTEL_INFO(dev_priv)->ring_mask; | |
| 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 | 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, · 6 unmodified lines | ||
| 3034 | 3096 | &dev_priv->gpu_error.flags)) |
| 3035 | 3097 | continue; |
| 3036 | 3098 | |
| 3037 | − if (i915_reset_engine(engine, 0) == 0) | |
| 3099 | + if (i915_reset_engine(engine, msg) == 0) | |
| 3038 | 3100 | engine_mask &= ~intel_engine_flag(engine); |
| 3039 | 3101 | |
| 3040 | 3102 | clear_bit(I915_RESET_ENGINE + engine->id, |
| @@ -3064,7 +3126,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv, · 23 unmodified lines | ||
| 3064 | 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 | 3131 | for_each_engine(engine, dev_priv, tmp) { |
| 3070 | 3132 | clear_bit(I915_RESET_ENGINE + engine->id, |
| @@ -3349,6 +3411,9 @@ static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv) · 278 unmodified lines | ||
| 3349 | 3411 | I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~0); |
| 3350 | 3412 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~0); |
| 3351 | 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 | 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) · 532 unmodified lines | ||
| 3887 | 3952 | I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~(irqs | irqs << 16)); |
| 3888 | 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 | 3965 | static int gen11_irq_postinstall(struct drm_device *dev) |
| @@ -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 | +} | |
| @@ -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 | |
| @@ -48,7 +48,7 @@ struct drm_printer; · 47 unmodified lines | ||
| 48 | 48 | param(int, enable_ips, 1) \ |
| 49 | 49 | param(int, invert_brightness, 0) \ |
| 50 | 50 | param(int, enable_guc, 0) \ |
| 51 | − param(int, guc_log_level, 0) \ | |
| 51 | + param(int, guc_log_level, -1) \ | |
| 52 | 52 | param(char *, guc_firmware_path, NULL) \ |
| 53 | 53 | param(char *, huc_firmware_path, NULL) \ |
| 54 | 54 | param(int, mmio_debug, 0) \ |
| @@ -602,6 +602,7 @@ static const struct intel_device_info intel_icelake_11_info = { · 601 unmodified lines | ||
| 602 | 602 | PLATFORM(INTEL_ICELAKE), |
| 603 | 603 | .is_alpha_support = 1, |
| 604 | 604 | .has_resource_streamer = 0, |
| 605 | + .ring_mask = RENDER_RING | BLT_RING | VEBOX_RING | BSD_RING | BSD3_RING, | |
| 605 | 606 | }; |
| 606 | 607 | |
| 607 | 608 | #undef GEN |
| @@ -209,6 +209,7 @@ · 208 unmodified lines | ||
| 209 | 209 | #include "i915_oa_cflgt2.h" |
| 210 | 210 | #include "i915_oa_cflgt3.h" |
| 211 | 211 | #include "i915_oa_cnl.h" |
| 212 | +#include "i915_oa_icl.h" | |
| 212 | 213 | |
| 213 | 214 | /* HW requires this to be a power of two, between 128k and 16M, though driver |
| 214 | 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, · 827 unmodified lines | ||
| 1042 | 1043 | |
| 1043 | 1044 | I915_WRITE(GEN7_OASTATUS2, |
| 1044 | 1045 | ((head & GEN7_OASTATUS2_HEAD_MASK) | |
| 1045 | − OA_MEM_SELECT_GGTT)); | |
| 1046 | + GEN7_OASTATUS2_MEM_SELECT_GGTT)); | |
| 1046 | 1047 | dev_priv->perf.oa.oa_buffer.head = head; |
| 1047 | 1048 | |
| 1048 | 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) · 283 unmodified lines | ||
| 1332 | 1333 | /* Pre-DevBDW: OABUFFER must be set with counters off, |
| 1333 | 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 | 1338 | dev_priv->perf.oa.oa_buffer.head = gtt_offset; |
| 1337 | 1339 | |
| 1338 | 1340 | I915_WRITE(GEN7_OABUFFER, gtt_offset); |
| @@ -1392,7 +1394,7 @@ static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv) · 53 unmodified lines | ||
| 1392 | 1394 | * bit." |
| 1393 | 1395 | */ |
| 1394 | 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 | 1398 | I915_WRITE(GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK); |
| 1397 | 1399 | |
| 1398 | 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, · 441 unmodified lines | ||
| 1840 | 1842 | * be read back from automatically triggered reports, as part of the |
| 1841 | 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 | 1846 | I915_WRITE(GEN8_OA_DEBUG, |
| 1845 | 1847 | _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | |
| 1846 | 1848 | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); |
| @@ -1870,7 +1872,6 @@ static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) · 23 unmodified lines | ||
| 1870 | 1872 | |
| 1871 | 1873 | I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & |
| 1872 | 1874 | ~GT_NOA_ENABLE)); |
| 1873 | − | |
| 1874 | 1875 | } |
| 1875 | 1876 | |
| 1876 | 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) · 8 unmodified lines | ||
| 1885 | 1886 | |
| 1886 | 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 | 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) · 5 unmodified lines | ||
| 1896 | 1904 | */ |
| 1897 | 1905 | gen7_init_oa_buffer(dev_priv); |
| 1898 | 1906 | |
| 1899 | − if (dev_priv->perf.oa.exclusive_stream->enabled) { | |
| 1900 | − struct i915_gem_context *ctx = | |
| 1901 | − dev_priv->perf.oa.exclusive_stream->ctx; | |
| 1902 | − u32 ctx_id = dev_priv->perf.oa.specific_ctx_id; | |
| 1903 | − | |
| 1904 | − bool periodic = dev_priv->perf.oa.periodic; | |
| 1905 | − u32 period_exponent = dev_priv->perf.oa.period_exponent; | |
| 1906 | − u32 report_format = dev_priv->perf.oa.oa_buffer.format; | |
| 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); | |
| 1907 | + I915_WRITE(GEN7_OACONTROL, | |
| 1908 | + (ctx_id & GEN7_OACONTROL_CTX_MASK) | | |
| 1909 | + (period_exponent << | |
| 1910 | + GEN7_OACONTROL_TIMER_PERIOD_SHIFT) | | |
| 1911 | + (periodic ? GEN7_OACONTROL_TIMER_ENABLE : 0) | | |
| 1912 | + (report_format << GEN7_OACONTROL_FORMAT_SHIFT) | | |
| 1913 | + (ctx ? GEN7_OACONTROL_PER_CTX_ENABLE : 0) | | |
| 1914 | + GEN7_OACONTROL_ENABLE); | |
| 1918 | 1915 | } |
| 1919 | 1916 | |
| 1920 | 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, · 178 unmodified lines | ||
| 2099 | 2096 | |
| 2100 | 2097 | if (stream->ctx) { |
| 2101 | 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 | 2101 | return ret; |
| 2102 | + } | |
| 2104 | 2103 | } |
| 2105 | 2104 | |
| 2106 | 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 | 2108 | goto err_config; |
| 2109 | + } | |
| 2109 | 2110 | |
| 2110 | 2111 | /* PRM - observability performance counters: |
| 2111 | 2112 | * |
| @@ -2132,8 +2133,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, · 20 unmodified lines | ||
| 2132 | 2133 | |
| 2133 | 2134 | ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv, |
| 2134 | 2135 | stream->oa_config); |
| 2135 | − if (ret) | |
| 2136 | + if (ret) { | |
| 2137 | + DRM_DEBUG("Unable to enable metric set\n"); | |
| 2136 | 2138 | goto err_enable; |
| 2139 | + } | |
| 2137 | 2140 | |
| 2138 | 2141 | stream->ops = &i915_oa_stream_ops; |
| 2139 | 2142 | |
| @@ -2745,7 +2748,8 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv, · 605 unmodified lines | ||
| 2745 | 2748 | props->ctx_handle = value; |
| 2746 | 2749 | break; |
| 2747 | 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 | 2753 | break; |
| 2750 | 2754 | case DRM_I915_PERF_PROP_OA_METRICS_SET: |
| 2751 | 2755 | if (value == 0) { |
| @@ -2935,6 +2939,8 @@ void i915_perf_register(struct drm_i915_private *dev_priv) · 183 unmodified lines | ||
| 2935 | 2939 | i915_perf_load_test_config_cflgt3(dev_priv); |
| 2936 | 2940 | } else if (IS_CANNONLAKE(dev_priv)) { |
| 2937 | 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 | 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, · 351 unmodified lines | ||
| 3292 | 3298 | |
| 3293 | 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 | 3303 | return oa_config->id; |
| 3296 | 3304 | |
| 3297 | 3305 | sysfs_err: |
| @@ -3348,6 +3356,9 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, · 50 unmodified lines | ||
| 3348 | 3356 | &oa_config->sysfs_metric); |
| 3349 | 3357 | |
| 3350 | 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 | 3362 | put_oa_config(dev_priv, oa_config); |
| 3352 | 3363 | |
| 3353 | 3364 | config_err: |
| @@ -3467,7 +3478,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) · 113 unmodified lines | ||
| 3467 | 3478 | |
| 3468 | 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 | 3482 | dev_priv->perf.oa.ops.is_valid_b_counter_reg = |
| 3472 | 3483 | gen7_is_valid_b_counter_addr; |
| 3473 | 3484 | dev_priv->perf.oa.ops.is_valid_mux_reg = |
| @@ -1,33 +1,12 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright © 2017 Intel Corporation | |
| 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. | |
| 2 | + * SPDX-License-Identifier: MIT | |
| 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 | 7 | #include "i915_pmu.h" |
| 30 | 8 | #include "intel_ringbuffer.h" |
| 9 | +#include "i915_drv.h" | |
| 31 | 10 | |
| 32 | 11 | /* Frequency for the sampling timer for events which need it. */ |
| 33 | 12 | #define FREQUENCY 200 |
| @@ -1,29 +1,19 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright © 2017 Intel Corporation | |
| 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. | |
| 2 | + * SPDX-License-Identifier: MIT | |
| 22 | 3 | * |
| 4 | + * Copyright © 2017-2018 Intel Corporation | |
| 23 | 5 | */ |
| 6 | + | |
| 24 | 7 | #ifndef __I915_PMU_H__ |
| 25 | 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 | 17 | enum { |
| 28 | 18 | __I915_SAMPLE_FREQ_ACT = 0, |
| 29 | 19 | __I915_SAMPLE_FREQ_REQ, |
| @@ -153,9 +153,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 152 unmodified lines | ||
| 153 | 153 | #define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) |
| 154 | 154 | #define _PLL(pll, a, b) ((a) + (pll)*((b)-(a))) |
| 155 | 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 | 156 | #define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) |
| 160 | 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) · 29 unmodified lines | ||
| 191 | 188 | #define OTHER_CLASS 4 |
| 192 | 189 | #define MAX_ENGINE_CLASS 4 |
| 193 | 190 | |
| 191 | +#define OTHER_GTPM_INSTANCE 1 | |
| 194 | 192 | #define MAX_ENGINE_INSTANCE 3 |
| 195 | 193 | |
| 196 | 194 | /* PCI config space */ |
| @@ -304,6 +302,17 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 107 unmodified lines | ||
| 304 | 302 | #define GEN6_GRDOM_VECS (1 << 4) |
| 305 | 303 | #define GEN9_GRDOM_GUC (1 << 5) |
| 306 | 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 | 317 | #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base+0x228) |
| 309 | 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) · 120 unmodified lines | ||
| 430 | 439 | #define VGA_CR_INDEX_CGA 0x3d4 |
| 431 | 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 | 442 | #define MI_PREDICATE_SRC0 _MMIO(0x2400) |
| 573 | 443 | #define MI_PREDICATE_SRC0_UDW _MMIO(0x2400 + 4) |
| 574 | 444 | #define MI_PREDICATE_SRC1 _MMIO(0x2408) |
| @@ -578,130 +448,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 3 unmodified lines | ||
| 578 | 448 | #define LOWER_SLICE_ENABLED (1<<0) |
| 579 | 449 | #define LOWER_SLICE_DISABLED (0<<0) |
| 580 | 450 | |
| 581 | −/* | |
| 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 | 451 | /* |
| 706 | 452 | * Registers used only by the command parser |
| 707 | 453 | */ |
| @@ -802,6 +548,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 94 unmodified lines | ||
| 802 | 548 | |
| 803 | 549 | #define GEN8_OABUFFER_UDW _MMIO(0x23b4) |
| 804 | 550 | #define GEN8_OABUFFER _MMIO(0x2b14) |
| 551 | +#define GEN8_OABUFFER_MEM_SELECT_GGTT (1 << 0) /* 0: PPGTT, 1: GGTT */ | |
| 805 | 552 | |
| 806 | 553 | #define GEN7_OASTATUS1 _MMIO(0x2364) |
| 807 | 554 | #define GEN7_OASTATUS1_TAIL_MASK 0xffffffc0 |
| @@ -810,7 +557,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 2 unmodified lines | ||
| 810 | 557 | #define GEN7_OASTATUS1_REPORT_LOST (1<<0) |
| 811 | 558 | |
| 812 | 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 | 563 | #define GEN8_OASTATUS _MMIO(0x2b08) |
| 816 | 564 | #define GEN8_OASTATUS_OVERRUN_STATUS (1<<3) |
| @@ -832,8 +580,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 15 unmodified lines | ||
| 832 | 580 | #define OABUFFER_SIZE_8M (6<<3) |
| 833 | 581 | #define OABUFFER_SIZE_16M (7<<3) |
| 834 | 582 | |
| 835 | −#define OA_MEM_SELECT_GGTT (1<<0) | |
| 836 | − | |
| 837 | 583 | /* |
| 838 | 584 | * Flexible, Aggregate EU Counter Registers. |
| 839 | 585 | * Note: these aren't contiguous |
| @@ -1127,6 +873,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 287 unmodified lines | ||
| 1127 | 873 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK (1 << GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT) |
| 1128 | 874 | #define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ 0 |
| 1129 | 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 | 882 | #define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT 1 |
| 1131 | 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 { · 815 unmodified lines | ||
| 1948 | 1700 | #define _CNL_PORT_PCS_DW1_LN0_C 0x162C04 |
| 1949 | 1701 | #define _CNL_PORT_PCS_DW1_LN0_D 0x162E04 |
| 1950 | 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 | 1704 | _CNL_PORT_PCS_DW1_GRP_AE, \ |
| 1953 | 1705 | _CNL_PORT_PCS_DW1_GRP_B, \ |
| 1954 | 1706 | _CNL_PORT_PCS_DW1_GRP_C, \ |
| 1955 | 1707 | _CNL_PORT_PCS_DW1_GRP_D, \ |
| 1956 | 1708 | _CNL_PORT_PCS_DW1_GRP_AE, \ |
| 1957 | − _CNL_PORT_PCS_DW1_GRP_F) | |
| 1958 | −#define CNL_PORT_PCS_DW1_LN0(port) _MMIO_PORT6(port, \ | |
| 1709 | + _CNL_PORT_PCS_DW1_GRP_F)) | |
| 1710 | + | |
| 1711 | +#define CNL_PORT_PCS_DW1_LN0(port) _MMIO(_PICK(port, \ | |
| 1959 | 1712 | _CNL_PORT_PCS_DW1_LN0_AE, \ |
| 1960 | 1713 | _CNL_PORT_PCS_DW1_LN0_B, \ |
| 1961 | 1714 | _CNL_PORT_PCS_DW1_LN0_C, \ |
| 1962 | 1715 | _CNL_PORT_PCS_DW1_LN0_D, \ |
| 1963 | 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 | 1728 | #define COMMON_KEEPER_EN (1 << 26) |
| 1966 | 1729 | |
| 1967 | −#define _CNL_PORT_TX_DW2_GRP_AE 0x162348 | |
| 1968 | −#define _CNL_PORT_TX_DW2_GRP_B 0x1623C8 | |
| 1969 | −#define _CNL_PORT_TX_DW2_GRP_C 0x162B48 | |
| 1970 | −#define _CNL_PORT_TX_DW2_GRP_D 0x162BC8 | |
| 1971 | −#define _CNL_PORT_TX_DW2_GRP_F 0x162A48 | |
| 1972 | −#define _CNL_PORT_TX_DW2_LN0_AE 0x162448 | |
| 1973 | −#define _CNL_PORT_TX_DW2_LN0_B 0x162648 | |
| 1974 | −#define _CNL_PORT_TX_DW2_LN0_C 0x162C48 | |
| 1975 | −#define _CNL_PORT_TX_DW2_LN0_D 0x162E48 | |
| 1976 | −#define _CNL_PORT_TX_DW2_LN0_F 0x162848 | |
| 1977 | −#define CNL_PORT_TX_DW2_GRP(port) _MMIO_PORT6(port, \ | |
| 1978 | − _CNL_PORT_TX_DW2_GRP_AE, \ | |
| 1979 | − _CNL_PORT_TX_DW2_GRP_B, \ | |
| 1980 | − _CNL_PORT_TX_DW2_GRP_C, \ | |
| 1981 | − _CNL_PORT_TX_DW2_GRP_D, \ | |
| 1982 | − _CNL_PORT_TX_DW2_GRP_AE, \ | |
| 1983 | − _CNL_PORT_TX_DW2_GRP_F) | |
| 1984 | −#define CNL_PORT_TX_DW2_LN0(port) _MMIO_PORT6(port, \ | |
| 1985 | − _CNL_PORT_TX_DW2_LN0_AE, \ | |
| 1986 | − _CNL_PORT_TX_DW2_LN0_B, \ | |
| 1987 | − _CNL_PORT_TX_DW2_LN0_C, \ | |
| 1988 | − _CNL_PORT_TX_DW2_LN0_D, \ | |
| 1989 | − _CNL_PORT_TX_DW2_LN0_AE, \ | |
| 1990 | − _CNL_PORT_TX_DW2_LN0_F) | |
| 1991 | −#define SWING_SEL_UPPER(x) ((x >> 3) << 15) | |
| 1730 | +/* CNL Port TX registers */ | |
| 1731 | +#define _CNL_PORT_TX_AE_GRP_OFFSET 0x162340 | |
| 1732 | +#define _CNL_PORT_TX_B_GRP_OFFSET 0x1623C0 | |
| 1733 | +#define _CNL_PORT_TX_C_GRP_OFFSET 0x162B40 | |
| 1734 | +#define _CNL_PORT_TX_D_GRP_OFFSET 0x162BC0 | |
| 1735 | +#define _CNL_PORT_TX_F_GRP_OFFSET 0x162A40 | |
| 1736 | +#define _CNL_PORT_TX_AE_LN0_OFFSET 0x162440 | |
| 1737 | +#define _CNL_PORT_TX_B_LN0_OFFSET 0x162640 | |
| 1738 | +#define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40 | |
| 1739 | +#define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40 | |
| 1740 | +#define _CNL_PORT_TX_F_LN0_OFFSET 0x162840 | |
| 1741 | +#define _CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \ | |
| 1742 | + _CNL_PORT_TX_AE_GRP_OFFSET, \ | |
| 1743 | + _CNL_PORT_TX_B_GRP_OFFSET, \ | |
| 1744 | + _CNL_PORT_TX_B_GRP_OFFSET, \ | |
| 1745 | + _CNL_PORT_TX_D_GRP_OFFSET, \ | |
| 1746 | + _CNL_PORT_TX_AE_GRP_OFFSET, \ | |
| 1747 | + _CNL_PORT_TX_F_GRP_OFFSET) + \ | |
| 1748 | + 4*(dw)) | |
| 1749 | +#define _CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \ | |
| 1750 | + _CNL_PORT_TX_AE_LN0_OFFSET, \ | |
| 1751 | + _CNL_PORT_TX_B_LN0_OFFSET, \ | |
| 1752 | + _CNL_PORT_TX_B_LN0_OFFSET, \ | |
| 1753 | + _CNL_PORT_TX_D_LN0_OFFSET, \ | |
| 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 | 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 | 1773 | #define SWING_SEL_LOWER_MASK (0x7 << 11) |
| 1995 | 1774 | #define RCOMP_SCALAR(x) ((x) << 0) |
| 1996 | 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 | 1777 | #define _CNL_PORT_TX_DW4_LN0_AE 0x162450 |
| 2004 | 1778 | #define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0 |
| 2005 | −#define _CNL_PORT_TX_DW4_LN0_B 0x162650 | |
| 2006 | −#define _CNL_PORT_TX_DW4_LN0_C 0x162C50 | |
| 2007 | −#define _CNL_PORT_TX_DW4_LN0_D 0x162E50 | |
| 2008 | −#define _CNL_PORT_TX_DW4_LN0_F 0x162850 | |
| 2009 | −#define CNL_PORT_TX_DW4_GRP(port) _MMIO_PORT6(port, \ | |
| 2010 | − _CNL_PORT_TX_DW4_GRP_AE, \ | |
| 2011 | − _CNL_PORT_TX_DW4_GRP_B, \ | |
| 2012 | − _CNL_PORT_TX_DW4_GRP_C, \ | |
| 2013 | − _CNL_PORT_TX_DW4_GRP_D, \ | |
| 2014 | − _CNL_PORT_TX_DW4_GRP_AE, \ | |
| 2015 | − _CNL_PORT_TX_DW4_GRP_F) | |
| 2016 | −#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO_PORT6_LN(port, ln, \ | |
| 2017 | − _CNL_PORT_TX_DW4_LN0_AE, \ | |
| 2018 | − _CNL_PORT_TX_DW4_LN1_AE, \ | |
| 2019 | − _CNL_PORT_TX_DW4_LN0_B, \ | |
| 2020 | − _CNL_PORT_TX_DW4_LN0_C, \ | |
| 2021 | − _CNL_PORT_TX_DW4_LN0_D, \ | |
| 2022 | − _CNL_PORT_TX_DW4_LN0_AE, \ | |
| 2023 | − _CNL_PORT_TX_DW4_LN0_F) | |
| 1779 | +#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 4)) | |
| 1780 | +#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4)) | |
| 1781 | +#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \ | |
| 1782 | + (ln * (_CNL_PORT_TX_DW4_LN1_AE - \ | |
| 1783 | + _CNL_PORT_TX_DW4_LN0_AE))) | |
| 1784 | +#define _ICL_PORT_TX_DW4_GRP_A 0x162690 | |
| 1785 | +#define _ICL_PORT_TX_DW4_GRP_B 0x6C690 | |
| 1786 | +#define _ICL_PORT_TX_DW4_LN0_A 0x162890 | |
| 1787 | +#define _ICL_PORT_TX_DW4_LN1_A 0x162990 | |
| 1788 | +#define _ICL_PORT_TX_DW4_LN0_B 0x6C890 | |
| 1789 | +#define ICL_PORT_TX_DW4_GRP(port) _MMIO_PORT(port, \ | |
| 1790 | + _ICL_PORT_TX_DW4_GRP_A, \ | |
| 1791 | + _ICL_PORT_TX_DW4_GRP_B) | |
| 1792 | +#define ICL_PORT_TX_DW4_LN(port, ln) _MMIO(_PORT(port, \ | |
| 1793 | + _ICL_PORT_TX_DW4_LN0_A, \ | |
| 1794 | + _ICL_PORT_TX_DW4_LN0_B) + \ | |
| 1795 | + (ln * (_ICL_PORT_TX_DW4_LN1_A - \ | |
| 1796 | + _ICL_PORT_TX_DW4_LN0_A))) | |
| 2024 | 1797 | #define LOADGEN_SELECT (1 << 31) |
| 2025 | 1798 | #define POST_CURSOR_1(x) ((x) << 12) |
| 2026 | 1799 | #define POST_CURSOR_1_MASK (0x3F << 12) |
| @@ -2029,64 +1802,147 @@ enum i915_power_well_id { · 2 unmodified lines | ||
| 2029 | 1802 | #define CURSOR_COEFF(x) ((x) << 0) |
| 2030 | 1803 | #define CURSOR_COEFF_MASK (0x3F << 0) |
| 2031 | 1804 | |
| 2032 | −#define _CNL_PORT_TX_DW5_GRP_AE 0x162354 | |
| 2033 | −#define _CNL_PORT_TX_DW5_GRP_B 0x1623D4 | |
| 2034 | −#define _CNL_PORT_TX_DW5_GRP_C 0x162B54 | |
| 2035 | −#define _CNL_PORT_TX_DW5_GRP_D 0x162BD4 | |
| 2036 | −#define _CNL_PORT_TX_DW5_GRP_F 0x162A54 | |
| 2037 | −#define _CNL_PORT_TX_DW5_LN0_AE 0x162454 | |
| 2038 | −#define _CNL_PORT_TX_DW5_LN0_B 0x162654 | |
| 2039 | −#define _CNL_PORT_TX_DW5_LN0_C 0x162C54 | |
| 2040 | −#define _CNL_PORT_TX_DW5_LN0_D 0x162E54 | |
| 2041 | −#define _CNL_PORT_TX_DW5_LN0_F 0x162854 | |
| 2042 | −#define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \ | |
| 2043 | − _CNL_PORT_TX_DW5_GRP_AE, \ | |
| 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) | |
| 1805 | +#define CNL_PORT_TX_DW5_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 5)) | |
| 1806 | +#define CNL_PORT_TX_DW5_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 5)) | |
| 1807 | +#define _ICL_PORT_TX_DW5_GRP_A 0x162694 | |
| 1808 | +#define _ICL_PORT_TX_DW5_GRP_B 0x6C694 | |
| 1809 | +#define _ICL_PORT_TX_DW5_LN0_A 0x162894 | |
| 1810 | +#define _ICL_PORT_TX_DW5_LN0_B 0x6C894 | |
| 1811 | +#define ICL_PORT_TX_DW5_GRP(port) _MMIO_PORT(port, \ | |
| 1812 | + _ICL_PORT_TX_DW5_GRP_A, \ | |
| 1813 | + _ICL_PORT_TX_DW5_GRP_B) | |
| 1814 | +#define ICL_PORT_TX_DW5_LN0(port) _MMIO_PORT(port, \ | |
| 1815 | + _ICL_PORT_TX_DW5_LN0_A, \ | |
| 1816 | + _ICL_PORT_TX_DW5_LN0_B) | |
| 2056 | 1817 | #define TX_TRAINING_EN (1 << 31) |
| 1818 | +#define TAP2_DISABLE (1 << 30) | |
| 2057 | 1819 | #define TAP3_DISABLE (1 << 29) |
| 2058 | 1820 | #define SCALING_MODE_SEL(x) ((x) << 18) |
| 2059 | 1821 | #define SCALING_MODE_SEL_MASK (0x7 << 18) |
| 2060 | 1822 | #define RTERM_SELECT(x) ((x) << 3) |
| 2061 | 1823 | #define RTERM_SELECT_MASK (0x7 << 3) |
| 2062 | 1824 | |
| 2063 | −#define _CNL_PORT_TX_DW7_GRP_AE 0x16235C | |
| 2064 | −#define _CNL_PORT_TX_DW7_GRP_B 0x1623DC | |
| 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) | |
| 1825 | +#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 7)) | |
| 1826 | +#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 7)) | |
| 2087 | 1827 | #define N_SCALAR(x) ((x) << 24) |
| 2088 | 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 | 1946 | /* The spec defines this only for BXT PHY0, but lets assume that this |
| 2091 | 1947 | * would exist for PHY1 too if it had a second channel. |
| 2092 | 1948 | */ |
| @@ -2473,6 +2329,10 @@ enum i915_power_well_id { · 380 unmodified lines | ||
| 2473 | 2329 | #define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) |
| 2474 | 2330 | #define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) |
| 2475 | 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 | 2336 | #define RING_IPEIR(base) _MMIO((base)+0x64) |
| 2477 | 2337 | #define RING_IPEHR(base) _MMIO((base)+0x68) |
| 2478 | 2338 | /* |
| @@ -2867,6 +2727,19 @@ enum i915_power_well_id { · 388 unmodified lines | ||
| 2867 | 2727 | #define GEN10_EU_DISABLE3 _MMIO(0x9140) |
| 2868 | 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 | 2743 | #define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) |
| 2871 | 2744 | #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) |
| 2872 | 2745 | #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) |
| @@ -3951,6 +3824,9 @@ enum { · 1078 unmodified lines | ||
| 3951 | 3824 | #define _CLKGATE_DIS_PSL_A 0x46520 |
| 3952 | 3825 | #define _CLKGATE_DIS_PSL_B 0x46524 |
| 3953 | 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 | 3830 | #define DPF_GATING_DIS (1 << 10) |
| 3955 | 3831 | #define DPF_RAM_GATING_DIS (1 << 9) |
| 3956 | 3832 | #define DPFR_GATING_DIS (1 << 8) |
| @@ -4151,6 +4027,12 @@ enum { · 194 unmodified lines | ||
| 4151 | 4027 | #define EDP_PSR_IDLE_FRAME_SHIFT 0 |
| 4152 | 4028 | |
| 4153 | 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 | 4036 | #define EDP_PSR_AUX_DATA(i) _MMIO(dev_priv->psr_mmio_base + 0x14 + (i) * 4) /* 5 registers */ |
| 4155 | 4037 | |
| 4156 | 4038 | #define EDP_PSR_STATUS _MMIO(dev_priv->psr_mmio_base + 0x40) |
| @@ -4180,17 +4062,19 @@ enum { · 23 unmodified lines | ||
| 4180 | 4062 | #define EDP_PSR_PERF_CNT _MMIO(dev_priv->psr_mmio_base + 0x44) |
| 4181 | 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 | 4066 | #define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1<<28) |
| 4185 | 4067 | #define EDP_PSR_DEBUG_MASK_LPSP (1<<27) |
| 4186 | 4068 | #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) |
| 4187 | 4069 | #define EDP_PSR_DEBUG_MASK_HPD (1<<25) |
| 4188 | 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 | 4073 | #define EDP_PSR2_CTL _MMIO(0x6f900) |
| 4192 | 4074 | #define EDP_PSR2_ENABLE (1<<31) |
| 4193 | 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 | 4078 | #define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20) |
| 4195 | 4079 | #define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f<<20) |
| 4196 | 4080 | #define EDP_PSR2_TP2_TIME_500 (0<<8) |
| @@ -4200,8 +4084,9 @@ enum { · 3 unmodified lines | ||
| 4200 | 4084 | #define EDP_PSR2_TP2_TIME_MASK (3<<8) |
| 4201 | 4085 | #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 |
| 4202 | 4086 | #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) |
| 4203 | −#define EDP_PSR2_IDLE_MASK 0xf | |
| 4204 | 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 | 4091 | #define EDP_PSR2_STATUS _MMIO(0x6f940) |
| 4207 | 4092 | #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) |
| @@ -5265,8 +5150,6 @@ enum { · 1057 unmodified lines | ||
| 5265 | 5150 | #define DP_LINK_TRAIN_OFF (3 << 28) |
| 5266 | 5151 | #define DP_LINK_TRAIN_MASK (3 << 28) |
| 5267 | 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 | 5154 | /* CPT Link training mode */ |
| 5272 | 5155 | #define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) |
| @@ -6009,6 +5892,7 @@ enum { · 736 unmodified lines | ||
| 6009 | 5892 | #define CURSIZE _MMIO(0x700a0) /* 845/865 */ |
| 6010 | 5893 | #define _CUR_FBC_CTL_A 0x700a0 /* ivb+ */ |
| 6011 | 5894 | #define CUR_FBC_CTL_EN (1 << 31) |
| 5895 | +#define _CURASURFLIVE 0x700ac /* g4x+ */ | |
| 6012 | 5896 | #define _CURBCNTR 0x700c0 |
| 6013 | 5897 | #define _CURBBASE 0x700c4 |
| 6014 | 5898 | #define _CURBPOS 0x700c8 |
| @@ -6025,6 +5909,7 @@ enum { · 10 unmodified lines | ||
| 6025 | 5909 | #define CURBASE(pipe) _CURSOR2(pipe, _CURABASE) |
| 6026 | 5910 | #define CURPOS(pipe) _CURSOR2(pipe, _CURAPOS) |
| 6027 | 5911 | #define CUR_FBC_CTL(pipe) _CURSOR2(pipe, _CUR_FBC_CTL_A) |
| 5912 | +#define CURSURFLIVE(pipe) _CURSOR2(pipe, _CURASURFLIVE) | |
| 6028 | 5913 | |
| 6029 | 5914 | #define CURSOR_A_OFFSET 0x70080 |
| 6030 | 5915 | #define CURSOR_B_OFFSET 0x700c0 |
| @@ -6779,6 +6664,8 @@ enum { · 748 unmodified lines | ||
| 6779 | 6664 | #define PS_SCALER_MODE_MASK (3 << 28) |
| 6780 | 6665 | #define PS_SCALER_MODE_DYN (0 << 28) |
| 6781 | 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 | 6669 | #define PS_PLANE_SEL_MASK (7 << 25) |
| 6783 | 6670 | #define PS_PLANE_SEL(plane) (((plane) + 1) << 25) |
| 6784 | 6671 | #define PS_FILTER_MASK (3 << 23) |
| @@ -7117,7 +7004,9 @@ enum { · 332 unmodified lines | ||
| 7117 | 7004 | #define GEN11_INTR_IDENTITY_REG0 _MMIO(0x190060) |
| 7118 | 7005 | #define GEN11_INTR_IDENTITY_REG1 _MMIO(0x190064) |
| 7119 | 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 | 7011 | #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + (x * 4)) |
| 7123 | 7012 | |
| @@ -7197,6 +7086,7 @@ enum { · 73 unmodified lines | ||
| 7197 | 7086 | #define CHICKEN_TRANS_A 0x420c0 |
| 7198 | 7087 | #define CHICKEN_TRANS_B 0x420c4 |
| 7199 | 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 | 7090 | #define DDI_TRAINING_OVERRIDE_ENABLE (1<<19) |
| 7201 | 7091 | #define DDI_TRAINING_OVERRIDE_VALUE (1<<18) |
| 7202 | 7092 | #define DDIE_TRAINING_OVERRIDE_ENABLE (1<<17) /* CHICKEN_TRANS_A only */ |
| @@ -59,11 +59,7 @@ static bool i915_fence_signaled(struct dma_fence *fence) · 58 unmodified lines | ||
| 59 | 59 | |
| 60 | 60 | static bool i915_fence_enable_signaling(struct dma_fence *fence) |
| 61 | 61 | { |
| 62 | − if (i915_fence_signaled(fence)) | |
| 63 | − return false; | |
| 64 | − | |
| 65 | − intel_engine_enable_signaling(to_request(fence), true); | |
| 66 | − return !i915_fence_signaled(fence); | |
| 62 | + return intel_engine_enable_signaling(to_request(fence), true); | |
| 67 | 63 | } |
| 68 | 64 | |
| 69 | 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) · 141 unmodified lines | ||
| 211 | 207 | if (ret) |
| 212 | 208 | return ret; |
| 213 | 209 | |
| 210 | + GEM_BUG_ON(i915->gt.active_requests); | |
| 211 | + | |
| 214 | 212 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ |
| 215 | 213 | for_each_engine(engine, i915, id) { |
| 216 | 214 | struct i915_gem_timeline *timeline; |
| 217 | 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 | 223 | if (!i915_seqno_passed(seqno, tl->seqno)) { |
| 220 | 224 | /* Flush any waiters before we reuse the seqno */ |
| 221 | 225 | intel_engine_disarm_breadcrumbs(engine); |
| @@ -251,47 +255,6 @@ int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) · 29 unmodified lines | ||
| 251 | 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 | 258 | static int reserve_engine(struct intel_engine_cs *engine) |
| 296 | 259 | { |
| 297 | 260 | struct drm_i915_private *i915 = engine->i915; |
| @@ -309,7 +272,7 @@ static int reserve_engine(struct intel_engine_cs *engine) · 11 unmodified lines | ||
| 309 | 272 | } |
| 310 | 273 | |
| 311 | 274 | if (!i915->gt.active_requests++) |
| 312 | − mark_busy(i915); | |
| 275 | + i915_gem_unpark(i915); | |
| 313 | 276 | |
| 314 | 277 | return 0; |
| 315 | 278 | } |
| @@ -318,13 +281,8 @@ static void unreserve_engine(struct intel_engine_cs *engine) · 2 unmodified lines | ||
| 318 | 281 | { |
| 319 | 282 | struct drm_i915_private *i915 = engine->i915; |
| 320 | 283 | |
| 321 | − if (!--i915->gt.active_requests) { | |
| 322 | − /* Cancel the mark_busy() from our reserve_engine() */ | |
| 323 | − GEM_BUG_ON(!i915->gt.awake); | |
| 324 | − mod_delayed_work(i915->wq, | |
| 325 | − &i915->gt.idle_work, | |
| 326 | − msecs_to_jiffies(100)); | |
| 327 | − } | |
| 284 | + if (!--i915->gt.active_requests) | |
| 285 | + i915_gem_park(i915); | |
| 328 | 286 | |
| 329 | 287 | GEM_BUG_ON(!engine->timeline->inflight_seqnos); |
| 330 | 288 | engine->timeline->inflight_seqnos--; |
| @@ -358,7 +316,7 @@ static void advance_ring(struct i915_request *request) · 27 unmodified lines | ||
| 358 | 316 | * is just about to be. Either works, if we miss the last two |
| 359 | 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 | 320 | } else { |
| 363 | 321 | tail = request->postfix; |
| 364 | 322 | } |
| @@ -385,6 +343,12 @@ static void i915_request_retire(struct i915_request *request) · 20 unmodified lines | ||
| 385 | 343 | struct intel_engine_cs *engine = request->engine; |
| 386 | 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 | 352 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
| 389 | 353 | GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); |
| 390 | 354 | GEM_BUG_ON(!i915_request_completed(request)); |
| @@ -486,21 +450,34 @@ static u32 timeline_get_seqno(struct intel_timeline *tl) · 95 unmodified lines | ||
| 486 | 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 | 464 | void __i915_request_submit(struct i915_request *request) |
| 490 | 465 | { |
| 491 | 466 | struct intel_engine_cs *engine = request->engine; |
| 492 | − struct intel_timeline *timeline; | |
| 493 | 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 | 475 | GEM_BUG_ON(!irqs_disabled()); |
| 496 | 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 | 478 | GEM_BUG_ON(request->global_seqno); |
| 502 | 479 | |
| 503 | − seqno = timeline_get_seqno(timeline); | |
| 480 | + seqno = timeline_get_seqno(engine->timeline); | |
| 504 | 481 | GEM_BUG_ON(!seqno); |
| 505 | 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) · 7 unmodified lines | ||
| 514 | 491 | engine->emit_breadcrumb(request, |
| 515 | 492 | request->ring->vaddr + request->postfix); |
| 516 | 493 | |
| 517 | − spin_lock(&request->timeline->lock); | |
| 518 | − list_move_tail(&request->link, &timeline->requests); | |
| 519 | − spin_unlock(&request->timeline->lock); | |
| 494 | + /* Transfer from per-context onto the global per-engine timeline */ | |
| 495 | + move_to_timeline(request, engine->timeline); | |
| 520 | 496 | |
| 521 | 497 | trace_i915_request_execute(request); |
| 522 | 498 | |
| @@ -539,7 +515,12 @@ void i915_request_submit(struct i915_request *request) · 16 unmodified lines | ||
| 539 | 515 | void __i915_request_unsubmit(struct i915_request *request) |
| 540 | 516 | { |
| 541 | 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 | 525 | GEM_BUG_ON(!irqs_disabled()); |
| 545 | 526 | lockdep_assert_held(&engine->timeline->lock); |
| @@ -562,12 +543,7 @@ void __i915_request_unsubmit(struct i915_request *request) · 16 unmodified lines | ||
| 562 | 543 | spin_unlock(&request->lock); |
| 563 | 544 | |
| 564 | 545 | /* Transfer back from the global per-engine timeline to per-context */ |
| 565 | − timeline = 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); | |
| 546 | + move_to_timeline(request, request->timeline); | |
| 571 | 547 | |
| 572 | 548 | /* |
| 573 | 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) · 426 unmodified lines | ||
| 1000 | 976 | u32 *cs; |
| 1001 | 977 | int err; |
| 1002 | 978 | |
| 979 | + GEM_TRACE("%s fence %llx:%d\n", | |
| 980 | + engine->name, request->fence.context, request->fence.seqno); | |
| 981 | + | |
| 1003 | 982 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
| 1004 | 983 | trace_i915_request_add(request); |
| 1005 | 984 | |
| @@ -1206,11 +1185,13 @@ static bool __i915_spin_request(const struct i915_request *rq, · 200 unmodified lines | ||
| 1206 | 1185 | |
| 1207 | 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 | 1191 | return false; |
| 1211 | 1192 | |
| 1212 | 1193 | __set_current_state(TASK_RUNNING); |
| 1213 | − i915_reset(request->i915, 0); | |
| 1194 | + i915_reset(request->i915, error->stalled_mask, error->reason); | |
| 1214 | 1195 | return true; |
| 1215 | 1196 | } |
| 1216 | 1197 | |
| @@ -40,8 +40,8 @@ · 39 unmodified lines | ||
| 40 | 40 | #undef WARN_ON_ONCE |
| 41 | 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", \ | |
| 44 | − (long)(x), __func__) | |
| 43 | +#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ | |
| 44 | + __stringify(x), (long)(x)) | |
| 45 | 45 | |
| 46 | 46 | #if GCC_VERSION >= 70000 |
| 47 | 47 | #define add_overflows(A, B) \ |
| @@ -227,6 +227,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, · 226 unmodified lines | ||
| 227 | 227 | struct intel_crtc_scaler_state *scaler_state = |
| 228 | 228 | &crtc_state->scaler_state; |
| 229 | 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 | 231 | int num_scalers_need; |
| 231 | 232 | int i, j; |
| 232 | 233 | |
| @@ -304,8 +305,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, · 71 unmodified lines | ||
| 304 | 305 | continue; |
| 305 | 306 | } |
| 306 | 307 | |
| 307 | − plane_state = intel_atomic_get_existing_plane_state(drm_state, | |
| 308 | − intel_plane); | |
| 308 | + plane_state = intel_atomic_get_new_plane_state(intel_state, | |
| 309 | + intel_plane); | |
| 309 | 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, · 16 unmodified lines | ||
| 328 | 329 | } |
| 329 | 330 | |
| 330 | 331 | /* set scaler mode */ |
| 331 | − if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { | |
| 332 | − scaler_state->scalers[*scaler_id].mode = 0; | |
| 332 | + if ((INTEL_GEN(dev_priv) >= 9) && | |
| 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 | 344 | } else if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) { |
| 334 | 345 | /* |
| 335 | 346 | * when only 1 scaler is in use on either pipe A or B, |
| @@ -1215,10 +1215,8 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, · 1214 unmodified lines | ||
| 1215 | 1215 | { |
| 1216 | 1216 | struct child_device_config *it, *child = NULL; |
| 1217 | 1217 | struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; |
| 1218 | − uint8_t hdmi_level_shift; | |
| 1219 | 1218 | int i, j; |
| 1220 | 1219 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; |
| 1221 | − uint8_t aux_channel, ddc_pin; | |
| 1222 | 1220 | /* Each DDI port can have more than one value on the "DVO Port" field, |
| 1223 | 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, · 30 unmodified lines | ||
| 1255 | 1253 | if (!child) |
| 1256 | 1254 | return; |
| 1257 | 1255 | |
| 1258 | − aux_channel = child->aux_channel; | |
| 1259 | − | |
| 1260 | 1256 | is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; |
| 1261 | 1257 | is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; |
| 1262 | 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, · 7 unmodified lines | ||
| 1270 | 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 | 1269 | info->supports_dvi = is_dvi; |
| 1281 | 1270 | info->supports_hdmi = is_hdmi; |
| 1282 | 1271 | info->supports_dp = is_dp; |
| @@ -1302,6 +1291,8 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, · 19 unmodified lines | ||
| 1302 | 1291 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
| 1303 | 1292 | |
| 1304 | 1293 | if (is_dvi) { |
| 1294 | + u8 ddc_pin; | |
| 1295 | + | |
| 1305 | 1296 | ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin); |
| 1306 | 1297 | if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) { |
| 1307 | 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, · 6 unmodified lines | ||
| 1314 | 1305 | } |
| 1315 | 1306 | |
| 1316 | 1307 | if (is_dp) { |
| 1317 | − info->alternate_aux_channel = aux_channel; | |
| 1308 | + info->alternate_aux_channel = child->aux_channel; | |
| 1318 | 1309 | |
| 1319 | 1310 | sanitize_aux_ch(dev_priv, port); |
| 1320 | 1311 | } |
| 1321 | 1312 | |
| 1322 | 1313 | if (bdb_version >= 158) { |
| 1323 | 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 | 1316 | DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", |
| 1326 | 1317 | port_name(port), |
| 1327 | 1318 | hdmi_level_shift); |
| @@ -730,10 +730,11 @@ static void insert_signal(struct intel_breadcrumbs *b, · 729 unmodified lines | ||
| 730 | 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 | 735 | struct intel_engine_cs *engine = request->engine; |
| 736 | 736 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
| 737 | + struct intel_wait *wait = &request->signaling.wait; | |
| 737 | 738 | u32 seqno; |
| 738 | 739 | |
| 739 | 740 | /* |
| @@ -750,12 +751,12 @@ void intel_engine_enable_signaling(struct i915_request *request, bool wakeup) · 10 unmodified lines | ||
| 750 | 751 | |
| 751 | 752 | seqno = i915_request_global_seqno(request); |
| 752 | 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 | − request->signaling.wait.tsk = b->signaler; | |
| 757 | − request->signaling.wait.request = request; | |
| 758 | − request->signaling.wait.seqno = seqno; | |
| 756 | + GEM_BUG_ON(wait->seqno); | |
| 757 | + wait->tsk = b->signaler; | |
| 758 | + wait->request = request; | |
| 759 | + wait->seqno = seqno; | |
| 759 | 760 | |
| 760 | 761 | /* |
| 761 | 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) · 6 unmodified lines | ||
| 768 | 769 | */ |
| 769 | 770 | spin_lock(&b->rb_lock); |
| 770 | 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 | 773 | spin_unlock(&b->rb_lock); |
| 773 | 774 | |
| 774 | − if (wakeup) | |
| 775 | + if (wakeup) { | |
| 775 | 776 | wake_up_process(b->signaler); |
| 777 | + return !intel_wait_complete(wait); | |
| 778 | + } | |
| 779 | + | |
| 780 | + return true; | |
| 776 | 781 | } |
| 777 | 782 | |
| 778 | 783 | void intel_engine_cancel_signaling(struct i915_request *request) |
| @@ -493,6 +493,125 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = { · 492 unmodified lines | ||
| 493 | 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 | 615 | static const struct ddi_buf_trans * |
| 497 | 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, · 376 unmodified lines | ||
| 875 | 994 | |
| 876 | 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 | 998 | case DPLL_ID_WRPLL1: |
| 880 | 999 | return PORT_CLK_SEL_WRPLL1; |
| 881 | 1000 | case DPLL_ID_WRPLL2: |
| @@ -889,7 +1008,7 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) · 7 unmodified lines | ||
| 889 | 1008 | case DPLL_ID_LCPLL_2700: |
| 890 | 1009 | return PORT_CLK_SEL_LCPLL_2700; |
| 891 | 1010 | default: |
| 892 | − MISSING_CASE(pll->id); | |
| 1011 | + MISSING_CASE(pll->info->id); | |
| 893 | 1012 | return PORT_CLK_SEL_NONE; |
| 894 | 1013 | } |
| 895 | 1014 | } |
| @@ -2131,7 +2250,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, · 1235 unmodified lines | ||
| 2131 | 2250 | /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ |
| 2132 | 2251 | val = I915_READ(DPCLKA_CFGCR0); |
| 2133 | 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 | 2254 | I915_WRITE(DPCLKA_CFGCR0, val); |
| 2136 | 2255 | |
| 2137 | 2256 | /* |
| @@ -2148,7 +2267,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, · 10 unmodified lines | ||
| 2148 | 2267 | |
| 2149 | 2268 | val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | |
| 2150 | 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 | 2271 | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); |
| 2153 | 2272 | |
| 2154 | 2273 | I915_WRITE(DPLL_CTRL2, val); |
| @@ -2205,7 +2324,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, · 50 unmodified lines | ||
| 2205 | 2324 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); |
| 2206 | 2325 | |
| 2207 | 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 | 2329 | intel_dp_start_link_train(intel_dp); |
| 2210 | 2330 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) |
| 2211 | 2331 | intel_dp_stop_link_train(intel_dp); |
| @@ -2303,12 +2423,15 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, · 91 unmodified lines | ||
| 2303 | 2423 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2304 | 2424 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2305 | 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 | 2430 | * Power down sink before disabling the port, otherwise we end |
| 2309 | 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 | 2436 | intel_disable_ddi_buf(encoder); |
| 2314 | 2437 | |
| @@ -2424,12 +2547,14 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder, · 109 unmodified lines | ||
| 2424 | 2547 | { |
| 2425 | 2548 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2426 | 2549 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2550 | + struct drm_connector *connector = conn_state->connector; | |
| 2427 | 2551 | enum port port = encoder->port; |
| 2428 | 2552 | |
| 2429 | − intel_hdmi_handle_sink_scrambling(encoder, | |
| 2430 | − conn_state->connector, | |
| 2431 | − crtc_state->hdmi_high_tmds_clock_ratio, | |
| 2432 | − crtc_state->hdmi_scrambling); | |
| 2553 | + if (!intel_hdmi_handle_sink_scrambling(encoder, connector, | |
| 2554 | + crtc_state->hdmi_high_tmds_clock_ratio, | |
| 2555 | + 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 | 2559 | /* Display WA #1143: skl,kbl,cfl */ |
| 2435 | 2560 | if (IS_GEN9_BC(dev_priv)) { |
| @@ -2520,13 +2645,16 @@ static void intel_disable_ddi_hdmi(struct intel_encoder *encoder, · 84 unmodified lines | ||
| 2520 | 2645 | const struct intel_crtc_state *old_crtc_state, |
| 2521 | 2646 | const struct drm_connector_state *old_conn_state) |
| 2522 | 2647 | { |
| 2648 | + struct drm_connector *connector = old_conn_state->connector; | |
| 2649 | + | |
| 2523 | 2650 | if (old_crtc_state->has_audio) |
| 2524 | 2651 | intel_audio_codec_disable(encoder, |
| 2525 | 2652 | old_crtc_state, old_conn_state); |
| 2526 | 2653 | |
| 2527 | − intel_hdmi_handle_sink_scrambling(encoder, | |
| 2528 | − old_conn_state->connector, | |
| 2529 | − false, false); | |
| 2654 | + if (!intel_hdmi_handle_sink_scrambling(encoder, connector, | |
| 2655 | + 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 | 2660 | static void intel_disable_ddi(struct intel_encoder *encoder, |
| @@ -83,11 +83,11 @@ static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) · 82 unmodified lines | ||
| 83 | 83 | { |
| 84 | 84 | int s; |
| 85 | 85 | |
| 86 | − drm_printf(p, "slice mask: %04x\n", sseu->slice_mask); | |
| 87 | − drm_printf(p, "slice total: %u\n", hweight8(sseu->slice_mask)); | |
| 86 | + drm_printf(p, "slice total: %u, mask=%04x\n", | |
| 87 | + hweight8(sseu->slice_mask), sseu->slice_mask); | |
| 88 | 88 | drm_printf(p, "subslice total: %u\n", sseu_subslice_total(sseu)); |
| 89 | − for (s = 0; s < ARRAY_SIZE(sseu->subslice_mask); s++) { | |
| 90 | − drm_printf(p, "slice%d %u subslices mask=%04x\n", | |
| 89 | + for (s = 0; s < sseu->max_slices; s++) { | |
| 90 | + drm_printf(p, "slice%d: %u subslices, mask=%04x\n", | |
| 91 | 91 | s, hweight8(sseu->subslice_mask[s]), |
| 92 | 92 | sseu->subslice_mask[s]); |
| 93 | 93 | } |
| @@ -158,6 +158,45 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu) · 64 unmodified lines | ||
| 158 | 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 | 200 | static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) |
| 162 | 201 | { |
| 163 | 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) · 393 unmodified lines | ||
| 557 | 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 | 645 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) |
| 561 | 646 | { |
| 562 | 647 | u32 f12_5_mhz = 12500; |
| @@ -597,10 +682,9 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) · 34 unmodified lines | ||
| 597 | 682 | } |
| 598 | 683 | |
| 599 | 684 | return freq; |
| 600 | − } else if (INTEL_GEN(dev_priv) <= 10) { | |
| 685 | + } else if (INTEL_GEN(dev_priv) <= 11) { | |
| 601 | 686 | u32 ctc_reg = I915_READ(CTC_MODE); |
| 602 | 687 | u32 freq = 0; |
| 603 | − u32 rpm_config_reg = 0; | |
| 604 | 688 | |
| 605 | 689 | /* First figure out the reference frequency. There are 2 ways |
| 606 | 690 | * we can compute the frequency, either through the |
| @@ -610,20 +694,14 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) · 3 unmodified lines | ||
| 610 | 694 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { |
| 611 | 695 | freq = read_reference_ts_freq(dev_priv); |
| 612 | 696 | } else { |
| 613 | − u32 crystal_clock; | |
| 614 | − | |
| 615 | − rpm_config_reg = I915_READ(RPM_CONFIG0); | |
| 616 | − crystal_clock = (rpm_config_reg & | |
| 617 | − GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
| 618 | − GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
| 619 | − switch (crystal_clock) { | |
| 620 | − case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
| 621 | − freq = f19_2_mhz; | |
| 622 | − break; | |
| 623 | − case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
| 624 | − freq = f24_mhz; | |
| 625 | − break; | |
| 626 | − } | |
| 697 | + u32 rpm_config_reg = I915_READ(RPM_CONFIG0); | |
| 698 | + | |
| 699 | + if (INTEL_GEN(dev_priv) <= 10) | |
| 700 | + freq = gen10_get_crystal_clock_freq(dev_priv, | |
| 701 | + rpm_config_reg); | |
| 702 | + else | |
| 703 | + freq = gen11_get_crystal_clock_freq(dev_priv, | |
| 704 | + rpm_config_reg); | |
| 627 | 705 | |
| 628 | 706 | /* Now figure out how the command stream's timestamp |
| 629 | 707 | * register increments from this frequency (it might |
| @@ -768,8 +846,10 @@ void intel_device_info_runtime_init(struct intel_device_info *info) · 138 unmodified lines | ||
| 768 | 846 | broadwell_sseu_info_init(dev_priv); |
| 769 | 847 | else if (INTEL_GEN(dev_priv) == 9) |
| 770 | 848 | gen9_sseu_info_init(dev_priv); |
| 771 | − else if (INTEL_GEN(dev_priv) >= 10) | |
| 849 | + else if (INTEL_GEN(dev_priv) == 10) | |
| 772 | 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 | 854 | /* Initialize command stream timestamp frequency */ |
| 775 | 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, · 4 unmodified lines | ||
| 780 | 860 | { |
| 781 | 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 | +} | |
| @@ -114,7 +114,7 @@ enum intel_platform { · 113 unmodified lines | ||
| 114 | 114 | func(has_ipc); |
| 115 | 115 | |
| 116 | 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 | 119 | struct sseu_dev_info { |
| 120 | 120 | u8 slice_mask; |
| @@ -247,6 +247,8 @@ void intel_device_info_dump_runtime(const struct intel_device_info *info, · 126 unmodified lines | ||
| 247 | 247 | void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, |
| 248 | 248 | struct drm_printer *p); |
| 249 | 249 | |
| 250 | +void intel_device_info_init_mmio(struct drm_i915_private *dev_priv); | |
| 251 | + | |
| 250 | 252 | void intel_driver_caps_print(const struct intel_driver_caps *caps, |
| 251 | 253 | struct drm_printer *p); |
| 252 | 254 | |
| @@ -488,6 +488,21 @@ static const struct intel_limit intel_limits_bxt = { · 487 unmodified lines | ||
| 488 | 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 | 506 | static bool |
| 492 | 507 | needs_modeset(const struct drm_crtc_state *state) |
| 493 | 508 | { |
| @@ -2657,11 +2672,13 @@ static int i9xx_format_to_fourcc(int format) · 2163 unmodified lines | ||
| 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 | 2677 | switch (format) { |
| 2663 | 2678 | case PLANE_CTL_FORMAT_RGB_565: |
| 2664 | 2679 | return DRM_FORMAT_RGB565; |
| 2680 | + case PLANE_CTL_FORMAT_NV12: | |
| 2681 | + return DRM_FORMAT_NV12; | |
| 2665 | 2682 | default: |
| 2666 | 2683 | case PLANE_CTL_FORMAT_XRGB_8888: |
| 2667 | 2684 | if (rgb_order) { |
| @@ -2858,6 +2875,9 @@ valid_fb: · 190 unmodified lines | ||
| 2858 | 2875 | return; |
| 2859 | 2876 | } |
| 2860 | 2877 | |
| 2878 | + obj = intel_fb_obj(fb); | |
| 2879 | + intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | |
| 2880 | + | |
| 2861 | 2881 | plane_state->src_x = 0; |
| 2862 | 2882 | plane_state->src_y = 0; |
| 2863 | 2883 | plane_state->src_w = fb->width << 16; |
| @@ -2871,7 +2891,6 @@ valid_fb: · 7 unmodified lines | ||
| 2871 | 2891 | intel_state->base.src = drm_plane_state_src(plane_state); |
| 2872 | 2892 | intel_state->base.dst = drm_plane_state_dest(plane_state); |
| 2873 | 2893 | |
| 2874 | − obj = intel_fb_obj(fb); | |
| 2875 | 2894 | if (i915_gem_object_is_tiled(obj)) |
| 2876 | 2895 | dev_priv->preserve_bios_swizzle = true; |
| 2877 | 2896 | |
| @@ -3464,6 +3483,8 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format) · 586 unmodified lines | ||
| 3464 | 3483 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY; |
| 3465 | 3484 | case DRM_FORMAT_VYUY: |
| 3466 | 3485 | return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY; |
| 3486 | + case DRM_FORMAT_NV12: | |
| 3487 | + return PLANE_CTL_FORMAT_NV12; | |
| 3467 | 3488 | default: |
| 3468 | 3489 | MISSING_CASE(pixel_format); |
| 3469 | 3490 | } |
| @@ -3611,6 +3632,11 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, · 141 unmodified lines | ||
| 3611 | 3632 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); |
| 3612 | 3633 | |
| 3613 | 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 | 3640 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) |
| 3615 | 3641 | plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; |
| 3616 | 3642 | else |
| @@ -3619,7 +3645,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, · 2 unmodified lines | ||
| 3619 | 3645 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) |
| 3620 | 3646 | plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; |
| 3621 | 3647 | } |
| 3622 | − | |
| 3648 | +out: | |
| 3623 | 3649 | return plane_color_ctl; |
| 3624 | 3650 | } |
| 3625 | 3651 | |
| @@ -3675,7 +3701,6 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) · 49 unmodified lines | ||
| 3675 | 3701 | struct drm_atomic_state *state; |
| 3676 | 3702 | int ret; |
| 3677 | 3703 | |
| 3678 | − | |
| 3679 | 3704 | /* reset doesn't touch the display */ |
| 3680 | 3705 | if (!i915_modparams.force_reset_modeset_test && |
| 3681 | 3706 | !gpu_reset_clobbers_display(dev_priv)) |
| @@ -3729,19 +3754,17 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) · 47 unmodified lines | ||
| 3729 | 3754 | { |
| 3730 | 3755 | struct drm_device *dev = &dev_priv->drm; |
| 3731 | 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 | 3758 | int ret; |
| 3734 | 3759 | |
| 3735 | 3760 | /* reset doesn't touch the display */ |
| 3736 | − if (!i915_modparams.force_reset_modeset_test && | |
| 3737 | − !gpu_reset_clobbers_display(dev_priv)) | |
| 3761 | + if (!test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags)) | |
| 3738 | 3762 | return; |
| 3739 | 3763 | |
| 3764 | + state = fetch_and_zero(&dev_priv->modeset_restore_state); | |
| 3740 | 3765 | if (!state) |
| 3741 | 3766 | goto unlock; |
| 3742 | 3767 | |
| 3743 | − dev_priv->modeset_restore_state = NULL; | |
| 3744 | − | |
| 3745 | 3768 | /* reset doesn't touch the display */ |
| 3746 | 3769 | if (!gpu_reset_clobbers_display(dev_priv)) { |
| 3747 | 3770 | /* for testing only restore the display */ |
| @@ -4703,7 +4726,9 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) · 955 unmodified lines | ||
| 4703 | 4726 | static int |
| 4704 | 4727 | skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, |
| 4705 | 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 | 4733 | struct intel_crtc_scaler_state *scaler_state = |
| 4709 | 4734 | &crtc_state->scaler_state; |
| @@ -4721,6 +4746,10 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, · 11 unmodified lines | ||
| 4721 | 4746 | */ |
| 4722 | 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 | 4753 | if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX) |
| 4725 | 4754 | need_scaling = true; |
| 4726 | 4755 | |
| @@ -4760,12 +4789,22 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, · 33 unmodified lines | ||
| 4760 | 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 | 4799 | /* range checks */ |
| 4764 | 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 || | |
| 4766 | − | |
| 4767 | − src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || | |
| 4768 | − dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H) { | |
| 4801 | + dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || | |
| 4802 | + (IS_GEN11(dev_priv) && | |
| 4803 | + (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_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 | 4808 | DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u " |
| 4770 | 4809 | "size is out of scaler range\n", |
| 4771 | 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) · 24 unmodified lines | ||
| 4796 | 4835 | const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode; |
| 4797 | 4836 | |
| 4798 | 4837 | return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, |
| 4799 | − &state->scaler_state.scaler_id, | |
| 4800 | − state->pipe_src_w, state->pipe_src_h, | |
| 4801 | − adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay); | |
| 4838 | + &state->scaler_state.scaler_id, | |
| 4839 | + state->pipe_src_w, state->pipe_src_h, | |
| 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, · 22 unmodified lines | ||
| 4827 | 4867 | drm_rect_width(&plane_state->base.src) >> 16, |
| 4828 | 4868 | drm_rect_height(&plane_state->base.src) >> 16, |
| 4829 | 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 | 4873 | if (ret || plane_state->scaler_id < 0) |
| 4833 | 4874 | return ret; |
| @@ -4853,6 +4894,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, · 19 unmodified lines | ||
| 4853 | 4894 | case DRM_FORMAT_YVYU: |
| 4854 | 4895 | case DRM_FORMAT_UYVY: |
| 4855 | 4896 | case DRM_FORMAT_VYUY: |
| 4897 | + case DRM_FORMAT_NV12: | |
| 4856 | 4898 | break; |
| 4857 | 4899 | default: |
| 4858 | 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 · 240 unmodified lines | ||
| 5099 | 5141 | static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) |
| 5100 | 5142 | { |
| 5101 | 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 | 5146 | struct drm_atomic_state *old_state = old_crtc_state->base.state; |
| 5103 | 5147 | struct intel_crtc_state *pipe_config = |
| 5104 | 5148 | intel_atomic_get_new_crtc_state(to_intel_atomic_state(old_state), |
| 5105 | 5149 | crtc); |
| 5106 | 5150 | struct drm_plane *primary = crtc->base.primary; |
| 5107 | − struct drm_plane_state *old_pri_state = | |
| 5108 | − drm_atomic_get_existing_plane_state(old_state, primary); | |
| 5151 | + struct drm_plane_state *old_primary_state = | |
| 5152 | + drm_atomic_get_old_plane_state(old_state, primary); | |
| 5109 | 5153 | |
| 5110 | 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) · 3 unmodified lines | ||
| 5115 | 5159 | if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) |
| 5116 | 5160 | hsw_enable_ips(pipe_config); |
| 5117 | 5161 | |
| 5118 | − if (old_pri_state) { | |
| 5119 | − struct intel_plane_state *primary_state = | |
| 5120 | − intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state), | |
| 5121 | − to_intel_plane(primary)); | |
| 5122 | − struct intel_plane_state *old_primary_state = | |
| 5123 | − to_intel_plane_state(old_pri_state); | |
| 5162 | + if (old_primary_state) { | |
| 5163 | + struct drm_plane_state *new_primary_state = | |
| 5164 | + drm_atomic_get_new_plane_state(old_state, primary); | |
| 5165 | + struct drm_framebuffer *fb = new_primary_state->fb; | |
| 5124 | 5166 | |
| 5125 | 5167 | intel_fbc_post_update(crtc); |
| 5126 | 5168 | |
| 5127 | − if (primary_state->base.visible && | |
| 5169 | + if (new_primary_state->visible && | |
| 5128 | 5170 | (needs_modeset(&pipe_config->base) || |
| 5129 | − !old_primary_state->base.visible)) | |
| 5171 | + !old_primary_state->visible)) | |
| 5130 | 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, · 5 unmodified lines | ||
| 5139 | 5189 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 5140 | 5190 | struct drm_atomic_state *old_state = old_crtc_state->base.state; |
| 5141 | 5191 | struct drm_plane *primary = crtc->base.primary; |
| 5142 | − struct drm_plane_state *old_pri_state = | |
| 5143 | − drm_atomic_get_existing_plane_state(old_state, primary); | |
| 5192 | + struct drm_plane_state *old_primary_state = | |
| 5193 | + drm_atomic_get_old_plane_state(old_state, primary); | |
| 5144 | 5194 | bool modeset = needs_modeset(&pipe_config->base); |
| 5145 | 5195 | struct intel_atomic_state *old_intel_state = |
| 5146 | 5196 | to_intel_atomic_state(old_state); |
| @@ -5148,20 +5198,26 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, · 1 unmodified line | ||
| 5148 | 5198 | if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) |
| 5149 | 5199 | hsw_disable_ips(old_crtc_state); |
| 5150 | 5200 | |
| 5151 | − if (old_pri_state) { | |
| 5152 | − struct intel_plane_state *primary_state = | |
| 5201 | + if (old_primary_state) { | |
| 5202 | + struct intel_plane_state *new_primary_state = | |
| 5153 | 5203 | intel_atomic_get_new_plane_state(old_intel_state, |
| 5154 | 5204 | to_intel_plane(primary)); |
| 5155 | − struct intel_plane_state *old_primary_state = | |
| 5156 | − to_intel_plane_state(old_pri_state); | |
| 5205 | + struct drm_framebuffer *fb = new_primary_state->base.fb; | |
| 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 | 5216 | * Gen2 reports pipe underruns whenever all planes are disabled. |
| 5161 | 5217 | * So disable underrun reporting before all the planes get disabled. |
| 5162 | 5218 | */ |
| 5163 | − if (IS_GEN2(dev_priv) && old_primary_state->base.visible && | |
| 5164 | − (modeset || !primary_state->base.visible)) | |
| 5219 | + if (IS_GEN2(dev_priv) && old_primary_state->visible && | |
| 5220 | + (modeset || !new_primary_state->base.visible)) | |
| 5165 | 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, · 3598 unmodified lines | ||
| 8766 | 8822 | intel_get_shared_dpll_by_id(dev_priv, pll_id); |
| 8767 | 8823 | pll = pipe_config->shared_dpll; |
| 8768 | 8824 | |
| 8769 | − WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, | |
| 8770 | − &pipe_config->dpll_hw_state)); | |
| 8825 | + WARN_ON(!pll->info->funcs->get_hw_state(dev_priv, pll, | |
| 8826 | + &pipe_config->dpll_hw_state)); | |
| 8771 | 8827 | |
| 8772 | 8828 | tmp = pipe_config->dpll_hw_state.dpll; |
| 8773 | 8829 | pipe_config->pixel_multiplier = |
| @@ -9243,8 +9299,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, · 469 unmodified lines | ||
| 9243 | 9299 | |
| 9244 | 9300 | pll = pipe_config->shared_dpll; |
| 9245 | 9301 | if (pll) { |
| 9246 | − WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, | |
| 9247 | − &pipe_config->dpll_hw_state)); | |
| 9302 | + WARN_ON(!pll->info->funcs->get_hw_state(dev_priv, pll, | |
| 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) · 1524 unmodified lines | ||
| 10775 | 10831 | struct drm_connector_state *connector_state; |
| 10776 | 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 | 10835 | if (!connector_state) |
| 10780 | 10836 | connector_state = connector->state; |
| 10781 | 10837 | |
| @@ -11645,11 +11701,11 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv, · 863 unmodified lines | ||
| 11645 | 11701 | |
| 11646 | 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 | 11709 | I915_STATE_WARN(!pll->on && pll->active_mask, |
| 11654 | 11710 | "pll in active use but not on in sw tracking\n"); |
| 11655 | 11711 | I915_STATE_WARN(pll->on && !pll->active_mask, |
| @@ -12138,20 +12194,23 @@ static void intel_update_crtc(struct drm_crtc *crtc, · 482 unmodified lines | ||
| 12138 | 12194 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 12139 | 12195 | struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state); |
| 12140 | 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 | 12201 | if (modeset) { |
| 12143 | 12202 | update_scanline_offset(intel_crtc); |
| 12144 | 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 | 12207 | } else { |
| 12146 | 12208 | intel_pre_plane_update(to_intel_crtc_state(old_crtc_state), |
| 12147 | 12209 | pipe_config); |
| 12148 | 12210 | } |
| 12149 | 12211 | |
| 12150 | − if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { | |
| 12151 | − intel_fbc_enable( | |
| 12152 | − intel_crtc, pipe_config, | |
| 12153 | − to_intel_plane_state(crtc->primary->state)); | |
| 12154 | − } | |
| 12212 | + if (new_plane_state) | |
| 12213 | + intel_fbc_enable(intel_crtc, pipe_config, new_plane_state); | |
| 12155 | 12214 | |
| 12156 | 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) · 164 unmodified lines | ||
| 12322 | 12381 | |
| 12323 | 12382 | if (old_crtc_state->active) { |
| 12324 | 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 | 12391 | dev_priv->display.crtc_disable(to_intel_crtc_state(old_crtc_state), state); |
| 12326 | 12392 | intel_crtc->active = false; |
| 12327 | 12393 | intel_fbc_disable(intel_crtc); |
| @@ -12725,8 +12791,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, · 397 unmodified lines | ||
| 12725 | 12791 | |
| 12726 | 12792 | if (old_obj) { |
| 12727 | 12793 | struct drm_crtc_state *crtc_state = |
| 12728 | − drm_atomic_get_existing_crtc_state(new_state->state, | |
| 12729 | − plane->state->crtc); | |
| 12794 | + drm_atomic_get_new_crtc_state(new_state->state, | |
| 12795 | + plane->state->crtc); | |
| 12730 | 12796 | |
| 12731 | 12797 | /* Big Hammer, we also need to ensure that any pending |
| 12732 | 12798 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the |
| @@ -12780,6 +12846,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, · 47 unmodified lines | ||
| 12780 | 12846 | if (ret) |
| 12781 | 12847 | return ret; |
| 12782 | 12848 | |
| 12849 | + intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); | |
| 12850 | + | |
| 12783 | 12851 | if (!new_state->fence) { /* implicit fencing */ |
| 12784 | 12852 | struct dma_fence *fence; |
| 12785 | 12853 | |
| @@ -12824,11 +12892,13 @@ intel_cleanup_plane_fb(struct drm_plane *plane, · 38 unmodified lines | ||
| 12824 | 12892 | } |
| 12825 | 12893 | |
| 12826 | 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 | 12899 | struct drm_i915_private *dev_priv; |
| 12830 | − int max_scale; | |
| 12831 | − int crtc_clock, max_dotclk; | |
| 12900 | + int max_scale, mult; | |
| 12901 | + int crtc_clock, max_dotclk, tmpclk1, tmpclk2; | |
| 12832 | 12902 | |
| 12833 | 12903 | if (!intel_crtc || !crtc_state->base.enable) |
| 12834 | 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 · 15 unmodified lines | ||
| 12850 | 12920 | * or |
| 12851 | 12921 | * cdclk/crtc_clock |
| 12852 | 12922 | */ |
| 12853 | − max_scale = min((1 << 16) * 3 - 1, | |
| 12854 | − (1 << 8) * ((max_dotclk << 8) / crtc_clock)); | |
| 12923 | + mult = pixel_format == DRM_FORMAT_NV12 ? 2 : 3; | |
| 12924 | + tmpclk1 = (1 << 16) * mult - 1; | |
| 12925 | + tmpclk2 = (1 << 8) * ((max_dotclk << 8) / crtc_clock); | |
| 12926 | + max_scale = min(tmpclk1, tmpclk2); | |
| 12855 | 12927 | |
| 12856 | 12928 | return max_scale; |
| 12857 | 12929 | } |
| @@ -12867,12 +12939,16 @@ intel_check_primary_plane(struct intel_plane *plane, · 9 unmodified lines | ||
| 12867 | 12939 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; |
| 12868 | 12940 | bool can_position = false; |
| 12869 | 12941 | int ret; |
| 12942 | + uint32_t pixel_format = 0; | |
| 12870 | 12943 | |
| 12871 | 12944 | if (INTEL_GEN(dev_priv) >= 9) { |
| 12872 | 12945 | /* use scaler when colorkey is not required */ |
| 12873 | 12946 | if (!state->ckey.flags) { |
| 12874 | 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 | 12953 | can_position = true; |
| 12878 | 12954 | } |
| @@ -12945,10 +13021,25 @@ out: · 66 unmodified lines | ||
| 12945 | 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 | 13040 | static void intel_finish_crtc_commit(struct drm_crtc *crtc, |
| 12949 | 13041 | struct drm_crtc_state *old_crtc_state) |
| 12950 | 13042 | { |
| 12951 | − struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 12952 | 13043 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 12953 | 13044 | struct intel_atomic_state *old_intel_state = |
| 12954 | 13045 | to_intel_atomic_state(old_crtc_state->state); |
| @@ -12959,17 +13050,8 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, · 4 unmodified lines | ||
| 12959 | 13050 | |
| 12960 | 13051 | if (new_crtc_state->update_pipe && |
| 12961 | 13052 | !needs_modeset(&new_crtc_state->base) && |
| 12962 | − old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) { | |
| 12963 | − if (!IS_GEN2(dev_priv)) | |
| 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 | − } | |
| 13053 | + old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) | |
| 13054 | + intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state); | |
| 12973 | 13055 | } |
| 12974 | 13056 | |
| 12975 | 13057 | /** |
| @@ -13167,8 +13249,9 @@ intel_legacy_cursor_update(struct drm_plane *plane, · 191 unmodified lines | ||
| 13167 | 13249 | if (ret) |
| 13168 | 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 | 13255 | i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), |
| 13173 | 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) · 380 unmodified lines | ||
| 13555 | 13638 | /* initialize shared scalers */ |
| 13556 | 13639 | intel_crtc_init_scalers(intel_crtc, crtc_state); |
| 13557 | 13640 | |
| 13558 | − BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || | |
| 13559 | − dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] != NULL); | |
| 13560 | − dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] = intel_crtc; | |
| 13561 | − dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc; | |
| 13641 | + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || | |
| 13642 | + dev_priv->pipe_to_crtc_mapping[pipe] != NULL); | |
| 13643 | + dev_priv->pipe_to_crtc_mapping[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 | 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) · 1538 unmodified lines | ||
| 15103 | 15193 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
| 15104 | 15194 | struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; |
| 15105 | 15195 | |
| 15106 | − pll->on = pll->funcs.get_hw_state(dev_priv, pll, | |
| 15107 | − &pll->state.hw_state); | |
| 15196 | + pll->on = pll->info->funcs->get_hw_state(dev_priv, pll, | |
| 15197 | + &pll->state.hw_state); | |
| 15108 | 15198 | pll->state.crtc_mask = 0; |
| 15109 | 15199 | for_each_intel_crtc(dev, crtc) { |
| 15110 | 15200 | struct intel_crtc_state *crtc_state = |
| @@ -15117,7 +15207,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) · 6 unmodified lines | ||
| 15117 | 15207 | pll->active_mask = pll->state.crtc_mask; |
| 15118 | 15208 | |
| 15119 | 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 | 15213 | for_each_intel_encoder(dev, encoder) { |
| @@ -15291,9 +15381,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev, · 167 unmodified lines | ||
| 15291 | 15381 | if (!pll->on || pll->active_mask) |
| 15292 | 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 | 15388 | pll->on = false; |
| 15298 | 15389 | } |
| 15299 | 15390 | |
| @@ -43,7 +43,6 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <drm/i915_drm.h> |
| 44 | 44 | #include "i915_drv.h" |
| 45 | 45 | |
| 46 | −#define DP_LINK_CHECK_TIMEOUT (10 * 1000) | |
| 47 | 46 | #define DP_DPRX_ESI_LEN 14 |
| 48 | 47 | |
| 49 | 48 | /* Compliance test status bits */ |
| @@ -92,8 +91,6 @@ static const struct dp_link_dpll chv_dpll[] = { · 42 unmodified lines | ||
| 92 | 91 | { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, |
| 93 | 92 | { 270000, /* m2_int = 27, m2_fraction = 0 */ |
| 94 | 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, · 2801 unmodified lines | ||
| 2901 | 2898 | } |
| 2902 | 2899 | |
| 2903 | 2900 | } else { |
| 2904 | − if (IS_CHERRYVIEW(dev_priv)) | |
| 2905 | − *DP &= ~DP_LINK_TRAIN_MASK_CHV; | |
| 2906 | − else | |
| 2907 | − *DP &= ~DP_LINK_TRAIN_MASK; | |
| 2901 | + *DP &= ~DP_LINK_TRAIN_MASK; | |
| 2908 | 2902 | |
| 2909 | 2903 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
| 2910 | 2904 | case DP_TRAINING_PATTERN_DISABLE: |
| @@ -2917,12 +2911,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, · 6 unmodified lines | ||
| 2917 | 2911 | *DP |= DP_LINK_TRAIN_PAT_2; |
| 2918 | 2912 | break; |
| 2919 | 2913 | case DP_TRAINING_PATTERN_3: |
| 2920 | − if (IS_CHERRYVIEW(dev_priv)) { | |
| 2921 | − *DP |= DP_LINK_TRAIN_PAT_3_CHV; | |
| 2922 | − } else { | |
| 2923 | − DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); | |
| 2924 | − *DP |= DP_LINK_TRAIN_PAT_2; | |
| 2925 | − } | |
| 2914 | + DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); | |
| 2915 | + *DP |= DP_LINK_TRAIN_PAT_2; | |
| 2926 | 2916 | break; |
| 2927 | 2917 | } |
| 2928 | 2918 | } |
| @@ -3661,10 +3651,7 @@ intel_dp_link_down(struct intel_encoder *encoder, · 732 unmodified lines | ||
| 3661 | 3651 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
| 3662 | 3652 | DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; |
| 3663 | 3653 | } else { |
| 3664 | − if (IS_CHERRYVIEW(dev_priv)) | |
| 3665 | − DP &= ~DP_LINK_TRAIN_MASK_CHV; | |
| 3666 | − else | |
| 3667 | − DP &= ~DP_LINK_TRAIN_MASK; | |
| 3654 | + DP &= ~DP_LINK_TRAIN_MASK; | |
| 3668 | 3655 | DP |= DP_LINK_TRAIN_PAT_IDLE; |
| 3669 | 3656 | } |
| 3670 | 3657 | I915_WRITE(intel_dp->output_reg, DP); |
| @@ -180,9 +180,11 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, · 179 unmodified lines | ||
| 180 | 180 | intel_dp->active_mst_links--; |
| 181 | 181 | |
| 182 | 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 | 185 | intel_dig_port->base.post_disable(&intel_dig_port->base, |
| 185 | 186 | old_crtc_state, NULL); |
| 187 | + } | |
| 186 | 188 | |
| 187 | 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, · 34 unmodified lines | ||
| 223 | 225 | |
| 224 | 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 | 231 | drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); |
| 232 | + | |
| 227 | 233 | if (intel_dp->active_mst_links == 0) |
| 228 | 234 | intel_dig_port->base.pre_enable(&intel_dig_port->base, |
| 229 | 235 | pipe_config, NULL); |
| @@ -380,13 +380,14 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, · 379 unmodified lines | ||
| 380 | 380 | * all 1s. Eventually they become accessible as they power up, then |
| 381 | 381 | * the reserved bit will give the default 0. Poll on the reserved bit |
| 382 | 382 | * becoming 0 to find when the PHY is accessible. |
| 383 | − * HW team confirmed that the time to reach phypowergood status is | |
| 384 | − * anywhere between 50 us and 100us. | |
| 383 | + * The flag should get set in 100us according to the HW team, but | |
| 384 | + * use 1ms due to occasional timeouts observed with that. | |
| 385 | 385 | */ |
| 386 | − if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & | |
| 387 | − (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { | |
| 386 | + if (intel_wait_for_register_fw(dev_priv, BXT_PORT_CL1CM_DW0(phy), | |
| 387 | + PHY_RESERVED | PHY_POWER_GOOD, | |
| 388 | + PHY_POWER_GOOD, | |
| 389 | + 1)) | |
| 388 | 390 | DRM_ERROR("timeout during PHY%d power on\n", phy); |
| 389 | − } | |
| 390 | 391 | |
| 391 | 392 | /* Program PLL Rcomp code offset */ |
| 392 | 393 | val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); |
| @@ -118,10 +118,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, · 117 unmodified lines | ||
| 118 | 118 | if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) |
| 119 | 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 | 122 | I915_STATE_WARN(cur_state != state, |
| 123 | 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) · 15 unmodified lines | ||
| 143 | 143 | mutex_lock(&dev_priv->dpll_lock); |
| 144 | 144 | WARN_ON(!pll->state.crtc_mask); |
| 145 | 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 | 147 | WARN_ON(pll->on); |
| 148 | 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 | 152 | mutex_unlock(&dev_priv->dpll_lock); |
| 153 | 153 | } |
| @@ -179,7 +179,7 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) · 25 unmodified lines | ||
| 179 | 179 | pll->active_mask |= crtc_mask; |
| 180 | 180 | |
| 181 | 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 | 183 | crtc->base.base.id); |
| 184 | 184 | |
| 185 | 185 | if (old_mask) { |
| @@ -189,8 +189,8 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) · 3 unmodified lines | ||
| 189 | 189 | } |
| 190 | 190 | WARN_ON(pll->on); |
| 191 | 191 | |
| 192 | − DRM_DEBUG_KMS("enabling %s\n", pll->name); | |
| 193 | − pll->funcs.enable(dev_priv, pll); | |
| 192 | + DRM_DEBUG_KMS("enabling %s\n", pll->info->name); | |
| 193 | + pll->info->funcs->enable(dev_priv, pll); | |
| 194 | 194 | pll->on = true; |
| 195 | 195 | |
| 196 | 196 | out: |
| @@ -221,7 +221,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) · 24 unmodified lines | ||
| 221 | 221 | goto out; |
| 222 | 222 | |
| 223 | 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 | 225 | crtc->base.base.id); |
| 226 | 226 | |
| 227 | 227 | assert_shared_dpll_enabled(dev_priv, pll); |
| @@ -231,8 +231,8 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) · 3 unmodified lines | ||
| 231 | 231 | if (pll->active_mask) |
| 232 | 232 | goto out; |
| 233 | 233 | |
| 234 | − DRM_DEBUG_KMS("disabling %s\n", pll->name); | |
| 235 | − pll->funcs.disable(dev_priv, pll); | |
| 234 | + DRM_DEBUG_KMS("disabling %s\n", pll->info->name); | |
| 235 | + pll->info->funcs->disable(dev_priv, pll); | |
| 236 | 236 | pll->on = false; |
| 237 | 237 | |
| 238 | 238 | out: |
| @@ -263,7 +263,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc, · 24 unmodified lines | ||
| 263 | 263 | &shared_dpll[i].hw_state, |
| 264 | 264 | sizeof(crtc_state->dpll_hw_state)) == 0) { |
| 265 | 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 | 268 | shared_dpll[i].crtc_mask, |
| 268 | 269 | pll->active_mask); |
| 269 | 270 | return pll; |
| @@ -275,7 +276,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc, · 5 unmodified lines | ||
| 275 | 276 | pll = &dev_priv->shared_dplls[i]; |
| 276 | 277 | if (shared_dpll[i].crtc_mask == 0) { |
| 277 | 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 | 281 | return pll; |
| 280 | 282 | } |
| 281 | 283 | } |
| @@ -289,19 +291,19 @@ intel_reference_shared_dpll(struct intel_shared_dpll *pll, · 7 unmodified lines | ||
| 289 | 291 | { |
| 290 | 292 | struct intel_shared_dpll_state *shared_dpll; |
| 291 | 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 | 296 | shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); |
| 295 | 297 | |
| 296 | − if (shared_dpll[i].crtc_mask == 0) | |
| 297 | − shared_dpll[i].hw_state = | |
| 298 | + if (shared_dpll[id].crtc_mask == 0) | |
| 299 | + shared_dpll[id].hw_state = | |
| 298 | 300 | crtc_state->dpll_hw_state; |
| 299 | 301 | |
| 300 | 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 | 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, · 33 unmodified lines | ||
| 341 | 343 | struct intel_shared_dpll *pll, |
| 342 | 344 | struct intel_dpll_hw_state *hw_state) |
| 343 | 345 | { |
| 346 | + const enum intel_dpll_id id = pll->info->id; | |
| 344 | 347 | uint32_t val; |
| 345 | 348 | |
| 346 | 349 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
| 347 | 350 | return false; |
| 348 | 351 | |
| 349 | − val = I915_READ(PCH_DPLL(pll->id)); | |
| 352 | + val = I915_READ(PCH_DPLL(id)); | |
| 350 | 353 | hw_state->dpll = val; |
| 351 | − hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); | |
| 352 | − hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); | |
| 354 | + hw_state->fp0 = I915_READ(PCH_FP0(id)); | |
| 355 | + hw_state->fp1 = I915_READ(PCH_FP1(id)); | |
| 353 | 356 | |
| 354 | 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, · 3 unmodified lines | ||
| 359 | 362 | static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv, |
| 360 | 363 | struct intel_shared_dpll *pll) |
| 361 | 364 | { |
| 362 | − I915_WRITE(PCH_FP0(pll->id), pll->state.hw_state.fp0); | |
| 363 | − I915_WRITE(PCH_FP1(pll->id), pll->state.hw_state.fp1); | |
| 365 | + const enum intel_dpll_id id = pll->info->id; | |
| 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 | 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) · 12 unmodified lines | ||
| 379 | 384 | static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, |
| 380 | 385 | struct intel_shared_dpll *pll) |
| 381 | 386 | { |
| 387 | + const enum intel_dpll_id id = pll->info->id; | |
| 388 | + | |
| 382 | 389 | /* PCH refclock must be enabled first */ |
| 383 | 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 | 394 | /* Wait for the clocks to stabilize. */ |
| 388 | − POSTING_READ(PCH_DPLL(pll->id)); | |
| 395 | + POSTING_READ(PCH_DPLL(id)); | |
| 389 | 396 | udelay(150); |
| 390 | 397 | |
| 391 | 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, · 1 unmodified line | ||
| 393 | 400 | * |
| 394 | 401 | * So write it again. |
| 395 | 402 | */ |
| 396 | − I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll); | |
| 397 | − POSTING_READ(PCH_DPLL(pll->id)); | |
| 403 | + I915_WRITE(PCH_DPLL(id), pll->state.hw_state.dpll); | |
| 404 | + POSTING_READ(PCH_DPLL(id)); | |
| 398 | 405 | udelay(200); |
| 399 | 406 | } |
| 400 | 407 | |
| 401 | 408 | static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, |
| 402 | 409 | struct intel_shared_dpll *pll) |
| 403 | 410 | { |
| 411 | + const enum intel_dpll_id id = pll->info->id; | |
| 404 | 412 | struct drm_device *dev = &dev_priv->drm; |
| 405 | 413 | struct intel_crtc *crtc; |
| 406 | 414 | |
| @@ -410,8 +418,8 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, · 3 unmodified lines | ||
| 410 | 418 | assert_pch_transcoder_disabled(dev_priv, crtc->pipe); |
| 411 | 419 | } |
| 412 | 420 | |
| 413 | − I915_WRITE(PCH_DPLL(pll->id), 0); | |
| 414 | − POSTING_READ(PCH_DPLL(pll->id)); | |
| 421 | + I915_WRITE(PCH_DPLL(id), 0); | |
| 422 | + POSTING_READ(PCH_DPLL(id)); | |
| 415 | 423 | udelay(200); |
| 416 | 424 | } |
| 417 | 425 | |
| @@ -429,7 +437,8 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 11 unmodified lines | ||
| 429 | 437 | pll = &dev_priv->shared_dplls[i]; |
| 430 | 438 | |
| 431 | 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 | 442 | } else { |
| 434 | 443 | pll = intel_find_shared_dpll(crtc, crtc_state, |
| 435 | 444 | DPLL_ID_PCH_PLL_A, |
| @@ -466,8 +475,10 @@ static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { · 30 unmodified lines | ||
| 466 | 475 | static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, |
| 467 | 476 | struct intel_shared_dpll *pll) |
| 468 | 477 | { |
| 469 | − I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll); | |
| 470 | − POSTING_READ(WRPLL_CTL(pll->id)); | |
| 478 | + const enum intel_dpll_id id = pll->info->id; | |
| 479 | + | |
| 480 | + I915_WRITE(WRPLL_CTL(id), pll->state.hw_state.wrpll); | |
| 481 | + POSTING_READ(WRPLL_CTL(id)); | |
| 471 | 482 | udelay(20); |
| 472 | 483 | } |
| 473 | 484 | |
| @@ -482,11 +493,12 @@ static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv, · 8 unmodified lines | ||
| 482 | 493 | static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, |
| 483 | 494 | struct intel_shared_dpll *pll) |
| 484 | 495 | { |
| 496 | + const enum intel_dpll_id id = pll->info->id; | |
| 485 | 497 | uint32_t val; |
| 486 | 498 | |
| 487 | − val = I915_READ(WRPLL_CTL(pll->id)); | |
| 488 | − I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); | |
| 489 | − POSTING_READ(WRPLL_CTL(pll->id)); | |
| 499 | + val = I915_READ(WRPLL_CTL(id)); | |
| 500 | + I915_WRITE(WRPLL_CTL(id), val & ~WRPLL_PLL_ENABLE); | |
| 501 | + POSTING_READ(WRPLL_CTL(id)); | |
| 490 | 502 | } |
| 491 | 503 | |
| 492 | 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, · 10 unmodified lines | ||
| 503 | 515 | struct intel_shared_dpll *pll, |
| 504 | 516 | struct intel_dpll_hw_state *hw_state) |
| 505 | 517 | { |
| 518 | + const enum intel_dpll_id id = pll->info->id; | |
| 506 | 519 | uint32_t val; |
| 507 | 520 | |
| 508 | 521 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
| 509 | 522 | return false; |
| 510 | 523 | |
| 511 | − val = I915_READ(WRPLL_CTL(pll->id)); | |
| 524 | + val = I915_READ(WRPLL_CTL(id)); | |
| 512 | 525 | hw_state->wrpll = val; |
| 513 | 526 | |
| 514 | 527 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); |
| @@ -914,13 +927,15 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = { · 399 unmodified lines | ||
| 914 | 927 | static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, |
| 915 | 928 | struct intel_shared_dpll *pll) |
| 916 | 929 | { |
| 930 | + const enum intel_dpll_id id = pll->info->id; | |
| 917 | 931 | uint32_t val; |
| 918 | 932 | |
| 919 | 933 | val = I915_READ(DPLL_CTRL1); |
| 920 | 934 | |
| 921 | − val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) | | |
| 922 | − DPLL_CTRL1_LINK_RATE_MASK(pll->id)); | |
| 923 | − val |= pll->state.hw_state.ctrl1 << (pll->id * 6); | |
| 935 | + val &= ~(DPLL_CTRL1_HDMI_MODE(id) | | |
| 936 | + DPLL_CTRL1_SSC(id) | | |
| 937 | + DPLL_CTRL1_LINK_RATE_MASK(id)); | |
| 938 | + val |= pll->state.hw_state.ctrl1 << (id * 6); | |
| 924 | 939 | |
| 925 | 940 | I915_WRITE(DPLL_CTRL1, val); |
| 926 | 941 | POSTING_READ(DPLL_CTRL1); |
| @@ -930,24 +945,25 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, · 3 unmodified lines | ||
| 930 | 945 | struct intel_shared_dpll *pll) |
| 931 | 946 | { |
| 932 | 947 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
| 948 | + const enum intel_dpll_id id = pll->info->id; | |
| 933 | 949 | |
| 934 | 950 | skl_ddi_pll_write_ctrl1(dev_priv, pll); |
| 935 | 951 | |
| 936 | − I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1); | |
| 937 | − I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2); | |
| 938 | − POSTING_READ(regs[pll->id].cfgcr1); | |
| 939 | − POSTING_READ(regs[pll->id].cfgcr2); | |
| 952 | + I915_WRITE(regs[id].cfgcr1, pll->state.hw_state.cfgcr1); | |
| 953 | + I915_WRITE(regs[id].cfgcr2, pll->state.hw_state.cfgcr2); | |
| 954 | + POSTING_READ(regs[id].cfgcr1); | |
| 955 | + POSTING_READ(regs[id].cfgcr2); | |
| 940 | 956 | |
| 941 | 957 | /* the enable bit is always bit 31 */ |
| 942 | − I915_WRITE(regs[pll->id].ctl, | |
| 943 | − I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); | |
| 958 | + I915_WRITE(regs[id].ctl, | |
| 959 | + I915_READ(regs[id].ctl) | LCPLL_PLL_ENABLE); | |
| 944 | 960 | |
| 945 | 961 | if (intel_wait_for_register(dev_priv, |
| 946 | 962 | DPLL_STATUS, |
| 947 | − DPLL_LOCK(pll->id), | |
| 948 | − DPLL_LOCK(pll->id), | |
| 963 | + DPLL_LOCK(id), | |
| 964 | + DPLL_LOCK(id), | |
| 949 | 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 | 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, · 6 unmodified lines | ||
| 960 | 976 | struct intel_shared_dpll *pll) |
| 961 | 977 | { |
| 962 | 978 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
| 979 | + const enum intel_dpll_id id = pll->info->id; | |
| 963 | 980 | |
| 964 | 981 | /* the enable bit is always bit 31 */ |
| 965 | − I915_WRITE(regs[pll->id].ctl, | |
| 966 | − I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); | |
| 967 | − POSTING_READ(regs[pll->id].ctl); | |
| 982 | + I915_WRITE(regs[id].ctl, | |
| 983 | + I915_READ(regs[id].ctl) & ~LCPLL_PLL_ENABLE); | |
| 984 | + POSTING_READ(regs[id].ctl); | |
| 968 | 985 | } |
| 969 | 986 | |
| 970 | 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, · 7 unmodified lines | ||
| 978 | 995 | { |
| 979 | 996 | uint32_t val; |
| 980 | 997 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
| 998 | + const enum intel_dpll_id id = pll->info->id; | |
| 981 | 999 | bool ret; |
| 982 | 1000 | |
| 983 | 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, · 1 unmodified line | ||
| 985 | 1003 | |
| 986 | 1004 | ret = false; |
| 987 | 1005 | |
| 988 | − val = I915_READ(regs[pll->id].ctl); | |
| 1006 | + val = I915_READ(regs[id].ctl); | |
| 989 | 1007 | if (!(val & LCPLL_PLL_ENABLE)) |
| 990 | 1008 | goto out; |
| 991 | 1009 | |
| 992 | 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 | 1013 | /* avoid reading back stale values if HDMI mode is not enabled */ |
| 996 | − if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) { | |
| 997 | − hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); | |
| 998 | − hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); | |
| 1014 | + if (val & DPLL_CTRL1_HDMI_MODE(id)) { | |
| 1015 | + hw_state->cfgcr1 = I915_READ(regs[id].cfgcr1); | |
| 1016 | + hw_state->cfgcr2 = I915_READ(regs[id].cfgcr2); | |
| 999 | 1017 | } |
| 1000 | 1018 | ret = true; |
| 1001 | 1019 | |
| @@ -1011,6 +1029,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, · 9 unmodified lines | ||
| 1011 | 1029 | { |
| 1012 | 1030 | uint32_t val; |
| 1013 | 1031 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
| 1032 | + const enum intel_dpll_id id = pll->info->id; | |
| 1014 | 1033 | bool ret; |
| 1015 | 1034 | |
| 1016 | 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, · 2 unmodified lines | ||
| 1019 | 1038 | ret = false; |
| 1020 | 1039 | |
| 1021 | 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 | 1042 | if (WARN_ON(!(val & LCPLL_PLL_ENABLE))) |
| 1024 | 1043 | goto out; |
| 1025 | 1044 | |
| 1026 | 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 | 1048 | ret = true; |
| 1030 | 1049 | |
| @@ -1424,7 +1443,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, · 393 unmodified lines | ||
| 1424 | 1443 | struct intel_shared_dpll *pll) |
| 1425 | 1444 | { |
| 1426 | 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 | 1447 | enum dpio_phy phy; |
| 1429 | 1448 | enum dpio_channel ch; |
| 1430 | 1449 | |
| @@ -1543,7 +1562,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, · 112 unmodified lines | ||
| 1543 | 1562 | static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, |
| 1544 | 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 | 1566 | uint32_t temp; |
| 1548 | 1567 | |
| 1549 | 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, · 16 unmodified lines | ||
| 1566 | 1585 | struct intel_shared_dpll *pll, |
| 1567 | 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 | 1589 | uint32_t val; |
| 1571 | 1590 | bool ret; |
| 1572 | 1591 | enum dpio_phy phy; |
| @@ -1824,7 +1843,7 @@ bxt_get_dpll(struct intel_crtc *crtc, · 251 unmodified lines | ||
| 1824 | 1843 | pll = intel_get_shared_dpll_by_id(dev_priv, i); |
| 1825 | 1844 | |
| 1826 | 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 | 1848 | intel_reference_shared_dpll(pll, crtc_state); |
| 1830 | 1849 | |
| @@ -1877,13 +1896,6 @@ static void intel_ddi_pll_init(struct drm_device *dev) · 46 unmodified lines | ||
| 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 | 1899 | struct intel_dpll_mgr { |
| 1888 | 1900 | const struct dpll_info *dpll_info; |
| 1889 | 1901 | |
| @@ -1896,9 +1908,9 @@ struct intel_dpll_mgr { · 6 unmodified lines | ||
| 1896 | 1908 | }; |
| 1897 | 1909 | |
| 1898 | 1910 | static const struct dpll_info pch_plls[] = { |
| 1899 | − { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 }, | |
| 1900 | − { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 }, | |
| 1901 | − { NULL, -1, NULL, 0 }, | |
| 1911 | + { "PCH DPLL A", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_A, 0 }, | |
| 1912 | + { "PCH DPLL B", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_B, 0 }, | |
| 1913 | + { }, | |
| 1902 | 1914 | }; |
| 1903 | 1915 | |
| 1904 | 1916 | static const struct intel_dpll_mgr pch_pll_mgr = { |
| @@ -1908,13 +1920,13 @@ static const struct intel_dpll_mgr pch_pll_mgr = { · 3 unmodified lines | ||
| 1908 | 1920 | }; |
| 1909 | 1921 | |
| 1910 | 1922 | static const struct dpll_info hsw_plls[] = { |
| 1911 | − { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 }, | |
| 1912 | − { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 }, | |
| 1913 | − { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 }, | |
| 1914 | − { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | |
| 1915 | − { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | |
| 1916 | − { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, | |
| 1917 | − { NULL, -1, NULL, }, | |
| 1923 | + { "WRPLL 1", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL1, 0 }, | |
| 1924 | + { "WRPLL 2", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL2, 0 }, | |
| 1925 | + { "SPLL", &hsw_ddi_spll_funcs, DPLL_ID_SPLL, 0 }, | |
| 1926 | + { "LCPLL 810", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_810, INTEL_DPLL_ALWAYS_ON }, | |
| 1927 | + { "LCPLL 1350", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_1350, INTEL_DPLL_ALWAYS_ON }, | |
| 1928 | + { "LCPLL 2700", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_2700, INTEL_DPLL_ALWAYS_ON }, | |
| 1929 | + { }, | |
| 1918 | 1930 | }; |
| 1919 | 1931 | |
| 1920 | 1932 | static const struct intel_dpll_mgr hsw_pll_mgr = { |
| @@ -1924,11 +1936,11 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { · 3 unmodified lines | ||
| 1924 | 1936 | }; |
| 1925 | 1937 | |
| 1926 | 1938 | static const struct dpll_info skl_plls[] = { |
| 1927 | − { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON }, | |
| 1928 | − { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, | |
| 1929 | − { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, | |
| 1930 | − { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, | |
| 1931 | − { NULL, -1, NULL, }, | |
| 1939 | + { "DPLL 0", &skl_ddi_dpll0_funcs, DPLL_ID_SKL_DPLL0, INTEL_DPLL_ALWAYS_ON }, | |
| 1940 | + { "DPLL 1", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, | |
| 1941 | + { "DPLL 2", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, | |
| 1942 | + { "DPLL 3", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL3, 0 }, | |
| 1943 | + { }, | |
| 1932 | 1944 | }; |
| 1933 | 1945 | |
| 1934 | 1946 | static const struct intel_dpll_mgr skl_pll_mgr = { |
| @@ -1938,10 +1950,10 @@ static const struct intel_dpll_mgr skl_pll_mgr = { · 3 unmodified lines | ||
| 1938 | 1950 | }; |
| 1939 | 1951 | |
| 1940 | 1952 | static const struct dpll_info bxt_plls[] = { |
| 1941 | − { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 }, | |
| 1942 | − { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 }, | |
| 1943 | − { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 }, | |
| 1944 | − { NULL, -1, NULL, }, | |
| 1953 | + { "PORT PLL A", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 }, | |
| 1954 | + { "PORT PLL B", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, | |
| 1955 | + { "PORT PLL C", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, | |
| 1956 | + { }, | |
| 1945 | 1957 | }; |
| 1946 | 1958 | |
| 1947 | 1959 | static const struct intel_dpll_mgr bxt_pll_mgr = { |
| @@ -1953,38 +1965,39 @@ static const struct intel_dpll_mgr bxt_pll_mgr = { · 5 unmodified lines | ||
| 1953 | 1965 | static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, |
| 1954 | 1966 | struct intel_shared_dpll *pll) |
| 1955 | 1967 | { |
| 1968 | + const enum intel_dpll_id id = pll->info->id; | |
| 1956 | 1969 | uint32_t val; |
| 1957 | 1970 | |
| 1958 | 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 | 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 | 1976 | /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */ |
| 1964 | 1977 | if (intel_wait_for_register(dev_priv, |
| 1965 | − CNL_DPLL_ENABLE(pll->id), | |
| 1978 | + CNL_DPLL_ENABLE(id), | |
| 1966 | 1979 | PLL_POWER_STATE, |
| 1967 | 1980 | PLL_POWER_STATE, |
| 1968 | 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 | 1985 | * 3. Configure DPLL_CFGCR0 to set SSC enable/disable, |
| 1973 | 1986 | * select DP mode, and set DP link rate. |
| 1974 | 1987 | */ |
| 1975 | 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 | 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 | 1994 | /* 3. Configure DPLL_CFGCR0 */ |
| 1982 | 1995 | /* Avoid touch CFGCR1 if HDMI mode is not enabled */ |
| 1983 | 1996 | if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) { |
| 1984 | 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 | 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, · 6 unmodified lines | ||
| 1997 | 2010 | */ |
| 1998 | 2011 | |
| 1999 | 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 | 2014 | val |= PLL_ENABLE; |
| 2002 | − I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | |
| 2015 | + I915_WRITE(CNL_DPLL_ENABLE(id), val); | |
| 2003 | 2016 | |
| 2004 | 2017 | /* 7. Wait for PLL lock status in DPLL_ENABLE. */ |
| 2005 | 2018 | if (intel_wait_for_register(dev_priv, |
| 2006 | − CNL_DPLL_ENABLE(pll->id), | |
| 2019 | + CNL_DPLL_ENABLE(id), | |
| 2007 | 2020 | PLL_LOCK, |
| 2008 | 2021 | PLL_LOCK, |
| 2009 | 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 | 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, · 13 unmodified lines | ||
| 2027 | 2040 | static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, |
| 2028 | 2041 | struct intel_shared_dpll *pll) |
| 2029 | 2042 | { |
| 2043 | + const enum intel_dpll_id id = pll->info->id; | |
| 2030 | 2044 | uint32_t val; |
| 2031 | 2045 | |
| 2032 | 2046 | /* |
| @@ -2044,17 +2058,17 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, · 11 unmodified lines | ||
| 2044 | 2058 | */ |
| 2045 | 2059 | |
| 2046 | 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 | 2062 | val &= ~PLL_ENABLE; |
| 2049 | − I915_WRITE(CNL_DPLL_ENABLE(pll->id), val); | |
| 2063 | + I915_WRITE(CNL_DPLL_ENABLE(id), val); | |
| 2050 | 2064 | |
| 2051 | 2065 | /* 4. Wait for PLL not locked status in DPLL_ENABLE. */ |
| 2052 | 2066 | if (intel_wait_for_register(dev_priv, |
| 2053 | − CNL_DPLL_ENABLE(pll->id), | |
| 2067 | + CNL_DPLL_ENABLE(id), | |
| 2054 | 2068 | PLL_LOCK, |
| 2055 | 2069 | 0, |
| 2056 | 2070 | 5)) |
| 2057 | − DRM_ERROR("PLL %d locked\n", pll->id); | |
| 2071 | + DRM_ERROR("PLL %d locked\n", id); | |
| 2058 | 2072 | |
| 2059 | 2073 | /* |
| 2060 | 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, · 5 unmodified lines | ||
| 2066 | 2080 | */ |
| 2067 | 2081 | |
| 2068 | 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 | 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 | 2087 | /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */ |
| 2074 | 2088 | if (intel_wait_for_register(dev_priv, |
| 2075 | − CNL_DPLL_ENABLE(pll->id), | |
| 2089 | + CNL_DPLL_ENABLE(id), | |
| 2076 | 2090 | PLL_POWER_STATE, |
| 2077 | 2091 | 0, |
| 2078 | 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 | 2096 | static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, |
| 2083 | 2097 | struct intel_shared_dpll *pll, |
| 2084 | 2098 | struct intel_dpll_hw_state *hw_state) |
| 2085 | 2099 | { |
| 2100 | + const enum intel_dpll_id id = pll->info->id; | |
| 2086 | 2101 | uint32_t val; |
| 2087 | 2102 | bool ret; |
| 2088 | 2103 | |
| @@ -2091,16 +2106,16 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 2091 | 2106 | |
| 2092 | 2107 | ret = false; |
| 2093 | 2108 | |
| 2094 | − val = I915_READ(CNL_DPLL_ENABLE(pll->id)); | |
| 2109 | + val = I915_READ(CNL_DPLL_ENABLE(id)); | |
| 2095 | 2110 | if (!(val & PLL_ENABLE)) |
| 2096 | 2111 | goto out; |
| 2097 | 2112 | |
| 2098 | − val = I915_READ(CNL_DPLL_CFGCR0(pll->id)); | |
| 2113 | + val = I915_READ(CNL_DPLL_CFGCR0(id)); | |
| 2099 | 2114 | hw_state->cfgcr0 = val; |
| 2100 | 2115 | |
| 2101 | 2116 | /* avoid reading back stale values if HDMI mode is not enabled */ |
| 2102 | 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 | 2120 | ret = true; |
| 2106 | 2121 | |
| @@ -2372,10 +2387,10 @@ static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = { · 265 unmodified lines | ||
| 2372 | 2387 | }; |
| 2373 | 2388 | |
| 2374 | 2389 | static const struct dpll_info cnl_plls[] = { |
| 2375 | − { "DPLL 0", DPLL_ID_SKL_DPLL0, &cnl_ddi_pll_funcs, 0 }, | |
| 2376 | − { "DPLL 1", DPLL_ID_SKL_DPLL1, &cnl_ddi_pll_funcs, 0 }, | |
| 2377 | − { "DPLL 2", DPLL_ID_SKL_DPLL2, &cnl_ddi_pll_funcs, 0 }, | |
| 2378 | − { NULL, -1, NULL, }, | |
| 2390 | + { "DPLL 0", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 }, | |
| 2391 | + { "DPLL 1", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, | |
| 2392 | + { "DPLL 2", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, | |
| 2393 | + { }, | |
| 2379 | 2394 | }; |
| 2380 | 2395 | |
| 2381 | 2396 | static const struct intel_dpll_mgr cnl_pll_mgr = { |
| @@ -2415,13 +2430,9 @@ void intel_shared_dpll_init(struct drm_device *dev) · 33 unmodified lines | ||
| 2415 | 2430 | |
| 2416 | 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 | 2434 | WARN_ON(i != dpll_info[i].id); |
| 2420 | − | |
| 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; | |
| 2435 | + dev_priv->shared_dplls[i].info = &dpll_info[i]; | |
| 2425 | 2436 | } |
| 2426 | 2437 | |
| 2427 | 2438 | dev_priv->dpll_mgr = dpll_mgr; |
| @@ -2481,7 +2492,7 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll, · 53 unmodified lines | ||
| 2481 | 2492 | struct intel_shared_dpll_state *shared_dpll_state; |
| 2482 | 2493 | |
| 2483 | 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 | /** |
| @@ -205,6 +205,37 @@ struct intel_shared_dpll_funcs { · 204 unmodified lines | ||
| 205 | 205 | struct intel_dpll_hw_state *hw_state); |
| 206 | 206 | }; |
| 207 | 207 | |
| 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 | + | |
| 208 | 239 | /** |
| 209 | 240 | * struct intel_shared_dpll - display PLL with tracked state and users |
| 210 | 241 | */ |
| @@ -228,30 +259,9 @@ struct intel_shared_dpll { · 17 unmodified lines | ||
| 228 | 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; | |
| 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; | |
| 264 | + const struct dpll_info *info; | |
| 255 | 265 | }; |
| 256 | 266 | |
| 257 | 267 | #define SKL_DPLL0 0 |
| @@ -482,7 +482,7 @@ struct intel_atomic_state { · 481 unmodified lines | ||
| 482 | 482 | bool skip_intermediate_wm; |
| 483 | 483 | |
| 484 | 484 | /* Gen9+ only */ |
| 485 | − struct skl_wm_values wm_results; | |
| 485 | + struct skl_ddb_values wm_results; | |
| 486 | 486 | |
| 487 | 487 | struct i915_sw_fence commit_ready; |
| 488 | 488 | |
| @@ -548,6 +548,12 @@ struct intel_initial_plane_config { · 59 unmodified lines | ||
| 548 | 548 | #define SKL_MAX_DST_W 4096 |
| 549 | 549 | #define SKL_MIN_DST_H 8 |
| 550 | 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 | 558 | struct intel_scaler { |
| 553 | 559 | int in_use; |
| @@ -598,7 +604,9 @@ struct intel_pipe_wm { · 44 unmodified lines | ||
| 598 | 604 | |
| 599 | 605 | struct skl_plane_wm { |
| 600 | 606 | struct skl_wm_level wm[8]; |
| 607 | + struct skl_wm_level uv_wm[8]; | |
| 601 | 608 | struct skl_wm_level trans_wm; |
| 609 | + bool is_planar; | |
| 602 | 610 | }; |
| 603 | 611 | |
| 604 | 612 | struct skl_pipe_wm { |
| @@ -1325,6 +1333,7 @@ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); · 720 unmodified lines | ||
| 1325 | 1333 | void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); |
| 1326 | 1334 | void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); |
| 1327 | 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 | 1337 | void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); |
| 1329 | 1338 | void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv); |
| 1330 | 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); · 257 unmodified lines | ||
| 1588 | 1597 | enum intel_display_power_domain intel_port_to_power_domain(enum port port); |
| 1589 | 1598 | void intel_mode_from_pipe_config(struct drm_display_mode *mode, |
| 1590 | 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 | 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 | 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, · 10 unmodified lines | ||
| 1607 | 1619 | int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, |
| 1608 | 1620 | struct intel_plane_state *plane_state); |
| 1609 | 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 | 1624 | /* intel_csr.c */ |
| 1612 | 1625 | void intel_csr_ucode_init(struct drm_i915_private *); |
| @@ -1773,6 +1786,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, · 160 unmodified lines | ||
| 1773 | 1786 | unsigned int frontbuffer_bits, enum fb_op_origin origin); |
| 1774 | 1787 | void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); |
| 1775 | 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 | 1791 | /* intel_hdmi.c */ |
| 1778 | 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); · 4 unmodified lines | ||
| 1783 | 1797 | bool intel_hdmi_compute_config(struct intel_encoder *encoder, |
| 1784 | 1798 | struct intel_crtc_state *pipe_config, |
| 1785 | 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 | 1801 | struct drm_connector *connector, |
| 1788 | 1802 | bool high_tmds_clock_ratio, |
| 1789 | 1803 | bool scrambling); |
| @@ -1877,7 +1891,8 @@ void intel_psr_enable(struct intel_dp *intel_dp, · 87 unmodified lines | ||
| 1877 | 1891 | void intel_psr_disable(struct intel_dp *intel_dp, |
| 1878 | 1892 | const struct intel_crtc_state *old_crtc_state); |
| 1879 | 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 | 1896 | void intel_psr_flush(struct drm_i915_private *dev_priv, |
| 1882 | 1897 | unsigned frontbuffer_bits, |
| 1883 | 1898 | enum fb_op_origin origin); |
| @@ -2046,6 +2061,7 @@ void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc); · 162 unmodified lines | ||
| 2046 | 2061 | bool skl_plane_get_hw_state(struct intel_plane *plane); |
| 2047 | 2062 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, |
| 2048 | 2063 | enum pipe pipe, enum plane_id plane_id); |
| 2064 | +bool intel_format_is_yuv(uint32_t format); | |
| 2049 | 2065 | |
| 2050 | 2066 | /* intel_tv.c */ |
| 2051 | 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, · 30 unmodified lines | ||
| 2082 | 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 | 2101 | int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, |
| 2111 | 2102 | struct intel_crtc *intel_crtc, |
| 2112 | 2103 | struct intel_crtc_state *crtc_state); |
| @@ -2138,8 +2129,17 @@ int intel_pipe_crc_create(struct drm_minor *minor); · 25 unmodified lines | ||
| 2138 | 2129 | #ifdef CONFIG_DEBUG_FS |
| 2139 | 2130 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, |
| 2140 | 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 | 2134 | #else |
| 2142 | 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 | 2143 | #endif |
| 2144 | 2144 | extern const struct file_operations i915_display_crc_ctl_fops; |
| 2145 | 2145 | #endif /* __INTEL_DRV_H__ */ |
| @@ -81,13 +81,17 @@ static const struct engine_class_info intel_engine_classes[] = { · 80 unmodified lines | ||
| 81 | 81 | }, |
| 82 | 82 | }; |
| 83 | 83 | |
| 84 | +#define MAX_MMIO_BASES 3 | |
| 84 | 85 | struct engine_info { |
| 85 | 86 | unsigned int hw_id; |
| 86 | 87 | unsigned int uabi_id; |
| 87 | 88 | u8 class; |
| 88 | 89 | u8 instance; |
| 89 | − u32 mmio_base; | |
| 90 | − unsigned irq_shift; | |
| 90 | + /* mmio bases table *must* be sorted in reverse gen order */ | |
| 91 | + struct engine_mmio_base { | |
| 92 | + u32 gen : 8; | |
| 93 | + u32 base : 24; | |
| 94 | + } mmio_bases[MAX_MMIO_BASES]; | |
| 91 | 95 | }; |
| 92 | 96 | |
| 93 | 97 | static const struct engine_info intel_engines[] = { |
| @@ -96,64 +100,76 @@ static const struct engine_info intel_engines[] = { · 2 unmodified lines | ||
| 96 | 100 | .uabi_id = I915_EXEC_RENDER, |
| 97 | 101 | .class = RENDER_CLASS, |
| 98 | 102 | .instance = 0, |
| 99 | − .mmio_base = RENDER_RING_BASE, | |
| 100 | − .irq_shift = GEN8_RCS_IRQ_SHIFT, | |
| 103 | + .mmio_bases = { | |
| 104 | + { .gen = 1, .base = RENDER_RING_BASE } | |
| 105 | + }, | |
| 101 | 106 | }, |
| 102 | 107 | [BCS] = { |
| 103 | 108 | .hw_id = BCS_HW, |
| 104 | 109 | .uabi_id = I915_EXEC_BLT, |
| 105 | 110 | .class = COPY_ENGINE_CLASS, |
| 106 | 111 | .instance = 0, |
| 107 | − .mmio_base = BLT_RING_BASE, | |
| 108 | − .irq_shift = GEN8_BCS_IRQ_SHIFT, | |
| 112 | + .mmio_bases = { | |
| 113 | + { .gen = 6, .base = BLT_RING_BASE } | |
| 114 | + }, | |
| 109 | 115 | }, |
| 110 | 116 | [VCS] = { |
| 111 | 117 | .hw_id = VCS_HW, |
| 112 | 118 | .uabi_id = I915_EXEC_BSD, |
| 113 | 119 | .class = VIDEO_DECODE_CLASS, |
| 114 | 120 | .instance = 0, |
| 115 | − .mmio_base = GEN6_BSD_RING_BASE, | |
| 116 | − .irq_shift = GEN8_VCS1_IRQ_SHIFT, | |
| 121 | + .mmio_bases = { | |
| 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 | 127 | [VCS2] = { |
| 119 | 128 | .hw_id = VCS2_HW, |
| 120 | 129 | .uabi_id = I915_EXEC_BSD, |
| 121 | 130 | .class = VIDEO_DECODE_CLASS, |
| 122 | 131 | .instance = 1, |
| 123 | − .mmio_base = GEN8_BSD2_RING_BASE, | |
| 124 | − .irq_shift = GEN8_VCS2_IRQ_SHIFT, | |
| 132 | + .mmio_bases = { | |
| 133 | + { .gen = 11, .base = GEN11_BSD2_RING_BASE }, | |
| 134 | + { .gen = 8, .base = GEN8_BSD2_RING_BASE } | |
| 135 | + }, | |
| 125 | 136 | }, |
| 126 | 137 | [VCS3] = { |
| 127 | 138 | .hw_id = VCS3_HW, |
| 128 | 139 | .uabi_id = I915_EXEC_BSD, |
| 129 | 140 | .class = VIDEO_DECODE_CLASS, |
| 130 | 141 | .instance = 2, |
| 131 | − .mmio_base = GEN11_BSD3_RING_BASE, | |
| 132 | − .irq_shift = 0, /* not used */ | |
| 142 | + .mmio_bases = { | |
| 143 | + { .gen = 11, .base = GEN11_BSD3_RING_BASE } | |
| 144 | + }, | |
| 133 | 145 | }, |
| 134 | 146 | [VCS4] = { |
| 135 | 147 | .hw_id = VCS4_HW, |
| 136 | 148 | .uabi_id = I915_EXEC_BSD, |
| 137 | 149 | .class = VIDEO_DECODE_CLASS, |
| 138 | 150 | .instance = 3, |
| 139 | − .mmio_base = GEN11_BSD4_RING_BASE, | |
| 140 | − .irq_shift = 0, /* not used */ | |
| 151 | + .mmio_bases = { | |
| 152 | + { .gen = 11, .base = GEN11_BSD4_RING_BASE } | |
| 153 | + }, | |
| 141 | 154 | }, |
| 142 | 155 | [VECS] = { |
| 143 | 156 | .hw_id = VECS_HW, |
| 144 | 157 | .uabi_id = I915_EXEC_VEBOX, |
| 145 | 158 | .class = VIDEO_ENHANCEMENT_CLASS, |
| 146 | 159 | .instance = 0, |
| 147 | − .mmio_base = VEBOX_RING_BASE, | |
| 148 | − .irq_shift = GEN8_VECS_IRQ_SHIFT, | |
| 160 | + .mmio_bases = { | |
| 161 | + { .gen = 11, .base = GEN11_VEBOX_RING_BASE }, | |
| 162 | + { .gen = 7, .base = VEBOX_RING_BASE } | |
| 163 | + }, | |
| 149 | 164 | }, |
| 150 | 165 | [VECS2] = { |
| 151 | 166 | .hw_id = VECS2_HW, |
| 152 | 167 | .uabi_id = I915_EXEC_VEBOX, |
| 153 | 168 | .class = VIDEO_ENHANCEMENT_CLASS, |
| 154 | 169 | .instance = 1, |
| 155 | − .mmio_base = GEN11_VEBOX2_RING_BASE, | |
| 156 | − .irq_shift = 0, /* not used */ | |
| 170 | + .mmio_bases = { | |
| 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) · 63 unmodified lines | ||
| 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 | 264 | static int |
| 227 | 265 | intel_engine_setup(struct drm_i915_private *dev_priv, |
| 228 | 266 | enum intel_engine_id id) |
| 229 | 267 | { |
| 230 | 268 | const struct engine_info *info = &intel_engines[id]; |
| 231 | − const struct engine_class_info *class_info; | |
| 232 | 269 | struct intel_engine_cs *engine; |
| 233 | 270 | |
| 234 | 271 | GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes)); |
| 235 | − class_info = &intel_engine_classes[info->class]; | |
| 236 | 272 | |
| 237 | 273 | BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH)); |
| 238 | 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, · 14 unmodified lines | ||
| 253 | 289 | |
| 254 | 290 | engine->id = id; |
| 255 | 291 | engine->i915 = dev_priv; |
| 256 | − WARN_ON(snprintf(engine->name, sizeof(engine->name), "%s%u", | |
| 257 | − class_info->name, info->instance) >= | |
| 258 | − sizeof(engine->name)); | |
| 292 | + __sprint_engine_name(engine->name, info); | |
| 259 | 293 | engine->hw_id = engine->guc_id = info->hw_id; |
| 260 | − if (INTEL_GEN(dev_priv) >= 11) { | |
| 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; | |
| 294 | + engine->mmio_base = __engine_mmio_base(dev_priv, info->mmio_bases); | |
| 280 | 295 | engine->class = info->class; |
| 281 | 296 | engine->instance = info->instance; |
| 282 | 297 | |
| 283 | 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 | 301 | engine->context_size = __intel_engine_context_size(dev_priv, |
| 287 | 302 | engine->class); |
| @@ -441,6 +456,11 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) · 153 unmodified lines | ||
| 441 | 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 | 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) · 8 unmodified lines | ||
| 455 | 475 | if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) |
| 456 | 476 | return true; |
| 457 | 477 | |
| 478 | + if (IS_CANNONLAKE(i915)) | |
| 479 | + return true; | |
| 480 | + | |
| 458 | 481 | return false; |
| 459 | 482 | } |
| 460 | 483 | |
| @@ -485,11 +508,9 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine) · 24 unmodified lines | ||
| 485 | 508 | void intel_engine_setup_common(struct intel_engine_cs *engine) |
| 486 | 509 | { |
| 487 | 510 | intel_engine_init_execlist(engine); |
| 488 | − | |
| 489 | 511 | intel_engine_init_timeline(engine); |
| 490 | 512 | intel_engine_init_hangcheck(engine); |
| 491 | − i915_gem_batch_pool_init(engine, &engine->batch_pool); | |
| 492 | − | |
| 513 | + intel_engine_init_batch_pool(engine); | |
| 493 | 514 | intel_engine_init_cmd_parser(engine); |
| 494 | 515 | } |
| 495 | 516 | |
| @@ -782,10 +803,24 @@ static inline uint32_t · 286 unmodified lines | ||
| 782 | 803 | read_subslice_reg(struct drm_i915_private *dev_priv, int slice, |
| 783 | 804 | int subslice, i915_reg_t reg) |
| 784 | 805 | { |
| 806 | + uint32_t mcr_slice_subslice_mask; | |
| 807 | + uint32_t mcr_slice_subslice_select; | |
| 785 | 808 | uint32_t mcr; |
| 786 | 809 | uint32_t ret; |
| 787 | 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 | 824 | fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, |
| 790 | 825 | FW_REG_READ); |
| 791 | 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, · 8 unmodified lines | ||
| 800 | 835 | * The HW expects the slice and sublice selectors to be reset to 0 |
| 801 | 836 | * after reading out the registers. |
| 802 | 837 | */ |
| 803 | − WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); | |
| 804 | − mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); | |
| 805 | − mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); | |
| 838 | + WARN_ON_ONCE(mcr & mcr_slice_subslice_mask); | |
| 839 | + mcr &= ~mcr_slice_subslice_mask; | |
| 840 | + mcr |= mcr_slice_subslice_select; | |
| 806 | 841 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); |
| 807 | 842 | |
| 808 | 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 | 846 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); |
| 812 | 847 | |
| 813 | 848 | intel_uncore_forcewake_put__locked(dev_priv, fw_domains); |
| @@ -871,640 +906,6 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine, · 57 unmodified lines | ||
| 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 | 909 | static bool ring_is_idle(struct intel_engine_cs *engine) |
| 1509 | 910 | { |
| 1510 | 911 | struct drm_i915_private *dev_priv = engine->i915; |
| @@ -1655,6 +1056,9 @@ void intel_engines_park(struct drm_i915_private *i915) · 144 unmodified lines | ||
| 1655 | 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 | 1062 | if (engine->park) |
| 1659 | 1063 | engine->park(engine); |
| 1660 | 1064 | |
| @@ -1713,13 +1117,15 @@ static void print_request(struct drm_printer *m, · 52 unmodified lines | ||
| 1713 | 1117 | struct i915_request *rq, |
| 1714 | 1118 | const char *prefix) |
| 1715 | 1119 | { |
| 1120 | + const char *name = rq->fence.ops->get_timeline_name(&rq->fence); | |
| 1121 | + | |
| 1716 | 1122 | drm_printf(m, "%s%x%s [%llx:%x] prio=%d @ %dms: %s\n", prefix, |
| 1717 | 1123 | rq->global_seqno, |
| 1718 | 1124 | i915_request_completed(rq) ? "!" : "", |
| 1719 | 1125 | rq->fence.context, rq->fence.seqno, |
| 1720 | 1126 | rq->priotree.priority, |
| 1721 | 1127 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), |
| 1722 | − rq->timeline->common->name); | |
| 1128 | + name); | |
| 1723 | 1129 | } |
| 1724 | 1130 | |
| 1725 | 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, · 99 unmodified lines | ||
| 1825 | 1231 | ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); |
| 1826 | 1232 | read = GEN8_CSB_READ_PTR(ptr); |
| 1827 | 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 | 1235 | read, execlists->csb_head, |
| 1830 | 1236 | write, |
| 1831 | 1237 | intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), |
| 1832 | 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 | 1243 | if (read >= GEN8_CSB_ENTRIES) |
| 1835 | 1244 | read = 0; |
| 1836 | 1245 | if (write >= GEN8_CSB_ENTRIES) |
| @@ -1929,12 +1338,16 @@ void intel_engine_dump(struct intel_engine_cs *engine, · 92 unmodified lines | ||
| 1929 | 1338 | rq->head, rq->postfix, rq->tail, |
| 1930 | 1339 | rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, |
| 1931 | 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 | 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 | 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 | 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 | 1353 | rcu_read_unlock(); |
| @@ -2109,4 +1522,5 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) · 168 unmodified lines | ||
| 2109 | 1522 | |
| 2110 | 1523 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
| 2111 | 1524 | #include "selftests/mock_engine.c" |
| 1525 | +#include "selftests/intel_engine_cs.c" | |
| 2112 | 1526 | #endif |
| @@ -1272,6 +1272,34 @@ out: · 1271 unmodified lines | ||
| 1272 | 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 | 1304 | * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun |
| 1277 | 1305 | * @dev_priv: i915 device instance |
| @@ -221,6 +221,9 @@ static int intelfb_create(struct drm_fb_helper *helper, · 220 unmodified lines | ||
| 221 | 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 | 227 | info = drm_fb_helper_alloc_fbi(helper); |
| 225 | 228 | if (IS_ERR(info)) { |
| 226 | 229 | DRM_ERROR("Failed to allocate fb_info\n"); |
| @@ -230,8 +233,6 @@ static int intelfb_create(struct drm_fb_helper *helper, · 3 unmodified lines | ||
| 230 | 233 | |
| 231 | 234 | info->par = helper; |
| 232 | 235 | |
| 233 | − fb = &ifbdev->fb->base; | |
| 234 | − | |
| 235 | 236 | ifbdev->helper.fb = fb; |
| 236 | 237 | |
| 237 | 238 | strcpy(info->fix.id, "inteldrmfb"); |
| @@ -80,7 +80,7 @@ void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, · 79 unmodified lines | ||
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | might_sleep(); |
| 83 | − intel_psr_invalidate(dev_priv, frontbuffer_bits); | |
| 83 | + intel_psr_invalidate(dev_priv, frontbuffer_bits, origin); | |
| 84 | 84 | intel_edp_drrs_invalidate(dev_priv, frontbuffer_bits); |
| 85 | 85 | intel_fbc_invalidate(dev_priv, frontbuffer_bits, origin); |
| 86 | 86 | } |
| @@ -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_ */ | |
| @@ -64,10 +64,12 @@ void intel_guc_init_early(struct intel_guc *guc) · 63 unmodified lines | ||
| 64 | 64 | { |
| 65 | 65 | intel_guc_fw_init_early(guc); |
| 66 | 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 | 69 | mutex_init(&guc->send_mutex); |
| 70 | + spin_lock_init(&guc->irq_lock); | |
| 70 | 71 | guc->send = intel_guc_send_nop; |
| 72 | + guc->handler = intel_guc_to_host_event_handler_nop; | |
| 71 | 73 | guc->notify = gen8_guc_raise_irq; |
| 72 | 74 | } |
| 73 | 75 | |
| @@ -86,9 +88,10 @@ int intel_guc_init_wq(struct intel_guc *guc) · 12 unmodified lines | ||
| 86 | 88 | * or scheduled later on resume. This way the handling of work |
| 87 | 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", | |
| 90 | − WQ_HIGHPRI | WQ_FREEZABLE); | |
| 91 | − if (!guc->log.runtime.flush_wq) { | |
| 91 | + guc->log.relay.flush_wq = | |
| 92 | + alloc_ordered_workqueue("i915-guc_log", | |
| 93 | + WQ_HIGHPRI | WQ_FREEZABLE); | |
| 94 | + if (!guc->log.relay.flush_wq) { | |
| 92 | 95 | DRM_ERROR("Couldn't allocate workqueue for GuC log\n"); |
| 93 | 96 | return -ENOMEM; |
| 94 | 97 | } |
| @@ -111,7 +114,7 @@ int intel_guc_init_wq(struct intel_guc *guc) · 16 unmodified lines | ||
| 111 | 114 | guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", |
| 112 | 115 | WQ_HIGHPRI); |
| 113 | 116 | if (!guc->preempt_wq) { |
| 114 | − destroy_workqueue(guc->log.runtime.flush_wq); | |
| 117 | + destroy_workqueue(guc->log.relay.flush_wq); | |
| 115 | 118 | DRM_ERROR("Couldn't allocate workqueue for GuC " |
| 116 | 119 | "preemption\n"); |
| 117 | 120 | return -ENOMEM; |
| @@ -129,7 +132,7 @@ void intel_guc_fini_wq(struct intel_guc *guc) · 11 unmodified lines | ||
| 129 | 132 | USES_GUC_SUBMISSION(dev_priv)) |
| 130 | 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 | 138 | static int guc_shared_data_create(struct intel_guc *guc) |
| @@ -169,7 +172,7 @@ int intel_guc_init(struct intel_guc *guc) · 33 unmodified lines | ||
| 169 | 172 | return ret; |
| 170 | 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 | 176 | if (ret) |
| 174 | 177 | goto err_shared; |
| 175 | 178 | |
| @@ -184,7 +187,7 @@ int intel_guc_init(struct intel_guc *guc) · 8 unmodified lines | ||
| 184 | 187 | return 0; |
| 185 | 188 | |
| 186 | 189 | err_log: |
| 187 | − intel_guc_log_destroy(guc); | |
| 190 | + intel_guc_log_destroy(&guc->log); | |
| 188 | 191 | err_shared: |
| 189 | 192 | guc_shared_data_destroy(guc); |
| 190 | 193 | return ret; |
| @@ -196,7 +199,7 @@ void intel_guc_fini(struct intel_guc *guc) · 5 unmodified lines | ||
| 196 | 199 | |
| 197 | 200 | i915_ggtt_disable_guc(dev_priv); |
| 198 | 201 | intel_guc_ads_destroy(guc); |
| 199 | − intel_guc_log_destroy(guc); | |
| 202 | + intel_guc_log_destroy(&guc->log); | |
| 200 | 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) · 17 unmodified lines | ||
| 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) { | |
| 226 | − u32 verbosity = i915_modparams.guc_log_level - 1; | |
| 228 | + u32 level = i915_modparams.guc_log_level; | |
| 229 | + u32 flags = 0; | |
| 227 | 230 | |
| 228 | − GEM_BUG_ON(verbosity > GUC_LOG_VERBOSITY_MAX); | |
| 229 | − return verbosity << GUC_LOG_VERBOSITY_SHIFT; | |
| 230 | − } | |
| 231 | + GEM_BUG_ON(level < 0); | |
| 232 | + | |
| 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); | |
| 233 | − return GUC_LOG_DISABLED; | |
| 242 | + return flags; | |
| 234 | 243 | } |
| 235 | 244 | |
| 236 | 245 | /* |
| @@ -265,12 +274,13 @@ void intel_guc_init_params(struct intel_guc *guc) · 28 unmodified lines | ||
| 265 | 274 | |
| 266 | 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 | 279 | /* If GuC submission is enabled, set up additional parameters here */ |
| 271 | 280 | if (USES_GUC_SUBMISSION(dev_priv)) { |
| 272 | − u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; | |
| 273 | − u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); | |
| 281 | + u32 ads = intel_guc_ggtt_offset(guc, | |
| 282 | + guc->ads_vma) >> PAGE_SHIFT; | |
| 283 | + u32 pgs = intel_guc_ggtt_offset(guc, guc->stage_desc_pool); | |
| 274 | 284 | u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; |
| 275 | 285 | |
| 276 | 286 | params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; |
| @@ -301,16 +311,23 @@ void intel_guc_init_params(struct intel_guc *guc) · 24 unmodified lines | ||
| 301 | 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 | 317 | WARN(1, "Unexpected send: action=%#x\n", *action); |
| 307 | 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 | 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 | 332 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 316 | 333 | u32 status; |
| @@ -320,6 +337,9 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) · 3 unmodified lines | ||
| 320 | 337 | GEM_BUG_ON(!len); |
| 321 | 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 | 343 | /* If CT is available, we expect to use MMIO only during init/fini */ |
| 324 | 344 | GEM_BUG_ON(HAS_GUC_CT(dev_priv) && |
| 325 | 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) · 15 unmodified lines | ||
| 341 | 361 | */ |
| 342 | 362 | ret = __intel_wait_for_register_fw(dev_priv, |
| 343 | 363 | guc_send_reg(guc, 0), |
| 344 | − INTEL_GUC_RECV_MASK, | |
| 345 | − INTEL_GUC_RECV_MASK, | |
| 364 | + INTEL_GUC_MSG_TYPE_MASK, | |
| 365 | + INTEL_GUC_MSG_TYPE_RESPONSE << | |
| 366 | + INTEL_GUC_MSG_TYPE_SHIFT, | |
| 346 | 367 | 10, 10, &status); |
| 347 | − if (status != INTEL_GUC_STATUS_SUCCESS) { | |
| 348 | − /* | |
| 349 | − * Either the GuC explicitly returned an error (which | |
| 350 | − * we convert to -EIO here) or no response at all was | |
| 351 | − * received within the timeout limit (-ETIMEDOUT) | |
| 352 | − */ | |
| 353 | − if (ret != -ETIMEDOUT) | |
| 354 | − ret = -EIO; | |
| 355 | − | |
| 356 | − DRM_WARN("INTEL_GUC_SEND: Action 0x%X failed;" | |
| 357 | − " ret=%d status=0x%08X response=0x%08X\n", | |
| 358 | − action[0], ret, status, I915_READ(SOFT_SCRATCH(15))); | |
| 368 | + /* If GuC explicitly returned an error, convert it to -EIO */ | |
| 369 | + if (!ret && !INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(status)) | |
| 370 | + ret = -EIO; | |
| 371 | + | |
| 372 | + if (ret) { | |
| 373 | + DRM_DEBUG_DRIVER("INTEL_GUC_SEND: Action 0x%X failed;" | |
| 374 | + " ret=%d status=0x%08X response=0x%08X\n", | |
| 375 | + action[0], ret, status, | |
| 376 | + I915_READ(SOFT_SCRATCH(15))); | |
| 377 | + goto out; | |
| 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 | 391 | intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains); |
| 362 | 392 | mutex_unlock(&guc->send_mutex); |
| 363 | 393 | |
| 364 | 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 | 432 | int intel_guc_sample_forcewake(struct intel_guc *guc) |
| 368 | 433 | { |
| 369 | 434 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| @@ -410,7 +475,7 @@ int intel_guc_suspend(struct intel_guc *guc) · 40 unmodified lines | ||
| 410 | 475 | u32 data[] = { |
| 411 | 476 | INTEL_GUC_ACTION_ENTER_S_STATE, |
| 412 | 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 | 481 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
| @@ -434,7 +499,7 @@ int intel_guc_reset_engine(struct intel_guc *guc, · 17 unmodified lines | ||
| 434 | 499 | data[3] = 0; |
| 435 | 500 | data[4] = 0; |
| 436 | 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 | 504 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
| 440 | 505 | } |
| @@ -448,12 +513,65 @@ int intel_guc_resume(struct intel_guc *guc) · 7 unmodified lines | ||
| 448 | 513 | u32 data[] = { |
| 449 | 514 | INTEL_GUC_ACTION_EXIT_S_STATE, |
| 450 | 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 | 519 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
| 455 | 520 | } |
| 456 | 521 | |
| 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 | + | |
| 457 | 575 | /** |
| 458 | 576 | * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage |
| 459 | 577 | * @guc: the guc |
| @@ -462,7 +580,7 @@ int intel_guc_resume(struct intel_guc *guc) · 2 unmodified lines | ||
| 462 | 580 | * This is a wrapper to create an object for use with the GuC. In order to |
| 463 | 581 | * use it inside the GuC, an object needs to be pinned lifetime, so we allocate |
| 464 | 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 | 584 | * range is reserved inside GuC. |
| 467 | 585 | * |
| 468 | 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) · 14 unmodified lines | ||
| 483 | 601 | goto err; |
| 484 | 602 | |
| 485 | 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 | 605 | if (ret) { |
| 488 | 606 | vma = ERR_PTR(ret); |
| 489 | 607 | goto err; |
| @@ -495,14 +613,3 @@ err: · 5 unmodified lines | ||
| 495 | 613 | i915_gem_object_put(obj); |
| 496 | 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 | −} | |
| @@ -49,11 +49,16 @@ struct intel_guc { · 48 unmodified lines | ||
| 49 | 49 | struct intel_guc_log log; |
| 50 | 50 | struct intel_guc_ct ct; |
| 51 | 51 | |
| 52 | + /* Offset where Non-WOPCM memory starts. */ | |
| 53 | + u32 ggtt_pin_bias; | |
| 54 | + | |
| 52 | 55 | /* Log snapshot if GuC errors during load */ |
| 53 | 56 | struct drm_i915_gem_object *load_err_log; |
| 54 | 57 | |
| 55 | 58 | /* intel_guc_recv interrupt related state */ |
| 59 | + spinlock_t irq_lock; | |
| 56 | 60 | bool interrupts_enabled; |
| 61 | + unsigned int msg_enabled_mask; | |
| 57 | 62 | |
| 58 | 63 | struct i915_vma *ads_vma; |
| 59 | 64 | struct i915_vma *stage_desc_pool; |
| @@ -83,7 +88,11 @@ struct intel_guc { · 23 unmodified lines | ||
| 83 | 88 | struct mutex send_mutex; |
| 84 | 89 | |
| 85 | 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 | 97 | /* GuC's FW specific notify function */ |
| 89 | 98 | void (*notify)(struct intel_guc *guc); |
| @@ -92,7 +101,14 @@ struct intel_guc { · 2 unmodified lines | ||
| 92 | 101 | static |
| 93 | 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 | 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) · 1 unmodified line | ||
| 100 | 116 | guc->notify(guc); |
| 101 | 117 | } |
| 102 | 118 | |
| 103 | −/* | |
| 104 | − * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), | |
| 105 | − * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is | |
| 106 | − * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects | |
| 107 | − * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. | |
| 119 | +static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) | |
| 120 | +{ | |
| 121 | + guc->handler(guc); | |
| 122 | +} | |
| 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 | 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 | 146 | GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); |
| 115 | 147 | |
| 116 | 148 | return offset; |
| @@ -119,17 +151,43 @@ static inline u32 guc_ggtt_offset(struct i915_vma *vma) · 2 unmodified lines | ||
| 119 | 151 | void intel_guc_init_early(struct intel_guc *guc); |
| 120 | 152 | void intel_guc_init_send_regs(struct intel_guc *guc); |
| 121 | 153 | void intel_guc_init_params(struct intel_guc *guc); |
| 154 | +void intel_guc_init_ggtt_pin_bias(struct intel_guc *guc); | |
| 122 | 155 | int intel_guc_init_wq(struct intel_guc *guc); |
| 123 | 156 | void intel_guc_fini_wq(struct intel_guc *guc); |
| 124 | 157 | int intel_guc_init(struct intel_guc *guc); |
| 125 | 158 | void intel_guc_fini(struct intel_guc *guc); |
| 126 | −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); | |
| 159 | +int intel_guc_send_nop(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 | 167 | int intel_guc_sample_forcewake(struct intel_guc *guc); |
| 129 | 168 | int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); |
| 130 | 169 | int intel_guc_suspend(struct intel_guc *guc); |
| 131 | 170 | int intel_guc_resume(struct intel_guc *guc); |
| 132 | 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 | 193 | #endif |
| @@ -75,7 +75,7 @@ static void guc_policies_init(struct guc_policies *policies) · 74 unmodified lines | ||
| 75 | 75 | int intel_guc_ads_create(struct intel_guc *guc) |
| 76 | 76 | { |
| 77 | 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 | 79 | struct page *page; |
| 80 | 80 | /* The ads obj includes the struct itself and buffers passed to GuC */ |
| 81 | 81 | struct { |
| @@ -121,9 +121,9 @@ int intel_guc_ads_create(struct intel_guc *guc) · 39 unmodified lines | ||
| 121 | 121 | * to find it. Note that we have to skip our header (1 page), |
| 122 | 122 | * because our GuC shared data is there. |
| 123 | 123 | */ |
| 124 | + kernel_ctx_vma = dev_priv->kernel_context->engine[RCS].state; | |
| 124 | 125 | blob->ads.golden_context_lrca = |
| 125 | − guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + | |
| 126 | − skipped_offset; | |
| 126 | + intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset; | |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 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) · 5 unmodified lines | ||
| 135 | 135 | blob->ads.eng_state_size[engine->guc_id] = |
| 136 | 136 | engine->context_size - skipped_size; |
| 137 | 137 | |
| 138 | − base = guc_ggtt_offset(vma); | |
| 138 | + base = intel_guc_ggtt_offset(guc, vma); | |
| 139 | 139 | blob->ads.scheduler_policies = base + ptr_offset(blob, policies); |
| 140 | 140 | blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer); |
| 141 | 141 | blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); |
| @@ -24,14 +24,49 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "i915_drv.h" |
| 25 | 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 | 46 | enum { CTB_SEND = 0, CTB_RECV = 1 }; |
| 28 | 47 | |
| 29 | 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 | 56 | void intel_guc_ct_init_early(struct intel_guc_ct *ct) |
| 32 | 57 | { |
| 33 | 58 | /* we're using static channel owners */ |
| 34 | 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 | 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) · 11 unmodified lines | ||
| 49 | 84 | static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, |
| 50 | 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", | |
| 53 | − desc, cmds_addr, size, owner); | |
| 87 | + CT_DEBUG_DRIVER("CT: desc %p init addr=%#x size=%u owner=%u\n", | |
| 88 | + desc, cmds_addr, size, owner); | |
| 54 | 89 | memset(desc, 0, sizeof(*desc)); |
| 55 | 90 | desc->addr = cmds_addr; |
| 56 | 91 | desc->size = size; |
| @@ -59,8 +94,8 @@ static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, · 2 unmodified lines | ||
| 59 | 94 | |
| 60 | 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", | |
| 63 | − desc, desc->head, desc->tail); | |
| 97 | + CT_DEBUG_DRIVER("CT: desc %p reset head=%u tail=%u\n", | |
| 98 | + desc, desc->head, desc->tail); | |
| 64 | 99 | desc->head = 0; |
| 65 | 100 | desc->tail = 0; |
| 66 | 101 | desc->is_in_error = 0; |
| @@ -79,7 +114,7 @@ static int guc_action_register_ct_buffer(struct intel_guc *guc, · 12 unmodified lines | ||
| 79 | 114 | int err; |
| 80 | 115 | |
| 81 | 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 | 118 | if (err) |
| 84 | 119 | DRM_ERROR("CT: register %s buffer failed; err=%d\n", |
| 85 | 120 | guc_ct_buffer_type_to_str(type), err); |
| @@ -98,7 +133,7 @@ static int guc_action_deregister_ct_buffer(struct intel_guc *guc, · 12 unmodified lines | ||
| 98 | 133 | int err; |
| 99 | 134 | |
| 100 | 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 | 137 | if (err) |
| 103 | 138 | DRM_ERROR("CT: deregister %s buffer failed; owner=%d err=%d\n", |
| 104 | 139 | guc_ct_buffer_type_to_str(type), owner, err); |
| @@ -156,7 +191,8 @@ static int ctch_init(struct intel_guc *guc, · 51 unmodified lines | ||
| 156 | 191 | err = PTR_ERR(blob); |
| 157 | 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 | 197 | /* store pointers to desc and cmds */ |
| 162 | 198 | for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) { |
| @@ -170,8 +206,8 @@ static int ctch_init(struct intel_guc *guc, · 7 unmodified lines | ||
| 170 | 206 | err_vma: |
| 171 | 207 | i915_vma_unpin_and_release(&ctch->vma); |
| 172 | 208 | err_out: |
| 173 | − DRM_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", | |
| 174 | − ctch->owner, err); | |
| 209 | + CT_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", | |
| 210 | + ctch->owner, err); | |
| 175 | 211 | return err; |
| 176 | 212 | } |
| 177 | 213 | |
| @@ -191,8 +227,8 @@ static int ctch_open(struct intel_guc *guc, · 13 unmodified lines | ||
| 191 | 227 | int err; |
| 192 | 228 | int i; |
| 193 | 229 | |
| 194 | − DRM_DEBUG_DRIVER("CT: channel %d reopen=%s\n", | |
| 195 | − ctch->owner, yesno(ctch_is_open(ctch))); | |
| 230 | + CT_DEBUG_DRIVER("CT: channel %d reopen=%s\n", | |
| 231 | + ctch->owner, yesno(ctch_is_open(ctch))); | |
| 196 | 232 | |
| 197 | 233 | if (!ctch->vma) { |
| 198 | 234 | err = ctch_init(guc, ctch); |
| @@ -202,7 +238,7 @@ static int ctch_open(struct intel_guc *guc, · 3 unmodified lines | ||
| 202 | 238 | } |
| 203 | 239 | |
| 204 | 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 | 243 | /* (re)initialize descriptors |
| 208 | 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) · 54 unmodified lines | ||
| 263 | 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 | 320 | static int ctb_write(struct intel_guc_ct_buffer *ctb, |
| 267 | 321 | const u32 *action, |
| 268 | 322 | u32 len /* in dwords */, |
| 269 | − u32 fence) | |
| 323 | + u32 fence, | |
| 324 | + bool want_response) | |
| 270 | 325 | { |
| 271 | 326 | struct guc_ct_buffer_desc *desc = ctb->desc; |
| 272 | 327 | u32 head = desc->head / 4; /* in dwords */ |
| @@ -295,15 +350,21 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb, · 22 unmodified lines | ||
| 295 | 350 | if (unlikely(used + len + 1 >= size)) |
| 296 | 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 | 355 | * DW0: header (including action code) |
| 300 | 356 | * DW1: fence |
| 301 | 357 | * DW2+: action data |
| 302 | 358 | */ |
| 303 | 359 | header = (len << GUC_CT_MSG_LEN_SHIFT) | |
| 304 | 360 | (GUC_CT_MSG_WRITE_FENCE_TO_DESC) | |
| 361 | + (want_response ? GUC_CT_MSG_SEND_STATUS : 0) | | |
| 305 | 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 | 368 | cmds[tail] = header; |
| 308 | 369 | tail = (tail + 1) % size; |
| 309 | 370 | |
| @@ -322,16 +383,25 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb, · 12 unmodified lines | ||
| 322 | 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 | 389 | * @fence: response fence |
| 327 | 390 | * @status: placeholder for status |
| 328 | − * return: 0 response received (status is valid) | |
| 329 | − * -ETIMEDOUT no response within hardcoded timeout | |
| 330 | − * -EPROTO no response, ct buffer was in error | |
| 391 | + * | |
| 392 | + * Guc will update CT buffer descriptor with new fence and status | |
| 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, | |
| 333 | − u32 fence, | |
| 334 | − u32 *status) | |
| 402 | +static int wait_for_ctb_desc_update(struct guc_ct_buffer_desc *desc, | |
| 403 | + u32 fence, | |
| 404 | + u32 *status) | |
| 335 | 405 | { |
| 336 | 406 | int err; |
| 337 | 407 | |
| @@ -363,71 +433,440 @@ static int wait_for_response(struct guc_ct_buffer_desc *desc, · 25 unmodified lines | ||
| 363 | 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 | 473 | struct intel_guc_ct_channel *ctch, |
| 368 | 474 | const u32 *action, |
| 369 | 475 | u32 len, |
| 476 | + u32 *response_buf, | |
| 477 | + u32 response_buf_size, | |
| 370 | 478 | u32 *status) |
| 371 | 479 | { |
| 372 | 480 | struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_SEND]; |
| 373 | 481 | struct guc_ct_buffer_desc *desc = ctb->desc; |
| 482 | + struct ct_request request; | |
| 483 | + unsigned long flags; | |
| 374 | 484 | u32 fence; |
| 375 | 485 | int err; |
| 376 | 486 | |
| 377 | 487 | GEM_BUG_ON(!ctch_is_open(ctch)); |
| 378 | 488 | GEM_BUG_ON(!len); |
| 379 | 489 | GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK); |
| 490 | + GEM_BUG_ON(!response_buf && response_buf_size); | |
| 380 | 491 | |
| 381 | 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 | 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 | 512 | if (unlikely(err)) |
| 390 | − return err; | |
| 391 | − if (*status != INTEL_GUC_STATUS_SUCCESS) | |
| 392 | − return -EIO; | |
| 393 | − return 0; | |
| 513 | + goto unlink; | |
| 514 | + | |
| 515 | + if (!INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(*status)) { | |
| 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 | 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 | 548 | u32 status = ~0; /* undefined */ |
| 403 | − int err; | |
| 549 | + int ret; | |
| 404 | 550 | |
| 405 | 551 | mutex_lock(&guc->send_mutex); |
| 406 | 552 | |
| 407 | − err = ctch_send(guc, ctch, action, len, &status); | |
| 408 | − if (unlikely(err)) { | |
| 553 | + ret = ctch_send(ct, ctch, action, len, response_buf, response_buf_size, | |
| 554 | + &status); | |
| 555 | + if (unlikely(ret < 0)) { | |
| 409 | 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 | 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 | 858 | * Shall only be called for platforms with HAS_GUC_CT. |
| 420 | − * @guc: the guc | |
| 421 | − * return: 0 on success | |
| 422 | − * non-zero on failure | |
| 859 | + * | |
| 860 | + * Return: 0 on success, a negative errno code 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); | |
| 427 | − struct intel_guc_ct_channel *ctch = &guc->ct.host_channel; | |
| 864 | + struct intel_guc *guc = ct_to_guc(ct); | |
| 865 | + struct drm_i915_private *i915 = guc_to_i915(guc); | |
| 866 | + struct intel_guc_ct_channel *ctch = &ct->host_channel; | |
| 428 | 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 | 871 | err = ctch_open(guc, ctch); |
| 433 | 872 | if (unlikely(err)) |
| @@ -435,21 +874,24 @@ int intel_guc_enable_ct(struct intel_guc *guc) · 1 unmodified line | ||
| 435 | 874 | |
| 436 | 875 | /* Switch into cmd transport buffer based send() */ |
| 437 | 876 | guc->send = intel_guc_send_ct; |
| 877 | + guc->handler = intel_guc_to_host_event_handler_ct; | |
| 438 | 878 | DRM_INFO("CT: %s\n", enableddisabled(true)); |
| 439 | 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 | 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); | |
| 450 | − struct intel_guc_ct_channel *ctch = &guc->ct.host_channel; | |
| 890 | + struct intel_guc *guc = ct_to_guc(ct); | |
| 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 | 896 | if (!ctch_is_open(ctch)) |
| 455 | 897 | return; |
| @@ -458,5 +900,6 @@ void intel_guc_disable_ct(struct intel_guc *guc) · 2 unmodified lines | ||
| 458 | 900 | |
| 459 | 901 | /* Disable send */ |
| 460 | 902 | guc->send = intel_guc_send_nop; |
| 903 | + guc->handler = intel_guc_to_host_event_handler_nop; | |
| 461 | 904 | DRM_INFO("CT: %s\n", enableddisabled(false)); |
| 462 | 905 | } |
| @@ -75,12 +75,22 @@ struct intel_guc_ct_channel { · 74 unmodified lines | ||
| 75 | 75 | struct intel_guc_ct { |
| 76 | 76 | struct intel_guc_ct_channel host_channel; |
| 77 | 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 | 92 | void intel_guc_ct_init_early(struct intel_guc_ct *ct); |
| 81 | − | |
| 82 | −/* XXX: move to intel_uc.h ? don't fit there either */ | |
| 83 | −int intel_guc_enable_ct(struct intel_guc *guc); | |
| 84 | −void intel_guc_disable_ct(struct intel_guc *guc); | |
| 93 | +int intel_guc_ct_enable(struct intel_guc_ct *ct); | |
| 94 | +void intel_guc_ct_disable(struct intel_guc_ct *ct); | |
| 85 | 95 | |
| 86 | 96 | #endif /* _INTEL_GUC_CT_H_ */ |
| @@ -165,7 +165,7 @@ static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma) · 164 unmodified lines | ||
| 165 | 165 | I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size); |
| 166 | 166 | |
| 167 | 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 | 169 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); |
| 170 | 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) · 103 unmodified lines | ||
| 275 | 275 | * Called from intel_uc_init_hw() during driver load, resume from sleep and |
| 276 | 276 | * after a GPU reset. |
| 277 | 277 | * |
| 278 | − * The firmware image should have already been fetched into memory by the | |
| 279 | − * earlier call to intel_uc_init_fw(), so here we need to only check that | |
| 280 | − * fetch succeeded, and then transfer the image to the h/w. | |
| 278 | + * The firmware image should have already been fetched into memory, so only | |
| 279 | + * check that fetch succeeded, and then transfer the image to the h/w. | |
| 281 | 280 | * |
| 282 | 281 | * Return: non-zero code on error |
| 283 | 282 | */ |
| @@ -127,7 +127,7 @@ · 126 unmodified lines | ||
| 127 | 127 | #define GUC_PROFILE_ENABLED (1 << 7) |
| 128 | 128 | #define GUC_WQ_TRACK_ENABLED (1 << 8) |
| 129 | 129 | #define GUC_ADS_ENABLED (1 << 9) |
| 130 | −#define GUC_DEBUG_RESERVED (1 << 10) | |
| 130 | +#define GUC_LOG_DEFAULT_DISABLED (1 << 10) | |
| 131 | 131 | #define GUC_ADS_ADDR_SHIFT 11 |
| 132 | 132 | #define GUC_ADS_ADDR_MASK 0xfffff800 |
| 133 | 133 | |
| @@ -327,6 +327,58 @@ struct guc_stage_desc { · 193 unmodified lines | ||
| 327 | 327 | u64 desc_private; |
| 328 | 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 | 383 | * Describes single command transport buffer. |
| 332 | 384 | * Used by both guc-master and clients. |
| @@ -534,16 +586,6 @@ struct guc_log_buffer_state { · 201 unmodified lines | ||
| 534 | 586 | u32 version; |
| 535 | 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 | 589 | struct guc_ctx_report { |
| 548 | 590 | u32 report_return_status; |
| 549 | 591 | u32 reserved1[64]; |
| @@ -570,7 +612,68 @@ struct guc_shared_ctx_data { · 20 unmodified lines | ||
| 570 | 612 | struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM]; |
| 571 | 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 | 677 | enum intel_guc_action { |
| 575 | 678 | INTEL_GUC_ACTION_DEFAULT = 0x0, |
| 576 | 679 | INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2, |
| @@ -602,24 +705,22 @@ enum intel_guc_report_status { · 25 unmodified lines | ||
| 602 | 705 | INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4, |
| 603 | 706 | }; |
| 604 | 707 | |
| 605 | −/* | |
| 606 | − * The GuC sends its response to a command by overwriting the | |
| 607 | − * command in SS0. The response is distinguishable from a command | |
| 608 | − * by the fact that all the MASK bits are set. The remaining bits | |
| 609 | − * give more detail. | |
| 610 | − */ | |
| 611 | −#define INTEL_GUC_RECV_MASK ((u32)0xF0000000) | |
| 612 | −#define INTEL_GUC_RECV_IS_RESPONSE(x) ((u32)(x) >= INTEL_GUC_RECV_MASK) | |
| 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) | |
| 708 | +#define GUC_LOG_CONTROL_LOGGING_ENABLED (1 << 0) | |
| 709 | +#define GUC_LOG_CONTROL_VERBOSITY_SHIFT 4 | |
| 710 | +#define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT) | |
| 711 | +#define GUC_LOG_CONTROL_DEFAULT_LOGGING (1 << 8) | |
| 712 | + | |
| 713 | +enum intel_guc_response_status { | |
| 714 | + INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0, | |
| 715 | + INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, | |
| 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 | 724 | /* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */ |
| 624 | 725 | enum intel_guc_recv_message { |
| 625 | 726 | INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1), |
| @@ -23,12 +23,11 @@ · 22 unmodified lines | ||
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | 25 | #include <linux/debugfs.h> |
| 26 | −#include <linux/relay.h> | |
| 27 | 26 | |
| 28 | 27 | #include "intel_guc_log.h" |
| 29 | 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 | 33 | * DOC: GuC firmware log |
| @@ -39,7 +38,7 @@ static void guc_log_capture_logs(struct intel_guc *guc); · 4 unmodified lines | ||
| 39 | 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 | 43 | u32 action[] = { |
| 45 | 44 | INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE |
| @@ -48,7 +47,7 @@ static int guc_log_flush_complete(struct intel_guc *guc) · 2 unmodified lines | ||
| 48 | 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 | 52 | u32 action[] = { |
| 54 | 53 | INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH, |
| @@ -58,22 +57,40 @@ static int guc_log_flush(struct intel_guc *guc) · 3 unmodified lines | ||
| 58 | 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 | 63 | u32 action[] = { |
| 70 | 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 | 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 | 95 | * Sub buffer switch callback. Called whenever relay has to switch to a new |
| 79 | 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, · 41 unmodified lines | ||
| 121 | 138 | if (!parent) |
| 122 | 139 | return NULL; |
| 123 | 140 | |
| 124 | − /* | |
| 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, | |
| 141 | + buf_file = debugfs_create_file(filename, mode, | |
| 132 | 142 | parent, buf, &relay_file_operations); |
| 133 | 143 | return buf_file; |
| 134 | 144 | } |
| @@ -149,59 +159,7 @@ static struct rchan_callbacks relay_callbacks = { · 14 unmodified lines | ||
| 149 | 159 | .remove_buf_file = remove_buf_file_callback, |
| 150 | 160 | }; |
| 151 | 161 | |
| 152 | −static int guc_log_relay_file_create(struct intel_guc *guc) | |
| 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) | |
| 162 | +static void guc_move_to_next_buf(struct intel_guc_log *log) | |
| 205 | 163 | { |
| 206 | 164 | /* |
| 207 | 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) · 1 unmodified line | ||
| 209 | 167 | */ |
| 210 | 168 | smp_wmb(); |
| 211 | 169 | |
| 212 | − if (!guc_log_has_relay(guc)) | |
| 213 | − return; | |
| 214 | − | |
| 215 | 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 | 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 | 180 | * Just get the base address of a new sub buffer and copy data into it |
| 229 | 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) · 3 unmodified lines | ||
| 233 | 185 | * done without using relay_reserve() along with relay_write(). So its |
| 234 | 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 | 192 | enum guc_log_buffer_type type, |
| 241 | 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 | 196 | bool overflow = false; |
| 245 | 197 | |
| 246 | 198 | if (full_cnt != prev_full_cnt) { |
| 247 | 199 | overflow = true; |
| 248 | 200 | |
| 249 | − guc->log.prev_overflow_count[type] = full_cnt; | |
| 250 | − guc->log.total_overflow_count[type] += full_cnt - prev_full_cnt; | |
| 201 | + log->stats[type].overflow = full_cnt; | |
| 202 | + log->stats[type].sampled_overflow += full_cnt - prev_full_cnt; | |
| 251 | 203 | |
| 252 | 204 | if (full_cnt < prev_full_cnt) { |
| 253 | 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 | 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) · 17 unmodified lines | ||
| 275 | 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 | 232 | unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; |
| 281 | 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) · 2 unmodified lines | ||
| 284 | 236 | void *src_data, *dst_data; |
| 285 | 237 | bool new_overflow; |
| 286 | 238 | |
| 287 | − if (WARN_ON(!guc->log.runtime.buf_addr)) | |
| 288 | − return; | |
| 239 | + mutex_lock(&log->relay.lock); | |
| 289 | 240 | |
| 290 | − /* Get the pointer to shared GuC log buffer */ | |
| 291 | − log_buf_state = src_data = guc->log.runtime.buf_addr; | |
| 241 | + if (WARN_ON(!intel_guc_log_relay_enabled(log))) | |
| 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 | 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 | 250 | if (unlikely(!log_buf_snapshot_state)) { |
| 299 | 251 | /* |
| @@ -301,10 +253,9 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) · 1 unmodified line | ||
| 301 | 253 | * getting consumed by User at a slow rate. |
| 302 | 254 | */ |
| 303 | 255 | DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); |
| 304 | − guc->log.capture_miss_count++; | |
| 305 | − mutex_unlock(&guc->log.runtime.relay_lock); | |
| 256 | + log->relay.full_count++; | |
| 306 | 257 | |
| 307 | − return; | |
| 258 | + goto out_unlock; | |
| 308 | 259 | } |
| 309 | 260 | |
| 310 | 261 | /* Actual logs are present from the 2nd page */ |
| @@ -325,8 +276,8 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) · 14 unmodified lines | ||
| 325 | 276 | full_cnt = log_buf_state_local.buffer_full_cnt; |
| 326 | 277 | |
| 327 | 278 | /* Bookkeeping stuff */ |
| 328 | − guc->log.flush_count[type] += log_buf_state_local.flush_to_file; | |
| 329 | − new_overflow = guc_check_log_buf_overflow(guc, type, full_cnt); | |
| 279 | + log->stats[type].flush += log_buf_state_local.flush_to_file; | |
| 280 | + new_overflow = guc_check_log_buf_overflow(log, type, full_cnt); | |
| 330 | 281 | |
| 331 | 282 | /* Update the state of shared log buffer */ |
| 332 | 283 | log_buf_state->read_ptr = write_offset; |
| @@ -373,38 +324,35 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) · 40 unmodified lines | ||
| 373 | 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 | 333 | static void capture_logs_work(struct work_struct *work) |
| 382 | 334 | { |
| 383 | − struct intel_guc *guc = | |
| 384 | − container_of(work, struct intel_guc, log.runtime.flush_work); | |
| 385 | − | |
| 386 | − guc_log_capture_logs(guc); | |
| 387 | −} | |
| 335 | + struct intel_guc_log *log = | |
| 336 | + container_of(work, struct intel_guc_log, relay.flush_work); | |
| 388 | 337 | |
| 389 | −static bool guc_log_has_runtime(struct intel_guc *guc) | |
| 390 | −{ | |
| 391 | − return guc->log.runtime.buf_addr != NULL; | |
| 338 | + guc_log_capture_logs(log); | |
| 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 | 344 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 397 | 345 | void *vaddr; |
| 398 | 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 | 351 | return -ENODEV; |
| 404 | 352 | |
| 405 | − GEM_BUG_ON(guc_log_has_runtime(guc)); | |
| 406 | − | |
| 407 | − ret = i915_gem_object_set_to_wc_domain(guc->log.vma->obj, true); | |
| 353 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 354 | + ret = i915_gem_object_set_to_wc_domain(log->vma->obj, true); | |
| 355 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 408 | 356 | if (ret) |
| 409 | 357 | return ret; |
| 410 | 358 | |
| @@ -413,49 +361,40 @@ static int guc_log_runtime_create(struct intel_guc *guc) · 2 unmodified lines | ||
| 413 | 361 | * buffer pages, so that we can directly get the data |
| 414 | 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 | 365 | if (IS_ERR(vaddr)) { |
| 418 | 366 | DRM_ERROR("Couldn't map log buffer pages %d\n", ret); |
| 419 | 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 | 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 | − /* | |
| 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; | |
| 377 | + lockdep_assert_held(&log->relay.lock); | |
| 435 | 378 | |
| 436 | − i915_gem_object_unpin_map(guc->log.vma->obj); | |
| 437 | − guc->log.runtime.buf_addr = NULL; | |
| 379 | + i915_gem_object_unpin_map(log->vma->obj); | |
| 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); | |
| 443 | − INIT_WORK(&guc->log.runtime.flush_work, capture_logs_work); | |
| 385 | + mutex_init(&log->relay.lock); | |
| 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 | 392 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 449 | 393 | struct rchan *guc_log_relay_chan; |
| 450 | 394 | size_t n_subbufs, subbuf_size; |
| 451 | 395 | int ret; |
| 452 | 396 | |
| 453 | − if (!i915_modparams.guc_log_level) | |
| 454 | − return 0; | |
| 455 | − | |
| 456 | − mutex_lock(&guc->log.runtime.relay_lock); | |
| 457 | − | |
| 458 | − GEM_BUG_ON(guc_log_has_relay(guc)); | |
| 397 | + lockdep_assert_held(&log->relay.lock); | |
| 459 | 398 | |
| 460 | 399 | /* Keep the size of sub buffers same as shared log buffer */ |
| 461 | 400 | subbuf_size = GUC_LOG_SIZE; |
| @@ -468,157 +407,56 @@ int intel_guc_log_relay_create(struct intel_guc *guc) · 6 unmodified lines | ||
| 468 | 407 | */ |
| 469 | 408 | n_subbufs = 8; |
| 470 | 409 | |
| 471 | − /* | |
| 472 | − * Create a relay channel, so that we have buffers for storing | |
| 473 | − * the GuC firmware logs, the channel will be linked with a file | |
| 474 | − * later on when debugfs is registered. | |
| 475 | − */ | |
| 476 | − guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, | |
| 477 | − n_subbufs, &relay_callbacks, dev_priv); | |
| 410 | + guc_log_relay_chan = relay_open("guc_log", | |
| 411 | + dev_priv->drm.primary->debugfs_root, | |
| 412 | + subbuf_size, n_subbufs, | |
| 413 | + &relay_callbacks, dev_priv); | |
| 478 | 414 | if (!guc_log_relay_chan) { |
| 479 | 415 | DRM_ERROR("Couldn't create relay chan for GuC logging\n"); |
| 480 | 416 | |
| 481 | 417 | ret = -ENOMEM; |
| 482 | − goto err; | |
| 418 | + return ret; | |
| 483 | 419 | } |
| 484 | 420 | |
| 485 | 421 | GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); |
| 486 | − guc->log.runtime.relay_chan = guc_log_relay_chan; | |
| 487 | − | |
| 488 | − mutex_unlock(&guc->log.runtime.relay_lock); | |
| 422 | + log->relay.channel = guc_log_relay_chan; | |
| 489 | 423 | |
| 490 | 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); | |
| 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; | |
| 429 | + lockdep_assert_held(&log->relay.lock); | |
| 547 | 430 | |
| 548 | −err_runtime: | |
| 549 | − mutex_lock(&dev_priv->drm.struct_mutex); | |
| 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; | |
| 431 | + relay_close(log->relay.channel); | |
| 432 | + log->relay.channel = NULL; | |
| 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 | 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 | 443 | * Generally device is expected to be active only at this |
| 568 | 444 | * time, so get/put should be really quick. |
| 569 | 445 | */ |
| 570 | 446 | intel_runtime_pm_get(dev_priv); |
| 571 | − guc_log_flush_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); | |
| 447 | + guc_action_flush_log_complete(guc); | |
| 598 | 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 | 454 | struct i915_vma *vma; |
| 607 | 455 | unsigned long offset; |
| 608 | 456 | u32 flags; |
| 609 | 457 | int ret; |
| 610 | 458 | |
| 611 | − GEM_BUG_ON(guc->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 | − } | |
| 459 | + GEM_BUG_ON(log->vma); | |
| 622 | 460 | |
| 623 | 461 | vma = intel_guc_allocate_vma(guc, GUC_LOG_SIZE); |
| 624 | 462 | if (IS_ERR(vma)) { |
| @@ -626,13 +464,7 @@ int intel_guc_log_create(struct intel_guc *guc) · 1 unmodified line | ||
| 626 | 464 | goto err; |
| 627 | 465 | } |
| 628 | 466 | |
| 629 | − guc->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 | − } | |
| 467 | + log->vma = vma; | |
| 636 | 468 | |
| 637 | 469 | /* each allocated unit is a page */ |
| 638 | 470 | flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | |
| @@ -640,117 +472,159 @@ int intel_guc_log_create(struct intel_guc *guc) · 1 unmodified line | ||
| 640 | 472 | (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | |
| 641 | 473 | (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); |
| 642 | 474 | |
| 643 | − offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */ | |
| 644 | − guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; | |
| 475 | + offset = intel_guc_ggtt_offset(guc, vma) >> PAGE_SHIFT; | |
| 476 | + log->flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; | |
| 645 | 477 | |
| 646 | 478 | return 0; |
| 647 | 479 | |
| 648 | −err_vma: | |
| 649 | − i915_vma_unpin_and_release(&guc->log.vma); | |
| 650 | 480 | err: |
| 651 | 481 | /* logging will be off */ |
| 652 | 482 | i915_modparams.guc_log_level = 0; |
| 653 | 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); | |
| 659 | − i915_vma_unpin_and_release(&guc->log.vma); | |
| 493 | + GEM_BUG_ON(!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 | 502 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 665 | − bool enable_logging = control_val > 0; | |
| 666 | − u32 verbosity; | |
| 667 | 503 | int ret; |
| 668 | 504 | |
| 669 | − if (!guc->log.vma) | |
| 670 | − return -ENODEV; | |
| 505 | + BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0); | |
| 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); | |
| 673 | − if (control_val > 1 + GUC_LOG_VERBOSITY_MAX) | |
| 509 | + /* | |
| 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 | 514 | return -EINVAL; |
| 675 | 515 | |
| 676 | − /* This combination doesn't make sense & won't have any effect */ | |
| 677 | − if (!enable_logging && !i915_modparams.guc_log_level) | |
| 678 | − return 0; | |
| 516 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 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 | 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 | 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 | 536 | mutex_unlock(&dev_priv->drm.struct_mutex); |
| 689 | 537 | |
| 690 | − if (ret < 0) { | |
| 691 | − DRM_DEBUG_DRIVER("guc_logging_control action failed %d\n", ret); | |
| 692 | − return ret; | |
| 693 | − } | |
| 538 | + return ret; | |
| 539 | +} | |
| 694 | 540 | |
| 695 | − if (enable_logging) { | |
| 696 | − i915_modparams.guc_log_level = 1 + verbosity; | |
| 541 | +bool intel_guc_log_relay_enabled(const struct intel_guc_log *log) | |
| 542 | +{ | |
| 543 | + return log->relay.buf_addr; | |
| 544 | +} | |
| 697 | 545 | |
| 698 | − /* | |
| 699 | − * If log was disabled at boot time, then the relay channel file | |
| 700 | − * wouldn't have been created by now and interrupts also would | |
| 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 | − } | |
| 546 | +int intel_guc_log_relay_open(struct intel_guc_log *log) | |
| 547 | +{ | |
| 548 | + int ret; | |
| 708 | 549 | |
| 709 | − /* GuC logging is currently the only user of Guc2Host interrupts */ | |
| 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); | |
| 550 | + mutex_lock(&log->relay.lock); | |
| 723 | 551 | |
| 724 | − /* As logging is disabled, update log level to reflect that */ | |
| 725 | − i915_modparams.guc_log_level = 0; | |
| 552 | + if (intel_guc_log_relay_enabled(log)) { | |
| 553 | + ret = -EEXIST; | |
| 554 | + goto out_unlock; | |
| 726 | 555 | } |
| 727 | 556 | |
| 728 | − return ret; | |
| 729 | −} | |
| 557 | + /* | |
| 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) | |
| 732 | −{ | |
| 733 | − if (!USES_GUC_SUBMISSION(dev_priv) || !i915_modparams.guc_log_level) | |
| 734 | − return; | |
| 567 | + ret = guc_log_relay_create(log); | |
| 568 | + if (ret) | |
| 569 | + goto out_unlock; | |
| 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)) | |
| 744 | − return; | |
| 607 | + intel_runtime_pm_get(i915); | |
| 608 | + guc_action_flush_log(guc); | |
| 609 | + intel_runtime_pm_put(i915); | |
| 745 | 610 | |
| 746 | − mutex_lock(&dev_priv->drm.struct_mutex); | |
| 747 | − /* GuC logging is currently the only user of Guc2Host interrupts */ | |
| 748 | − intel_runtime_pm_get(dev_priv); | |
| 749 | − gen9_disable_guc_interrupts(dev_priv); | |
| 750 | − intel_runtime_pm_put(dev_priv); | |
| 611 | + /* GuC would have updated log buffer by now, so capture it */ | |
| 612 | + guc_log_capture_logs(log); | |
| 613 | +} | |
| 751 | 614 | |
| 752 | − guc_log_runtime_destroy(guc); | |
| 753 | − mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 615 | +void intel_guc_log_relay_close(struct intel_guc_log *log) | |
| 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 | } |
| @@ -25,11 +25,12 @@ · 24 unmodified lines | ||
| 25 | 25 | #ifndef _INTEL_GUC_LOG_H_ |
| 26 | 26 | #define _INTEL_GUC_LOG_H_ |
| 27 | 27 | |
| 28 | +#include <linux/mutex.h> | |
| 29 | +#include <linux/relay.h> | |
| 28 | 30 | #include <linux/workqueue.h> |
| 29 | 31 | |
| 30 | 32 | #include "intel_guc_fwif.h" |
| 31 | 33 | |
| 32 | −struct drm_i915_private; | |
| 33 | 34 | struct intel_guc; |
| 34 | 35 | |
| 35 | 36 | /* |
| @@ -39,33 +40,53 @@ struct intel_guc; · 3 unmodified lines | ||
| 39 | 40 | #define GUC_LOG_SIZE ((1 + GUC_LOG_DPC_PAGES + 1 + GUC_LOG_ISR_PAGES + \ |
| 40 | 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 | 60 | struct intel_guc_log { |
| 43 | 61 | u32 flags; |
| 44 | 62 | struct i915_vma *vma; |
| 45 | − /* The runtime stuff gets created only when GuC logging gets enabled */ | |
| 46 | 63 | struct { |
| 47 | 64 | void *buf_addr; |
| 48 | 65 | struct workqueue_struct *flush_wq; |
| 49 | 66 | struct work_struct flush_work; |
| 50 | − struct rchan *relay_chan; | |
| 51 | − /* To serialize the access to relay_chan */ | |
| 52 | − struct mutex relay_lock; | |
| 53 | − } runtime; | |
| 67 | + struct rchan *channel; | |
| 68 | + struct mutex lock; | |
| 69 | + u32 full_count; | |
| 70 | + } relay; | |
| 54 | 71 | /* logging related stats */ |
| 55 | − u32 capture_miss_count; | |
| 56 | − u32 flush_interrupt_count; | |
| 57 | − u32 prev_overflow_count[GUC_MAX_LOG_BUFFER]; | |
| 58 | − u32 total_overflow_count[GUC_MAX_LOG_BUFFER]; | |
| 59 | − u32 flush_count[GUC_MAX_LOG_BUFFER]; | |
| 72 | + struct { | |
| 73 | + u32 sampled_overflow; | |
| 74 | + u32 overflow; | |
| 75 | + u32 flush; | |
| 76 | + } stats[GUC_MAX_LOG_BUFFER]; | |
| 60 | 77 | }; |
| 61 | 78 | |
| 62 | −int intel_guc_log_create(struct intel_guc *guc); | |
| 63 | −void intel_guc_log_destroy(struct intel_guc *guc); | |
| 64 | −void intel_guc_log_init_early(struct intel_guc *guc); | |
| 65 | −int intel_guc_log_relay_create(struct intel_guc *guc); | |
| 66 | −void intel_guc_log_relay_destroy(struct intel_guc *guc); | |
| 67 | −int intel_guc_log_control(struct intel_guc *guc, u64 control_val); | |
| 68 | −void i915_guc_log_register(struct drm_i915_private *dev_priv); | |
| 69 | −void i915_guc_log_unregister(struct drm_i915_private *dev_priv); | |
| 79 | +void intel_guc_log_init_early(struct intel_guc_log *log); | |
| 80 | +int intel_guc_log_create(struct intel_guc_log *log); | |
| 81 | +void intel_guc_log_destroy(struct intel_guc_log *log); | |
| 82 | + | |
| 83 | +int intel_guc_log_level_get(struct intel_guc_log *log); | |
| 84 | +int intel_guc_log_level_set(struct intel_guc_log *log, u64 control_val); | |
| 85 | +bool intel_guc_log_relay_enabled(const struct intel_guc_log *log); | |
| 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 | 92 | #endif |
| @@ -66,22 +66,20 @@ · 65 unmodified lines | ||
| 66 | 66 | #define UOS_MOVE (1<<4) |
| 67 | 67 | #define START_DMA (1<<0) |
| 68 | 68 | #define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) |
| 69 | +#define GUC_WOPCM_OFFSET_VALID (1<<0) | |
| 69 | 70 | #define HUC_LOADING_AGENT_VCR (0<<1) |
| 70 | 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 | 74 | #define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) |
| 73 | 75 | |
| 74 | 76 | #define HUC_STATUS2 _MMIO(0xD3B0) |
| 75 | 77 | #define HUC_FW_VERIFIED (1<<7) |
| 76 | 78 | |
| 77 | −/* Defines WOPCM space available to GuC firmware */ | |
| 78 | 79 | #define GUC_WOPCM_SIZE _MMIO(0xc050) |
| 79 | −/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ | |
| 80 | −#define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ | |
| 81 | −#define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ | |
| 82 | − | |
| 83 | −/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ | |
| 84 | −#define GUC_GGTT_TOP 0xFEE00000 | |
| 80 | +#define GUC_WOPCM_SIZE_LOCKED (1<<0) | |
| 81 | +#define GUC_WOPCM_SIZE_SHIFT 12 | |
| 82 | +#define GUC_WOPCM_SIZE_MASK (0xfffff << GUC_WOPCM_SIZE_SHIFT) | |
| 85 | 83 | |
| 86 | 84 | #define GEN8_GT_PM_CONFIG _MMIO(0x138140) |
| 87 | 85 | #define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) |
| @@ -231,8 +231,8 @@ static int create_doorbell(struct intel_guc_client *client) · 230 unmodified lines | ||
| 231 | 231 | if (ret) { |
| 232 | 232 | __destroy_doorbell(client); |
| 233 | 233 | __update_doorbell_desc(client, GUC_DOORBELL_INVALID); |
| 234 | − DRM_ERROR("Couldn't create client %u doorbell: %d\n", | |
| 235 | − client->stage_id, ret); | |
| 234 | + DRM_DEBUG_DRIVER("Couldn't create client %u doorbell: %d\n", | |
| 235 | + client->stage_id, ret); | |
| 236 | 236 | return ret; |
| 237 | 237 | } |
| 238 | 238 | |
| @@ -386,8 +386,8 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 147 unmodified lines | ||
| 386 | 386 | lrc->context_desc = lower_32_bits(ce->lrc_desc); |
| 387 | 387 | |
| 388 | 388 | /* The state page is after PPHWSP */ |
| 389 | − lrc->ring_lrca = | |
| 390 | − guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; | |
| 389 | + lrc->ring_lrca = intel_guc_ggtt_offset(guc, ce->state) + | |
| 390 | + LRC_STATE_PN * PAGE_SIZE; | |
| 391 | 391 | |
| 392 | 392 | /* XXX: In direct submission, the GuC wants the HW context id |
| 393 | 393 | * here. In proxy submission, it wants the stage id |
| @@ -395,7 +395,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 1 unmodified line | ||
| 395 | 395 | lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | |
| 396 | 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 | 399 | lrc->ring_end = lrc->ring_begin + ce->ring->size - 1; |
| 400 | 400 | lrc->ring_next_free_location = lrc->ring_begin; |
| 401 | 401 | lrc->ring_current_tail_pointer_value = 0; |
| @@ -411,7 +411,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 9 unmodified lines | ||
| 411 | 411 | * The doorbell, process descriptor, and workqueue are all parts |
| 412 | 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 | 415 | desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + |
| 416 | 416 | client->doorbell_offset; |
| 417 | 417 | desc->db_trigger_cpu = ptr_to_u64(__get_doorbell(client)); |
| @@ -584,7 +584,7 @@ static void inject_preempt_context(struct work_struct *work) · 166 unmodified lines | ||
| 584 | 584 | data[3] = engine->guc_id; |
| 585 | 585 | data[4] = guc->execbuf_client->priority; |
| 586 | 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 | 589 | if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { |
| 590 | 590 | execlists_clear_active(&engine->execlists, |
| @@ -657,6 +657,16 @@ static void port_assign(struct execlist_port *port, struct i915_request *rq) · 66 unmodified lines | ||
| 657 | 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 | 670 | static void guc_dequeue(struct intel_engine_cs *engine) |
| 661 | 671 | { |
| 662 | 672 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| @@ -672,12 +682,12 @@ static void guc_dequeue(struct intel_engine_cs *engine) · 9 unmodified lines | ||
| 672 | 682 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
| 673 | 683 | |
| 674 | 684 | if (port_isset(port)) { |
| 675 | − if (engine->i915->preempt_context) { | |
| 685 | + if (intel_engine_has_preemption(engine)) { | |
| 676 | 686 | struct guc_preempt_work *preempt_work = |
| 677 | 687 | &engine->i915->guc.preempt_work[engine->id]; |
| 688 | + int prio = execlists->queue_priority; | |
| 678 | 689 | |
| 679 | − if (execlists->queue_priority > | |
| 680 | − max(port_request(port)->priotree.priority, 0)) { | |
| 690 | + if (__execlists_need_preempt(prio, port_prio(port))) { | |
| 681 | 691 | execlists_set_active(execlists, |
| 682 | 692 | EXECLISTS_ACTIVE_PREEMPT); |
| 683 | 693 | queue_work(engine->i915->guc.preempt_wq, |
| @@ -728,7 +738,7 @@ done: · 44 unmodified lines | ||
| 728 | 738 | execlists->first = rb; |
| 729 | 739 | if (submit) { |
| 730 | 740 | port_assign(port, last); |
| 731 | − execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | |
| 741 | + execlists_user_begin(execlists, execlists->port); | |
| 732 | 742 | guc_submit(engine); |
| 733 | 743 | } |
| 734 | 744 | |
| @@ -748,17 +758,20 @@ static void guc_submission_tasklet(unsigned long data) · 13 unmodified lines | ||
| 748 | 758 | struct execlist_port *port = execlists->port; |
| 749 | 759 | struct i915_request *rq; |
| 750 | 760 | |
| 751 | − rq = port_request(&port[0]); | |
| 761 | + rq = port_request(port); | |
| 752 | 762 | while (rq && i915_request_completed(rq)) { |
| 753 | 763 | trace_i915_request_out(rq); |
| 754 | 764 | i915_request_put(rq); |
| 755 | 765 | |
| 756 | − execlists_port_complete(execlists, port); | |
| 757 | − | |
| 758 | − rq = port_request(&port[0]); | |
| 766 | + port = execlists_port_complete(execlists, port); | |
| 767 | + if (port_isset(port)) { | |
| 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 | 776 | if (execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT) && |
| 764 | 777 | intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) == |
| @@ -246,9 +246,8 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) · 245 unmodified lines | ||
| 246 | 246 | */ |
| 247 | 247 | tmp = I915_READ_CTL(engine); |
| 248 | 248 | if (tmp & RING_WAIT) { |
| 249 | − i915_handle_error(dev_priv, BIT(engine->id), | |
| 250 | − "Kicking stuck wait on %s", | |
| 251 | − engine->name); | |
| 249 | + i915_handle_error(dev_priv, BIT(engine->id), 0, | |
| 250 | + "stuck wait on %s", engine->name); | |
| 252 | 251 | I915_WRITE_CTL(engine, tmp); |
| 253 | 252 | return ENGINE_WAIT_KICK; |
| 254 | 253 | } |
| @@ -258,8 +257,8 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) · 3 unmodified lines | ||
| 258 | 257 | default: |
| 259 | 258 | return ENGINE_DEAD; |
| 260 | 259 | case 1: |
| 261 | − i915_handle_error(dev_priv, ALL_ENGINES, | |
| 262 | − "Kicking stuck semaphore on %s", | |
| 260 | + i915_handle_error(dev_priv, ALL_ENGINES, 0, | |
| 261 | + "stuck semaphore on %s", | |
| 263 | 262 | engine->name); |
| 264 | 263 | I915_WRITE_CTL(engine, tmp); |
| 265 | 264 | return ENGINE_WAIT_KICK; |
| @@ -386,13 +385,13 @@ static void hangcheck_declare_hang(struct drm_i915_private *i915, · 120 unmodified lines | ||
| 386 | 385 | if (stuck != hung) |
| 387 | 386 | hung &= ~stuck; |
| 388 | 387 | len = scnprintf(msg, sizeof(msg), |
| 389 | − "%s on ", stuck == hung ? "No progress" : "Hang"); | |
| 388 | + "%s on ", stuck == hung ? "no progress" : "hang"); | |
| 390 | 389 | for_each_engine_masked(engine, i915, hung, tmp) |
| 391 | 390 | len += scnprintf(msg + len, sizeof(msg) - len, |
| 392 | 391 | "%s, ", engine->name); |
| 393 | 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 | /* |
| @@ -37,6 +37,43 @@ static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, · 36 unmodified lines | ||
| 37 | 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 | 77 | static void intel_hdcp_clear_keys(struct drm_i915_private *dev_priv) |
| 41 | 78 | { |
| 42 | 79 | I915_WRITE(HDCP_KEY_CONF, HDCP_CLEAR_KEYS_TRIGGER); |
| @@ -142,53 +179,17 @@ bool intel_hdcp_is_ksv_valid(u8 *ksv) · 99 unmodified lines | ||
| 142 | 179 | return true; |
| 143 | 180 | } |
| 144 | 181 | |
| 145 | −/* Implements Part 2 of the HDCP authorization procedure */ | |
| 146 | 182 | static |
| 147 | −int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, | |
| 148 | − const struct intel_hdcp_shim *shim) | |
| 183 | +int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, | |
| 184 | + const struct intel_hdcp_shim *shim, | |
| 185 | + u8 *ksv_fifo, u8 num_downstream, u8 *bstatus) | |
| 149 | 186 | { |
| 150 | 187 | struct drm_i915_private *dev_priv; |
| 151 | 188 | u32 vprime, sha_text, sha_leftovers, rep_ctl; |
| 152 | − u8 bstatus[2], num_downstream, *ksv_fifo; | |
| 153 | 189 | int ret, i, j, sha_idx; |
| 154 | 190 | |
| 155 | 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 | 193 | /* Process V' values from the receiver */ |
| 193 | 194 | for (i = 0; i < DRM_HDCP_V_PRIME_NUM_PARTS; i++) { |
| 194 | 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, · 158 unmodified lines | ||
| 353 | 354 | return ret; |
| 354 | 355 | sha_idx += sizeof(sha_text); |
| 355 | 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 | 359 | return -EINVAL; |
| 358 | 360 | } |
| 359 | 361 | |
| @@ -381,17 +383,83 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port, · 21 unmodified lines | ||
| 381 | 383 | if (intel_wait_for_register(dev_priv, HDCP_REP_CTL, |
| 382 | 384 | HDCP_SHA1_COMPLETE, |
| 383 | 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 | 387 | return -ETIMEDOUT; |
| 386 | 388 | } |
| 387 | 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 | 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 | 457 | DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n", |
| 393 | 458 | num_downstream); |
| 394 | − return 0; | |
| 459 | + ret = 0; | |
| 460 | +err: | |
| 461 | + kfree(ksv_fifo); | |
| 462 | + return ret; | |
| 395 | 463 | } |
| 396 | 464 | |
| 397 | 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, · 108 unmodified lines | ||
| 506 | 574 | */ |
| 507 | 575 | wait_remaining_ms_from_jiffies(r0_prime_gen_start, 300); |
| 508 | 576 | |
| 509 | − ri.reg = 0; | |
| 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); | |
| 577 | + tries = 3; | |
| 514 | 578 | |
| 515 | − /* Wait for Ri prime match */ | |
| 516 | − if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & | |
| 517 | − (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) { | |
| 579 | + /* | |
| 580 | + * DP HDCP Spec mandates the two more reattempt to read R0, incase | |
| 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 | 597 | DRM_ERROR("Timed out waiting for Ri prime match (%x)\n", |
| 519 | 598 | I915_READ(PORT_HDCP_STATUS(port))); |
| 520 | 599 | return -ETIMEDOUT; |
| @@ -580,8 +659,8 @@ static int _intel_hdcp_enable(struct intel_connector *connector) · 59 unmodified lines | ||
| 580 | 659 | DRM_DEBUG_KMS("[%s:%d] HDCP is being enabled...\n", |
| 581 | 660 | connector->base.name, connector->base.base.id); |
| 582 | 661 | |
| 583 | − if (!(I915_READ(SKL_FUSE_STATUS) & SKL_FUSE_PG_DIST_STATUS(1))) { | |
| 584 | − DRM_ERROR("PG1 is disabled, cannot load keys\n"); | |
| 662 | + if (!hdcp_key_loadable(dev_priv)) { | |
| 663 | + DRM_ERROR("HDCP key Load is not possible\n"); | |
| 585 | 664 | return -ENXIO; |
| 586 | 665 | } |
| 587 | 666 | |
| @@ -2082,41 +2082,33 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c · 2081 unmodified lines | ||
| 2082 | 2082 | * it enables scrambling. This should be called before enabling the HDMI |
| 2083 | 2083 | * 2.0 port, as the sink can choose to disable the scrambling if it doesn't |
| 2084 | 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 | 2090 | struct drm_connector *connector, |
| 2088 | 2091 | bool high_tmds_clock_ratio, |
| 2089 | 2092 | bool scrambling) |
| 2090 | 2093 | { |
| 2094 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 2091 | 2095 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
| 2092 | − struct drm_i915_private *dev_priv = connector->dev->dev_private; | |
| 2093 | 2096 | struct drm_scrambling *sink_scrambling = |
| 2094 | − &connector->display_info.hdmi.scdc.scrambling; | |
| 2095 | − struct i2c_adapter *adptr = intel_gmbus_get_adapter(dev_priv, | |
| 2096 | − intel_hdmi->ddc_bus); | |
| 2097 | − bool ret; | |
| 2097 | + &connector->display_info.hdmi.scdc.scrambling; | |
| 2098 | + struct i2c_adapter *adapter = | |
| 2099 | + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); | |
| 2098 | 2100 | |
| 2099 | 2101 | if (!sink_scrambling->supported) |
| 2100 | − return; | |
| 2101 | − | |
| 2102 | − DRM_DEBUG_KMS("Setting sink scrambling for enc:%s connector:%s\n", | |
| 2103 | − encoder->base.name, connector->name); | |
| 2102 | + return true; | |
| 2104 | 2103 | |
| 2105 | − /* Set TMDS bit clock ratio to 1/40 or 1/10 */ | |
| 2106 | − ret = drm_scdc_set_high_tmds_clock_ratio(adptr, high_tmds_clock_ratio); | |
| 2107 | − if (!ret) { | |
| 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 | − } | |
| 2104 | + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n", | |
| 2105 | + connector->base.id, connector->name, | |
| 2106 | + yesno(scrambling), high_tmds_clock_ratio ? 40 : 10); | |
| 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 | 2114 | static u8 chv_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) |
| @@ -100,6 +100,8 @@ enum port intel_hpd_pin_to_port(struct drm_i915_private *dev_priv, · 99 unmodified lines | ||
| 100 | 100 | if (IS_CNL_WITH_PORT_F(dev_priv)) |
| 101 | 101 | return PORT_F; |
| 102 | 102 | return PORT_E; |
| 103 | + case HPD_PORT_F: | |
| 104 | + return PORT_F; | |
| 103 | 105 | default: |
| 104 | 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, · 26 unmodified lines | ||
| 132 | 134 | case PORT_F: |
| 133 | 135 | if (IS_CNL_WITH_PORT_F(dev_priv)) |
| 134 | 136 | return HPD_PORT_E; |
| 137 | + return HPD_PORT_F; | |
| 135 | 138 | default: |
| 136 | 139 | MISSING_CASE(port); |
| 137 | 140 | return HPD_NONE; |
| @@ -55,7 +55,7 @@ int intel_huc_auth(struct intel_huc *huc) · 54 unmodified lines | ||
| 55 | 55 | return -ENOEXEC; |
| 56 | 56 | |
| 57 | 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 | 59 | if (IS_ERR(vma)) { |
| 60 | 60 | ret = PTR_ERR(vma); |
| 61 | 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) · 1 unmodified line | ||
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 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 | 68 | if (ret) { |
| 68 | 69 | DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); |
| 69 | 70 | goto fail_unpin; |
| @@ -91,3 +92,28 @@ fail: · 21 unmodified lines | ||
| 91 | 92 | DRM_ERROR("HuC: Authentication failed %d\n", ret); |
| 92 | 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 | +} | |
| @@ -37,5 +37,12 @@ struct intel_huc { · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | void intel_huc_init_early(struct intel_huc *huc); |
| 39 | 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 | 48 | #endif |
| @@ -118,7 +118,8 @@ static int huc_fw_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) · 117 unmodified lines | ||
| 118 | 118 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
| 119 | 119 | |
| 120 | 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 | 123 | I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); |
| 123 | 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) · 29 unmodified lines | ||
| 154 | 155 | * Called from intel_uc_init_hw() during driver load, resume from sleep and |
| 155 | 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 | − * earlier call to intel_uc_init_fw(), so here we need to only check that | |
| 159 | − * fetch succeeded, and then transfer the image to the h/w. | |
| 158 | + * The firmware image should have already been fetched into memory, so only | |
| 159 | + * check that fetch succeeded, and then transfer the image to the h/w. | |
| 160 | 160 | * |
| 161 | 161 | * Return: non-zero code on error |
| 162 | 162 | */ |
| @@ -139,6 +139,7 @@ · 138 unmodified lines | ||
| 139 | 139 | #include "i915_gem_render_state.h" |
| 140 | 140 | #include "intel_lrc_reg.h" |
| 141 | 141 | #include "intel_mocs.h" |
| 142 | +#include "intel_workarounds.h" | |
| 142 | 143 | |
| 143 | 144 | #define RING_EXECLIST_QFULL (1 << 0x2) |
| 144 | 145 | #define RING_EXECLIST1_VALID (1 << 0x3) |
| @@ -183,7 +184,8 @@ static inline bool need_preempt(const struct intel_engine_cs *engine, · 38 unmodified lines | ||
| 183 | 184 | const struct i915_request *last, |
| 184 | 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) · 184 unmodified lines | ||
| 374 | 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 | 392 | static inline void |
| 378 | 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) · 74 unmodified lines | ||
| 454 | 469 | desc = execlists_update_context(rq); |
| 455 | 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 | 473 | engine->name, n, |
| 459 | 474 | port[n].context_id, count, |
| 460 | 475 | rq->global_seqno, |
| 476 | + rq->fence.context, rq->fence.seqno, | |
| 477 | + intel_engine_get_seqno(engine), | |
| 461 | 478 | rq_prio(rq)); |
| 462 | 479 | } else { |
| 463 | 480 | GEM_BUG_ON(!n); |
| @@ -697,8 +714,27 @@ static void execlists_dequeue(struct intel_engine_cs *engine) · 233 unmodified lines | ||
| 697 | 714 | if (p->priority != I915_PRIORITY_NORMAL) |
| 698 | 715 | kmem_cache_free(engine->i915->priorities, p); |
| 699 | 716 | } |
| 717 | + | |
| 700 | 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 | 738 | execlists->first = rb; |
| 703 | 739 | if (submit) |
| 704 | 740 | port_assign(port, last); |
| @@ -710,7 +746,7 @@ unlock: · 5 unmodified lines | ||
| 710 | 746 | spin_unlock_irq(&engine->timeline->lock); |
| 711 | 747 | |
| 712 | 748 | if (submit) { |
| 713 | − execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | |
| 749 | + execlists_user_begin(execlists, execlists->port); | |
| 714 | 750 | execlists_submit_ports(engine); |
| 715 | 751 | } |
| 716 | 752 | |
| @@ -727,6 +763,13 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) · 10 unmodified lines | ||
| 727 | 763 | while (num_ports-- && port_isset(port)) { |
| 728 | 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 | 773 | GEM_BUG_ON(!execlists->active); |
| 731 | 774 | intel_engine_context_out(rq->engine); |
| 732 | 775 | |
| @@ -741,7 +784,58 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) · 8 unmodified lines | ||
| 741 | 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 | 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) · 3 unmodified lines | ||
| 751 | 845 | struct rb_node *rb; |
| 752 | 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 | 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) · 13 unmodified lines | ||
| 771 | 866 | |
| 772 | 867 | /* Cancel the requests on the HW and clear the ELSP tracker. */ |
| 773 | 868 | execlists_cancel_port_requests(execlists); |
| 869 | + reset_irq(engine); | |
| 774 | 870 | |
| 775 | 871 | spin_lock(&engine->timeline->lock); |
| 776 | 872 | |
| @@ -809,17 +905,6 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) · 32 unmodified lines | ||
| 809 | 905 | |
| 810 | 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 | 908 | local_irq_restore(flags); |
| 824 | 909 | } |
| 825 | 910 | |
| @@ -831,7 +916,7 @@ static void execlists_submission_tasklet(unsigned long data) · 5 unmodified lines | ||
| 831 | 916 | { |
| 832 | 917 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; |
| 833 | 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 | 920 | struct drm_i915_private *dev_priv = engine->i915; |
| 836 | 921 | bool fw = false; |
| 837 | 922 | |
| @@ -958,10 +1043,13 @@ static void execlists_submission_tasklet(unsigned long data) · 120 unmodified lines | ||
| 958 | 1043 | EXECLISTS_ACTIVE_USER)); |
| 959 | 1044 | |
| 960 | 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 | 1047 | engine->name, |
| 963 | 1048 | port->context_id, count, |
| 964 | 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 | 1053 | rq ? rq_prio(rq) : 0); |
| 966 | 1054 | |
| 967 | 1055 | /* Check the context/desc id for this event matches */ |
| @@ -969,10 +1057,28 @@ static void execlists_submission_tasklet(unsigned long data) · 1 unmodified line | ||
| 969 | 1057 | |
| 970 | 1058 | GEM_BUG_ON(count == 0); |
| 971 | 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 | 1068 | GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); |
| 973 | 1069 | GEM_BUG_ON(port_isset(&port[1]) && |
| 974 | 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 | 1080 | GEM_BUG_ON(!i915_request_completed(rq)); |
| 1081 | + | |
| 976 | 1082 | execlists_context_schedule_out(rq); |
| 977 | 1083 | trace_i915_request_out(rq); |
| 978 | 1084 | i915_request_put(rq); |
| @@ -980,17 +1086,14 @@ static void execlists_submission_tasklet(unsigned long data) · 1 unmodified line | ||
| 980 | 1086 | GEM_TRACE("%s completed ctx=%d\n", |
| 981 | 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 | 1094 | } else { |
| 985 | 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 | 1099 | if (head != execlists->csb_head) { |
| @@ -1019,12 +1122,16 @@ static void queue_request(struct intel_engine_cs *engine, · 22 unmodified lines | ||
| 1019 | 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 | 1131 | static void submit_queue(struct intel_engine_cs *engine, int prio) |
| 1023 | 1132 | { |
| 1024 | − if (prio > engine->execlists.queue_priority) { | |
| 1025 | − engine->execlists.queue_priority = prio; | |
| 1026 | − tasklet_hi_schedule(&engine->execlists.tasklet); | |
| 1027 | − } | |
| 1133 | + if (prio > engine->execlists.queue_priority) | |
| 1134 | + __submit_queue(engine, prio); | |
| 1028 | 1135 | } |
| 1029 | 1136 | |
| 1030 | 1137 | static void execlists_submit_request(struct i915_request *request) |
| @@ -1157,7 +1264,10 @@ static void execlists_schedule(struct i915_request *request, int prio) · 126 unmodified lines | ||
| 1157 | 1264 | __list_del_entry(&pt->link); |
| 1158 | 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 | 1273 | spin_unlock_irq(&engine->timeline->lock); |
| @@ -1224,6 +1334,7 @@ execlists_context_pin(struct intel_engine_cs *engine, · 60 unmodified lines | ||
| 1224 | 1334 | ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; |
| 1225 | 1335 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = |
| 1226 | 1336 | i915_ggtt_offset(ce->ring->vma); |
| 1337 | + ce->lrc_reg_state[CTX_RING_HEAD+1] = ce->ring->head; | |
| 1227 | 1338 | |
| 1228 | 1339 | ce->state->obj->pin_global++; |
| 1229 | 1340 | i915_gem_context_get(ctx); |
| @@ -1574,14 +1685,6 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) · 344 unmodified lines | ||
| 1574 | 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 | 1688 | static void enable_execlists(struct intel_engine_cs *engine) |
| 1586 | 1689 | { |
| 1587 | 1690 | struct drm_i915_private *dev_priv = engine->i915; |
| @@ -1641,6 +1744,10 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine) · 53 unmodified lines | ||
| 1641 | 1744 | if (ret) |
| 1642 | 1745 | return ret; |
| 1643 | 1746 | |
| 1747 | + ret = intel_whitelist_workarounds_apply(engine); | |
| 1748 | + if (ret) | |
| 1749 | + return ret; | |
| 1750 | + | |
| 1644 | 1751 | /* We need to disable the AsyncFlip performance optimisations in order |
| 1645 | 1752 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be |
| 1646 | 1753 | * programmed to '1' on all products. |
| @@ -1651,7 +1758,7 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine) · 4 unmodified lines | ||
| 1651 | 1758 | |
| 1652 | 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 | 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) · 4 unmodified lines | ||
| 1662 | 1769 | if (ret) |
| 1663 | 1770 | return ret; |
| 1664 | 1771 | |
| 1665 | − return init_workarounds_ring(engine); | |
| 1666 | −} | |
| 1667 | − | |
| 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)); | |
| 1772 | + ret = intel_whitelist_workarounds_apply(engine); | |
| 1773 | + if (ret) | |
| 1774 | + return ret; | |
| 1689 | 1775 | |
| 1690 | − clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | |
| 1776 | + return 0; | |
| 1691 | 1777 | } |
| 1692 | 1778 | |
| 1693 | 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, · 3 unmodified lines | ||
| 1697 | 1783 | struct intel_context *ce; |
| 1698 | 1784 | unsigned long flags; |
| 1699 | 1785 | |
| 1700 | − GEM_TRACE("%s seqno=%x\n", | |
| 1701 | − engine->name, request ? request->global_seqno : 0); | |
| 1786 | + GEM_TRACE("%s request global=%x, current=%d\n", | |
| 1787 | + engine->name, request ? request->global_seqno : 0, | |
| 1788 | + intel_engine_get_seqno(engine)); | |
| 1702 | 1789 | |
| 1703 | 1790 | /* See execlists_cancel_requests() for the irq/spinlock split. */ |
| 1704 | 1791 | local_irq_save(flags); |
| 1705 | 1792 | |
| 1706 | − reset_irq(engine); | |
| 1707 | − | |
| 1708 | 1793 | /* |
| 1709 | 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, · 4 unmodified lines | ||
| 1715 | 1800 | * requests were completed. |
| 1716 | 1801 | */ |
| 1717 | 1802 | execlists_cancel_port_requests(execlists); |
| 1803 | + reset_irq(engine); | |
| 1718 | 1804 | |
| 1719 | 1805 | /* Push back any incomplete requests for replay after the reset. */ |
| 1720 | 1806 | spin_lock(&engine->timeline->lock); |
| 1721 | 1807 | __unwind_incomplete_requests(engine); |
| 1722 | 1808 | spin_unlock(&engine->timeline->lock); |
| 1723 | 1809 | |
| 1724 | − /* Mark all CS interrupts as complete */ | |
| 1725 | − execlists->active = 0; | |
| 1726 | − | |
| 1727 | 1810 | local_irq_restore(flags); |
| 1728 | 1811 | |
| 1729 | 1812 | /* |
| @@ -2015,7 +2098,7 @@ static int gen8_init_rcs_context(struct i915_request *rq) · 285 unmodified lines | ||
| 2015 | 2098 | { |
| 2016 | 2099 | int ret; |
| 2017 | 2100 | |
| 2018 | − ret = intel_ring_workarounds_emit(rq); | |
| 2101 | + ret = intel_ctx_workarounds_emit(rq); | |
| 2019 | 2102 | if (ret) |
| 2020 | 2103 | return ret; |
| 2021 | 2104 | |
| @@ -2075,11 +2158,13 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) · 53 unmodified lines | ||
| 2075 | 2158 | engine->unpark = NULL; |
| 2076 | 2159 | |
| 2077 | 2160 | engine->flags |= I915_ENGINE_SUPPORTS_STATS; |
| 2161 | + if (engine->i915->preempt_context) | |
| 2162 | + engine->flags |= I915_ENGINE_HAS_PREEMPTION; | |
| 2078 | 2163 | |
| 2079 | 2164 | engine->i915->caps.scheduler = |
| 2080 | 2165 | I915_SCHEDULER_CAP_ENABLED | |
| 2081 | 2166 | I915_SCHEDULER_CAP_PRIORITY; |
| 2082 | − if (engine->i915->preempt_context) | |
| 2167 | + if (intel_engine_has_preemption(engine)) | |
| 2083 | 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) · 32 unmodified lines | ||
| 2118 | 2203 | static inline void |
| 2119 | 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 | 2220 | engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; |
| 2123 | 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) · 426 unmodified lines | ||
| 2551 | 2649 | } |
| 2552 | 2650 | } |
| 2553 | 2651 | } |
| 2652 | + | |
| 2653 | +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | |
| 2654 | +#include "selftests/intel_lrc.c" | |
| 2655 | +#endif | |
| @@ -807,6 +807,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, · 806 unmodified lines | ||
| 807 | 807 | ret = PTR_ERR(vma); |
| 808 | 808 | goto out_pin_section; |
| 809 | 809 | } |
| 810 | + intel_fb_obj_flush(new_bo, ORIGIN_DIRTYFB); | |
| 810 | 811 | |
| 811 | 812 | ret = i915_vma_put_fence(vma); |
| 812 | 813 | if (ret) |
| @@ -569,7 +569,8 @@ unlock: · 568 unmodified lines | ||
| 569 | 569 | static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, |
| 570 | 570 | enum pipe pipe, |
| 571 | 571 | enum intel_pipe_crc_source *source, |
| 572 | − uint32_t *val) | |
| 572 | + uint32_t *val, | |
| 573 | + bool set_wa) | |
| 573 | 574 | { |
| 574 | 575 | if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) |
| 575 | 576 | *source = INTEL_PIPE_CRC_SOURCE_PF; |
| @@ -582,7 +583,7 @@ static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, · 6 unmodified lines | ||
| 582 | 583 | *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; |
| 583 | 584 | break; |
| 584 | 585 | case INTEL_PIPE_CRC_SOURCE_PF: |
| 585 | − if ((IS_HASWELL(dev_priv) || | |
| 586 | + if (set_wa && (IS_HASWELL(dev_priv) || | |
| 586 | 587 | IS_BROADWELL(dev_priv)) && pipe == PIPE_A) |
| 587 | 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, · 11 unmodified lines | ||
| 600 | 601 | |
| 601 | 602 | static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv, |
| 602 | 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 | 607 | if (IS_GEN2(dev_priv)) |
| 606 | 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, · 4 unmodified lines | ||
| 611 | 613 | else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) |
| 612 | 614 | return ilk_pipe_crc_ctl_reg(source, val); |
| 613 | 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 | 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, · 18 unmodified lines | ||
| 636 | 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 | 642 | if (ret != 0) |
| 641 | 643 | goto out; |
| 642 | 644 | |
| @@ -916,7 +918,7 @@ int intel_pipe_crc_create(struct drm_minor *minor) · 273 unmodified lines | ||
| 916 | 918 | int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, |
| 917 | 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 | 922 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; |
| 921 | 923 | enum intel_display_power_domain power_domain; |
| 922 | 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, · 11 unmodified lines | ||
| 934 | 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 | 940 | if (ret != 0) |
| 939 | 941 | goto out; |
| 940 | 942 | |
| 943 | + pipe_crc->source = source; | |
| 941 | 944 | I915_WRITE(PIPE_CRC_CTL(crtc->index), val); |
| 942 | 945 | POSTING_READ(PIPE_CRC_CTL(crtc->index)); |
| 943 | 946 | |
| @@ -959,3 +962,39 @@ out: · 15 unmodified lines | ||
| 959 | 962 | |
| 960 | 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 | +} | |
| @@ -3825,6 +3825,44 @@ static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg) · 3824 unmodified lines | ||
| 3825 | 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 | 3866 | void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, |
| 3829 | 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, · 10 unmodified lines | ||
| 3841 | 3879 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) |
| 3842 | 3880 | continue; |
| 3843 | 3881 | |
| 3844 | − for_each_plane_id_on_crtc(crtc, plane_id) { | |
| 3845 | − u32 val; | |
| 3846 | − | |
| 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 | − } | |
| 3882 | + for_each_plane_id_on_crtc(crtc, plane_id) | |
| 3883 | + skl_ddb_get_hw_plane_state(dev_priv, pipe, | |
| 3884 | + plane_id, ddb); | |
| 3854 | 3885 | |
| 3855 | 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, · 152 unmodified lines | ||
| 4009 | 4040 | static unsigned int |
| 4010 | 4041 | skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, |
| 4011 | 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 | 4046 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); |
| 4016 | 4047 | uint32_t data_rate; |
| 4017 | 4048 | uint32_t width = 0, height = 0; |
| @@ -4025,9 +4056,9 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, · 7 unmodified lines | ||
| 4025 | 4056 | fb = pstate->fb; |
| 4026 | 4057 | format = fb->format->format; |
| 4027 | 4058 | |
| 4028 | − if (plane->id == PLANE_CURSOR) | |
| 4059 | + if (intel_plane->id == PLANE_CURSOR) | |
| 4029 | 4060 | return 0; |
| 4030 | − if (y && format != DRM_FORMAT_NV12) | |
| 4061 | + if (plane == 1 && format != DRM_FORMAT_NV12) | |
| 4031 | 4062 | return 0; |
| 4032 | 4063 | |
| 4033 | 4064 | /* |
| @@ -4038,19 +4069,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, · 4 unmodified lines | ||
| 4038 | 4069 | width = drm_rect_width(&intel_pstate->base.src) >> 16; |
| 4039 | 4070 | height = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 4040 | 4071 | |
| 4041 | − /* for planar format */ | |
| 4042 | − if (format == DRM_FORMAT_NV12) { | |
| 4043 | − if (y) /* y-plane data rate */ | |
| 4044 | − data_rate = width * height * | |
| 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]; | |
| 4072 | + /* UV plane does 1/2 pixel sub-sampling */ | |
| 4073 | + if (plane == 1 && format == DRM_FORMAT_NV12) { | |
| 4074 | + width /= 2; | |
| 4075 | + height /= 2; | |
| 4052 | 4076 | } |
| 4053 | 4077 | |
| 4078 | + data_rate = width * height * fb->format->cpp[plane]; | |
| 4079 | + | |
| 4054 | 4080 | down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate); |
| 4055 | 4081 | |
| 4056 | 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, · 6 unmodified lines | ||
| 4063 | 4089 | */ |
| 4064 | 4090 | static unsigned int |
| 4065 | 4091 | skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, |
| 4066 | − unsigned *plane_data_rate, | |
| 4067 | − unsigned *plane_y_data_rate) | |
| 4092 | + unsigned int *plane_data_rate, | |
| 4093 | + unsigned int *uv_plane_data_rate) | |
| 4068 | 4094 | { |
| 4069 | 4095 | struct drm_crtc_state *cstate = &intel_cstate->base; |
| 4070 | 4096 | struct drm_atomic_state *state = cstate->state; |
| @@ -4080,17 +4106,17 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, · 9 unmodified lines | ||
| 4080 | 4106 | enum plane_id plane_id = to_intel_plane(plane)->id; |
| 4081 | 4107 | unsigned int rate; |
| 4082 | 4108 | |
| 4083 | − /* packed/uv */ | |
| 4109 | + /* packed/y */ | |
| 4084 | 4110 | rate = skl_plane_relative_data_rate(intel_cstate, |
| 4085 | 4111 | pstate, 0); |
| 4086 | 4112 | plane_data_rate[plane_id] = rate; |
| 4087 | 4113 | |
| 4088 | 4114 | total_data_rate += rate; |
| 4089 | 4115 | |
| 4090 | − /* y-plane */ | |
| 4116 | + /* uv-plane */ | |
| 4091 | 4117 | rate = skl_plane_relative_data_rate(intel_cstate, |
| 4092 | 4118 | pstate, 1); |
| 4093 | − plane_y_data_rate[plane_id] = rate; | |
| 4119 | + uv_plane_data_rate[plane_id] = rate; | |
| 4094 | 4120 | |
| 4095 | 4121 | total_data_rate += rate; |
| 4096 | 4122 | } |
| @@ -4099,8 +4125,7 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, · 2 unmodified lines | ||
| 4099 | 4125 | } |
| 4100 | 4126 | |
| 4101 | 4127 | static uint16_t |
| 4102 | −skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |
| 4103 | − const int y) | |
| 4128 | +skl_ddb_min_alloc(const struct drm_plane_state *pstate, const int plane) | |
| 4104 | 4129 | { |
| 4105 | 4130 | struct drm_framebuffer *fb = pstate->fb; |
| 4106 | 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, · 4 unmodified lines | ||
| 4111 | 4136 | if (WARN_ON(!fb)) |
| 4112 | 4137 | return 0; |
| 4113 | 4138 | |
| 4114 | − /* For packed formats, no y-plane, return 0 */ | |
| 4115 | − if (y && fb->format->format != DRM_FORMAT_NV12) | |
| 4139 | + /* For packed formats, and uv-plane, return 0 */ | |
| 4140 | + if (plane == 1 && fb->format->format != DRM_FORMAT_NV12) | |
| 4116 | 4141 | return 0; |
| 4117 | 4142 | |
| 4118 | 4143 | /* For Non Y-tile return 8-blocks */ |
| @@ -4131,15 +4156,12 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, · 12 unmodified lines | ||
| 4131 | 4156 | src_h = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 4132 | 4157 | |
| 4133 | 4158 | /* Halve UV plane width and height for NV12 */ |
| 4134 | − if (fb->format->format == DRM_FORMAT_NV12 && !y) { | |
| 4159 | + if (plane == 1) { | |
| 4135 | 4160 | src_w /= 2; |
| 4136 | 4161 | src_h /= 2; |
| 4137 | 4162 | } |
| 4138 | 4163 | |
| 4139 | − if (fb->format->format == DRM_FORMAT_NV12 && !y) | |
| 4140 | − plane_bpp = fb->format->cpp[1]; | |
| 4141 | − else | |
| 4142 | − plane_bpp = fb->format->cpp[0]; | |
| 4164 | + plane_bpp = fb->format->cpp[plane]; | |
| 4143 | 4165 | |
| 4144 | 4166 | if (drm_rotation_90_or_270(pstate->rotation)) { |
| 4145 | 4167 | switch (plane_bpp) { |
| @@ -4167,7 +4189,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, · 21 unmodified lines | ||
| 4167 | 4189 | |
| 4168 | 4190 | static void |
| 4169 | 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 | 4194 | const struct drm_plane_state *pstate; |
| 4173 | 4195 | struct drm_plane *plane; |
| @@ -4182,7 +4204,7 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, · 8 unmodified lines | ||
| 4182 | 4204 | continue; |
| 4183 | 4205 | |
| 4184 | 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 | 4210 | minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); |
| @@ -4200,17 +4222,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, · 11 unmodified lines | ||
| 4200 | 4222 | struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; |
| 4201 | 4223 | uint16_t alloc_size, start; |
| 4202 | 4224 | uint16_t minimum[I915_MAX_PLANES] = {}; |
| 4203 | − uint16_t y_minimum[I915_MAX_PLANES] = {}; | |
| 4225 | + uint16_t uv_minimum[I915_MAX_PLANES] = {}; | |
| 4204 | 4226 | unsigned int total_data_rate; |
| 4205 | 4227 | enum plane_id plane_id; |
| 4206 | 4228 | int num_active; |
| 4207 | − unsigned plane_data_rate[I915_MAX_PLANES] = {}; | |
| 4208 | − unsigned plane_y_data_rate[I915_MAX_PLANES] = {}; | |
| 4229 | + unsigned int plane_data_rate[I915_MAX_PLANES] = {}; | |
| 4230 | + unsigned int uv_plane_data_rate[I915_MAX_PLANES] = {}; | |
| 4209 | 4231 | uint16_t total_min_blocks = 0; |
| 4210 | 4232 | |
| 4211 | 4233 | /* Clear the partitioning for disabled planes. */ |
| 4212 | 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 | 4237 | if (WARN_ON(!state)) |
| 4216 | 4238 | return 0; |
| @@ -4225,7 +4247,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, · 8 unmodified lines | ||
| 4225 | 4247 | if (alloc_size == 0) |
| 4226 | 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 | 4253 | * 1. Allocate the mininum required blocks for each active plane |
| @@ -4235,7 +4257,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, · 3 unmodified lines | ||
| 4235 | 4257 | |
| 4236 | 4258 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { |
| 4237 | 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 | 4263 | if (total_min_blocks > alloc_size) { |
| @@ -4257,14 +4279,14 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, · 15 unmodified lines | ||
| 4257 | 4279 | */ |
| 4258 | 4280 | total_data_rate = skl_get_total_relative_data_rate(cstate, |
| 4259 | 4281 | plane_data_rate, |
| 4260 | − plane_y_data_rate); | |
| 4282 | + uv_plane_data_rate); | |
| 4261 | 4283 | if (total_data_rate == 0) |
| 4262 | 4284 | return 0; |
| 4263 | 4285 | |
| 4264 | 4286 | start = alloc->start; |
| 4265 | 4287 | for_each_plane_id_on_crtc(intel_crtc, plane_id) { |
| 4266 | − unsigned int data_rate, y_data_rate; | |
| 4267 | − uint16_t plane_blocks, y_plane_blocks = 0; | |
| 4288 | + unsigned int data_rate, uv_data_rate; | |
| 4289 | + uint16_t plane_blocks, uv_plane_blocks; | |
| 4268 | 4290 | |
| 4269 | 4291 | if (plane_id == PLANE_CURSOR) |
| 4270 | 4292 | continue; |
| @@ -4288,21 +4310,20 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, · 17 unmodified lines | ||
| 4288 | 4310 | |
| 4289 | 4311 | start += plane_blocks; |
| 4290 | 4312 | |
| 4291 | − /* | |
| 4292 | − * allocation for y_plane part of planar format: | |
| 4293 | − */ | |
| 4294 | − y_data_rate = plane_y_data_rate[plane_id]; | |
| 4313 | + /* Allocate DDB for UV plane for planar format/NV12 */ | |
| 4314 | + uv_data_rate = uv_plane_data_rate[plane_id]; | |
| 4295 | 4315 | |
| 4296 | − y_plane_blocks = y_minimum[plane_id]; | |
| 4297 | − y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, | |
| 4298 | − total_data_rate); | |
| 4316 | + uv_plane_blocks = uv_minimum[plane_id]; | |
| 4317 | + uv_plane_blocks += div_u64((uint64_t)alloc_size * uv_data_rate, | |
| 4318 | + total_data_rate); | |
| 4299 | 4319 | |
| 4300 | − if (y_data_rate) { | |
| 4301 | − ddb->y_plane[pipe][plane_id].start = start; | |
| 4302 | − ddb->y_plane[pipe][plane_id].end = start + y_plane_blocks; | |
| 4320 | + if (uv_data_rate) { | |
| 4321 | + ddb->uv_plane[pipe][plane_id].start = start; | |
| 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 | 4329 | return 0; |
| @@ -4398,7 +4419,7 @@ static int · 89 unmodified lines | ||
| 4398 | 4419 | skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, |
| 4399 | 4420 | struct intel_crtc_state *cstate, |
| 4400 | 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 | 4424 | struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); |
| 4404 | 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, · 6 unmodified lines | ||
| 4411 | 4432 | if (!intel_wm_plane_visible(cstate, intel_pstate)) |
| 4412 | 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 | 4441 | wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || |
| 4415 | 4442 | fb->modifier == I915_FORMAT_MOD_Yf_TILED || |
| 4416 | 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, · 1 unmodified line | ||
| 4418 | 4445 | wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; |
| 4419 | 4446 | wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || |
| 4420 | 4447 | fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; |
| 4448 | + wp->is_planar = fb->format->format == DRM_FORMAT_NV12; | |
| 4421 | 4449 | |
| 4422 | 4450 | if (plane->id == PLANE_CURSOR) { |
| 4423 | 4451 | wp->width = intel_pstate->base.crtc_w; |
| @@ -4430,8 +4458,10 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, · 6 unmodified lines | ||
| 4430 | 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] : | |
| 4434 | − fb->format->cpp[0]; | |
| 4461 | + if (plane_id == 1 && wp->is_planar) | |
| 4462 | + wp->width /= 2; | |
| 4463 | + | |
| 4464 | + wp->cpp = fb->format->cpp[plane_id]; | |
| 4435 | 4465 | wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, |
| 4436 | 4466 | intel_pstate); |
| 4437 | 4467 | |
| @@ -4499,9 +4529,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, · 61 unmodified lines | ||
| 4499 | 4529 | uint16_t ddb_allocation, |
| 4500 | 4530 | int level, |
| 4501 | 4531 | const struct skl_wm_params *wp, |
| 4502 | − uint16_t *out_blocks, /* out */ | |
| 4503 | − uint8_t *out_lines, /* out */ | |
| 4504 | − bool *enabled /* out */) | |
| 4532 | + const struct skl_wm_level *result_prev, | |
| 4533 | + struct skl_wm_level *result /* out */) | |
| 4505 | 4534 | { |
| 4506 | 4535 | const struct drm_plane_state *pstate = &intel_pstate->base; |
| 4507 | 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, · 7 unmodified lines | ||
| 4515 | 4544 | |
| 4516 | 4545 | if (latency == 0 || |
| 4517 | 4546 | !intel_wm_plane_visible(cstate, intel_pstate)) { |
| 4518 | − *enabled = false; | |
| 4547 | + result->plane_en = false; | |
| 4519 | 4548 | return 0; |
| 4520 | 4549 | } |
| 4521 | 4550 | |
| @@ -4568,6 +4597,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, · 46 unmodified lines | ||
| 4568 | 4597 | } else { |
| 4569 | 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 | 4611 | if (INTEL_GEN(dev_priv) >= 11) { |
| @@ -4596,7 +4634,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, · 22 unmodified lines | ||
| 4596 | 4634 | if ((level > 0 && res_lines > 31) || |
| 4597 | 4635 | res_blocks >= ddb_allocation || |
| 4598 | 4636 | min_disp_buf_needed >= ddb_allocation) { |
| 4599 | − *enabled = false; | |
| 4637 | + result->plane_en = false; | |
| 4600 | 4638 | |
| 4601 | 4639 | /* |
| 4602 | 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, · 12 unmodified lines | ||
| 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 | 4667 | /* The number of lines are ignored for the level 0 watermark. */ |
| 4619 | − *out_lines = level ? res_lines : 0; | |
| 4620 | − *out_blocks = res_blocks; | |
| 4621 | − *enabled = true; | |
| 4668 | + result->plane_res_b = res_blocks; | |
| 4669 | + result->plane_res_l = res_lines; | |
| 4670 | + result->plane_en = true; | |
| 4622 | 4671 | |
| 4623 | 4672 | return 0; |
| 4624 | 4673 | } |
| @@ -4629,7 +4678,8 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 4629 | 4678 | struct intel_crtc_state *cstate, |
| 4630 | 4679 | const struct intel_plane_state *intel_pstate, |
| 4631 | 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 | 4684 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); |
| 4635 | 4685 | struct drm_plane *plane = intel_pstate->base.plane; |
| @@ -4637,15 +4687,26 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, · 1 unmodified line | ||
| 4637 | 4687 | uint16_t ddb_blocks; |
| 4638 | 4688 | enum pipe pipe = intel_crtc->pipe; |
| 4639 | 4689 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 4690 | + enum plane_id intel_plane_id = intel_plane->id; | |
| 4640 | 4691 | int ret; |
| 4641 | 4692 | |
| 4642 | 4693 | if (WARN_ON(!intel_pstate->base.fb)) |
| 4643 | 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 | 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 | 4711 | ret = skl_compute_plane_wm(dev_priv, |
| 4651 | 4712 | cstate, |
| @@ -4653,13 +4714,15 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, · 1 unmodified line | ||
| 4653 | 4714 | ddb_blocks, |
| 4654 | 4715 | level, |
| 4655 | 4716 | wm_params, |
| 4656 | − &result->plane_res_b, | |
| 4657 | − &result->plane_res_l, | |
| 4658 | − &result->plane_en); | |
| 4717 | + result_prev, | |
| 4718 | + result); | |
| 4659 | 4719 | if (ret) |
| 4660 | 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 | 4726 | return 0; |
| 4664 | 4727 | } |
| 4665 | 4728 | |
| @@ -4769,20 +4832,39 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, · 103 unmodified lines | ||
| 4769 | 4832 | |
| 4770 | 4833 | wm = &pipe_wm->planes[plane_id]; |
| 4771 | 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 | 4836 | ret = skl_compute_plane_wm_params(dev_priv, cstate, |
| 4775 | − intel_pstate, &wm_params); | |
| 4837 | + intel_pstate, &wm_params, 0); | |
| 4776 | 4838 | if (ret) |
| 4777 | 4839 | return ret; |
| 4778 | 4840 | |
| 4779 | 4841 | ret = skl_compute_wm_levels(dev_priv, ddb, cstate, |
| 4780 | − intel_pstate, &wm_params, wm); | |
| 4842 | + intel_pstate, &wm_params, wm, 0); | |
| 4781 | 4843 | if (ret) |
| 4782 | 4844 | return ret; |
| 4845 | + | |
| 4783 | 4846 | skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], |
| 4784 | 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 | 4868 | pipe_wm->linetime = skl_compute_linetime_wm(cstate); |
| 4787 | 4869 | |
| 4788 | 4870 | return 0; |
| @@ -4833,10 +4915,21 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, · 44 unmodified lines | ||
| 4833 | 4915 | |
| 4834 | 4916 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), |
| 4835 | 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 | 4925 | skl_ddb_entry_write(dev_priv, |
| 4838 | 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 | 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) · 101 unmodified lines | ||
| 4944 | 5037 | struct drm_plane *plane; |
| 4945 | 5038 | enum pipe pipe = intel_crtc->pipe; |
| 4946 | 5039 | |
| 4947 | − WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); | |
| 4948 | − | |
| 4949 | 5040 | drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { |
| 4950 | 5041 | enum plane_id plane_id = to_intel_plane(plane)->id; |
| 4951 | 5042 | |
| 4952 | 5043 | if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id], |
| 4953 | 5044 | &new_ddb->plane[pipe][plane_id]) && |
| 4954 | − skl_ddb_entry_equal(&cur_ddb->y_plane[pipe][plane_id], | |
| 4955 | − &new_ddb->y_plane[pipe][plane_id])) | |
| 5045 | + skl_ddb_entry_equal(&cur_ddb->uv_plane[pipe][plane_id], | |
| 5046 | + &new_ddb->uv_plane[pipe][plane_id])) | |
| 4956 | 5047 | continue; |
| 4957 | 5048 | |
| 4958 | 5049 | plane_state = drm_atomic_get_plane_state(state, plane); |
| @@ -4966,69 +5057,16 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) · 7 unmodified lines | ||
| 4966 | 5057 | static int |
| 4967 | 5058 | skl_compute_ddb(struct drm_atomic_state *state) |
| 4968 | 5059 | { |
| 4969 | − struct drm_device *dev = state->dev; | |
| 4970 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5060 | + const struct drm_i915_private *dev_priv = to_i915(state->dev); | |
| 4971 | 5061 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); |
| 4972 | − struct intel_crtc *intel_crtc; | |
| 4973 | 5062 | struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb; |
| 4974 | − uint32_t realloc_pipes = pipes_modified(state); | |
| 4975 | − int ret; | |
| 4976 | − | |
| 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 | − } | |
| 5063 | + struct intel_crtc *crtc; | |
| 5064 | + struct intel_crtc_state *cstate; | |
| 5065 | + int ret, i; | |
| 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 | 5067 | memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); |
| 5024 | 5068 | |
| 5025 | − for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { | |
| 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 | − | |
| 5069 | + for_each_new_intel_crtc_in_state(intel_state, crtc, cstate, i) { | |
| 5032 | 5070 | ret = skl_allocate_pipe_ddb(cstate, ddb); |
| 5033 | 5071 | if (ret) |
| 5034 | 5072 | return ret; |
| @@ -5042,12 +5080,12 @@ skl_compute_ddb(struct drm_atomic_state *state) · 7 unmodified lines | ||
| 5042 | 5080 | } |
| 5043 | 5081 | |
| 5044 | 5082 | static void |
| 5045 | −skl_copy_wm_for_pipe(struct skl_wm_values *dst, | |
| 5046 | − struct skl_wm_values *src, | |
| 5047 | − enum pipe pipe) | |
| 5083 | +skl_copy_ddb_for_pipe(struct skl_ddb_values *dst, | |
| 5084 | + struct skl_ddb_values *src, | |
| 5085 | + enum pipe pipe) | |
| 5048 | 5086 | { |
| 5049 | − memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], | |
| 5050 | − sizeof(dst->ddb.y_plane[pipe])); | |
| 5087 | + memcpy(dst->ddb.uv_plane[pipe], src->ddb.uv_plane[pipe], | |
| 5088 | + sizeof(dst->ddb.uv_plane[pipe])); | |
| 5051 | 5089 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], |
| 5052 | 5090 | sizeof(dst->ddb.plane[pipe])); |
| 5053 | 5091 | } |
| @@ -5090,23 +5128,23 @@ skl_print_wm_changes(const struct drm_atomic_state *state) · 36 unmodified lines | ||
| 5090 | 5128 | } |
| 5091 | 5129 | |
| 5092 | 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 | 5133 | struct drm_device *dev = state->dev; |
| 5100 | − struct skl_pipe_wm *pipe_wm; | |
| 5101 | − bool changed = false; | |
| 5134 | + const struct drm_i915_private *dev_priv = to_i915(dev); | |
| 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 | 5140 | int ret, i; |
| 5103 | 5141 | |
| 5104 | 5142 | /* |
| 5105 | 5143 | * When we distrust bios wm we always need to recompute to set the |
| 5106 | 5144 | * expected DDB allocations for each CRTC. |
| 5107 | 5145 | */ |
| 5108 | − if (to_i915(dev)->wm.distrust_bios_wm) | |
| 5109 | − changed = true; | |
| 5146 | + if (dev_priv->wm.distrust_bios_wm) | |
| 5147 | + (*changed) = true; | |
| 5110 | 5148 | |
| 5111 | 5149 | /* |
| 5112 | 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) · 4 unmodified lines | ||
| 5117 | 5155 | * hold _all_ CRTC state mutexes. |
| 5118 | 5156 | */ |
| 5119 | 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 | 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 | 5231 | /* Clear all dirty flags */ |
| 5126 | 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 | 5238 | ret = skl_compute_ddb(state); |
| 5129 | 5239 | if (ret) |
| 5130 | 5240 | return ret; |
| @@ -5197,8 +5307,8 @@ static void skl_initial_wm(struct intel_atomic_state *state, · 66 unmodified lines | ||
| 5197 | 5307 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); |
| 5198 | 5308 | struct drm_device *dev = intel_crtc->base.dev; |
| 5199 | 5309 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 5200 | − struct skl_wm_values *results = &state->wm_results; | |
| 5201 | − struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw; | |
| 5310 | + struct skl_ddb_values *results = &state->wm_results; | |
| 5311 | + struct skl_ddb_values *hw_vals = &dev_priv->wm.skl_hw; | |
| 5202 | 5312 | enum pipe pipe = intel_crtc->pipe; |
| 5203 | 5313 | |
| 5204 | 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, · 4 unmodified lines | ||
| 5209 | 5319 | if (cstate->base.active_changed) |
| 5210 | 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 | 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, · 125 unmodified lines | ||
| 5341 | 5451 | void skl_wm_get_hw_state(struct drm_device *dev) |
| 5342 | 5452 | { |
| 5343 | 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 | 5455 | struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; |
| 5346 | 5456 | struct drm_crtc *crtc; |
| 5347 | 5457 | struct intel_crtc *intel_crtc; |
| @@ -6572,7 +6682,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) · 1224 unmodified lines | ||
| 6572 | 6682 | |
| 6573 | 6683 | rps->efficient_freq = rps->rp1_freq; |
| 6574 | 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 | 6686 | u32 ddcc_status = 0; |
| 6577 | 6687 | |
| 6578 | 6688 | if (sandybridge_pcode_read(dev_priv, |
| @@ -6585,7 +6695,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) · 6 unmodified lines | ||
| 6585 | 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 | 6699 | /* Store the frequency values in 16.66 MHZ units, which is |
| 6590 | 6700 | * the natural hardware unit for SKL |
| 6591 | 6701 | */ |
| @@ -6890,15 +7000,18 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) · 298 unmodified lines | ||
| 6890 | 7000 | static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) |
| 6891 | 7001 | { |
| 6892 | 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 | 7005 | unsigned int gpu_freq; |
| 6895 | 7006 | unsigned int max_ia_freq, min_ring_freq; |
| 6896 | 7007 | unsigned int max_gpu_freq, min_gpu_freq; |
| 6897 | − int scaling_factor = 180; | |
| 6898 | 7008 | struct cpufreq_policy *policy; |
| 6899 | 7009 | |
| 6900 | 7010 | WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); |
| 6901 | 7011 | |
| 7012 | + if (rps->max_freq <= rps->min_freq) | |
| 7013 | + return; | |
| 7014 | + | |
| 6902 | 7015 | policy = cpufreq_cpu_get(0); |
| 6903 | 7016 | if (policy) { |
| 6904 | 7017 | max_ia_freq = policy->cpuinfo.max_freq; |
| @@ -6918,13 +7031,12 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) · 13 unmodified lines | ||
| 6918 | 7031 | /* convert DDR frequency from units of 266.6MHz to bandwidth */ |
| 6919 | 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 | 7037 | /* Convert GT frequency to 50 HZ units */ |
| 6923 | − min_gpu_freq = rps->min_freq / GEN9_FREQ_SCALER; | |
| 6924 | − max_gpu_freq = rps->max_freq / GEN9_FREQ_SCALER; | |
| 6925 | − } else { | |
| 6926 | − min_gpu_freq = rps->min_freq; | |
| 6927 | − max_gpu_freq = rps->max_freq; | |
| 7038 | + min_gpu_freq /= GEN9_FREQ_SCALER; | |
| 7039 | + max_gpu_freq /= GEN9_FREQ_SCALER; | |
| 6928 | 7040 | } |
| 6929 | 7041 | |
| 6930 | 7042 | /* |
| @@ -6933,10 +7045,10 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) · 2 unmodified lines | ||
| 6933 | 7045 | * the PCU should use as a reference to determine the ring frequency. |
| 6934 | 7046 | */ |
| 6935 | 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 | 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 | 7053 | * ring_freq = 2 * GT. ring_freq is in 100MHz units |
| 6942 | 7054 | * No floor required for ring frequency on SKL. |
| @@ -8026,10 +8138,10 @@ void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv) · 1083 unmodified lines | ||
| 8026 | 8138 | dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */ |
| 8027 | 8139 | intel_disable_gt_powersave(dev_priv); |
| 8028 | 8140 | |
| 8029 | − if (INTEL_GEN(dev_priv) < 11) | |
| 8030 | − gen6_reset_rps_interrupts(dev_priv); | |
| 8141 | + if (INTEL_GEN(dev_priv) >= 11) | |
| 8142 | + gen11_reset_rps_interrupts(dev_priv); | |
| 8031 | 8143 | else |
| 8032 | − WARN_ON_ONCE(1); | |
| 8144 | + gen6_reset_rps_interrupts(dev_priv); | |
| 8033 | 8145 | } |
| 8034 | 8146 | |
| 8035 | 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) · 106 unmodified lines | ||
| 8142 | 8254 | cherryview_enable_rps(dev_priv); |
| 8143 | 8255 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 8144 | 8256 | valleyview_enable_rps(dev_priv); |
| 8145 | − } else if (WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11)) { | |
| 8146 | − /* TODO */ | |
| 8147 | 8257 | } else if (INTEL_GEN(dev_priv) >= 9) { |
| 8148 | 8258 | gen9_enable_rps(dev_priv); |
| 8149 | 8259 | } else if (IS_BROADWELL(dev_priv)) { |
| @@ -93,7 +93,7 @@ static void psr_aux_io_power_put(struct intel_dp *intel_dp) · 92 unmodified lines | ||
| 93 | 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 | 98 | uint8_t psr_caps = 0; |
| 99 | 99 | |
| @@ -122,6 +122,18 @@ static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp) · 22 unmodified lines | ||
| 122 | 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 | 137 | void intel_psr_init_dpcd(struct intel_dp *intel_dp) |
| 126 | 138 | { |
| 127 | 139 | struct drm_i915_private *dev_priv = |
| @@ -130,33 +142,36 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) · 2 unmodified lines | ||
| 130 | 142 | drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, |
| 131 | 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 | 146 | dev_priv->psr.sink_support = true; |
| 135 | 147 | DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); |
| 136 | 148 | } |
| 137 | 149 | |
| 138 | 150 | if (INTEL_GEN(dev_priv) >= 9 && |
| 139 | − (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { | |
| 140 | − uint8_t frame_sync_cap; | |
| 151 | + (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) { | |
| 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; | |
| 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); | |
| 168 | + if (dev_priv->psr.sink_psr2_support) { | |
| 156 | 169 | dev_priv->psr.colorimetry_support = |
| 157 | 170 | intel_dp_get_colorimetry_status(intel_dp); |
| 158 | 171 | dev_priv->psr.alpm = |
| 159 | 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, · 30 unmodified lines | ||
| 193 | 208 | struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); |
| 194 | 209 | struct edp_vsc_psr psr_vsc; |
| 195 | 210 | |
| 196 | − if (dev_priv->psr.psr2_support) { | |
| 211 | + if (dev_priv->psr.psr2_enabled) { | |
| 197 | 212 | /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ |
| 198 | 213 | memset(&psr_vsc, 0, sizeof(psr_vsc)); |
| 199 | 214 | psr_vsc.sdp_header.HB0 = 0; |
| 200 | 215 | psr_vsc.sdp_header.HB1 = 0x7; |
| 201 | − if (dev_priv->psr.colorimetry_support && | |
| 202 | − dev_priv->psr.y_cord_support) { | |
| 216 | + if (dev_priv->psr.colorimetry_support) { | |
| 203 | 217 | psr_vsc.sdp_header.HB2 = 0x5; |
| 204 | 218 | psr_vsc.sdp_header.HB3 = 0x13; |
| 205 | − } else if (dev_priv->psr.y_cord_support) { | |
| 219 | + } else { | |
| 206 | 220 | psr_vsc.sdp_header.HB2 = 0x4; |
| 207 | 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 | 223 | } else { |
| 213 | 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) · 14 unmodified lines | ||
| 228 | 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, | |
| 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) | |
| 242 | +static void hsw_psr_setup_aux(struct intel_dp *intel_dp) | |
| 250 | 243 | { |
| 251 | 244 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 252 | − struct drm_device *dev = dig_port->base.base.dev; | |
| 253 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 254 | − uint32_t aux_clock_divider; | |
| 255 | − i915_reg_t aux_ctl_reg; | |
| 245 | + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); | |
| 246 | + u32 aux_clock_divider, aux_ctl; | |
| 247 | + int i; | |
| 256 | 248 | static const uint8_t aux_msg[] = { |
| 257 | 249 | [0] = DP_AUX_NATIVE_WRITE << 4, |
| 258 | 250 | [1] = DP_SET_POWER >> 8, |
| @@ -260,41 +252,47 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) · 1 unmodified line | ||
| 260 | 252 | [3] = 1 - 1, |
| 261 | 253 | [4] = DP_SET_POWER_D0, |
| 262 | 254 | }; |
| 263 | − enum port port = dig_port->base.port; | |
| 264 | − u32 aux_ctl; | |
| 265 | − int i; | |
| 255 | + u32 psr_aux_mask = EDP_PSR_AUX_CTL_TIME_OUT_MASK | | |
| 256 | + EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK | | |
| 257 | + EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK | | |
| 258 | + EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK; | |
| 266 | 259 | |
| 267 | 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 | 265 | aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); |
| 270 | 266 | |
| 271 | − /* Enable AUX frame sync at sink */ | |
| 272 | − if (dev_priv->psr.aux_frame_sync) | |
| 273 | − drm_dp_dpcd_writeb(&intel_dp->aux, | |
| 274 | − DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, | |
| 275 | − DP_AUX_FRAME_SYNC_ENABLE); | |
| 267 | + /* Start with bits set for DDI_AUX_CTL register */ | |
| 268 | + aux_ctl = intel_dp->get_aux_send_ctl(intel_dp, 0, sizeof(aux_msg), | |
| 269 | + aux_clock_divider); | |
| 270 | + | |
| 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 | 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 | 285 | drm_dp_dpcd_writeb(&intel_dp->aux, |
| 279 | 286 | DP_RECEIVER_ALPM_CONFIG, |
| 280 | 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 */ | |
| 291 | − for (i = 0; i < sizeof(aux_msg); i += 4) | |
| 292 | − I915_WRITE(psr_aux_data_reg(dev_priv, port, i >> 2), | |
| 293 | − intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i)); | |
| 289 | + if (dev_priv->psr.psr2_enabled) | |
| 290 | + dpcd_val |= DP_PSR_ENABLE_PSR2; | |
| 291 | + if (dev_priv->psr.link_standby) | |
| 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), | |
| 296 | − aux_clock_divider); | |
| 297 | − I915_WRITE(aux_ctl_reg, aux_ctl); | |
| 295 | + drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); | |
| 298 | 296 | } |
| 299 | 297 | |
| 300 | 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) · 95 unmodified lines | ||
| 396 | 394 | * with the 5 or 6 idle patterns. |
| 397 | 395 | */ |
| 398 | 396 | uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); |
| 399 | − uint32_t val; | |
| 400 | − uint8_t sink_latency; | |
| 401 | − | |
| 402 | − val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; | |
| 397 | + u32 val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; | |
| 403 | 398 | |
| 404 | 399 | /* FIXME: selective update is probably totally broken because it doesn't |
| 405 | 400 | * mesh at all with our frontbuffer tracking. And the hw alone isn't |
| 406 | 401 | * good enough. */ |
| 407 | − val |= EDP_PSR2_ENABLE | | |
| 408 | − EDP_SU_TRACK_ENABLE; | |
| 409 | − | |
| 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; | |
| 402 | + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; | |
| 403 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { | |
| 404 | + val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; | |
| 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 | 409 | if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) |
| 420 | 410 | val |= EDP_PSR2_TP2_TIME_2500; |
| @@ -440,7 +430,7 @@ static void hsw_psr_activate(struct intel_dp *intel_dp) · 19 unmodified lines | ||
| 440 | 430 | */ |
| 441 | 431 | |
| 442 | 432 | /* psr1 and psr2 are mutually exclusive.*/ |
| 443 | − if (dev_priv->psr.psr2_support) | |
| 433 | + if (dev_priv->psr.psr2_enabled) | |
| 444 | 434 | hsw_activate_psr2(intel_dp); |
| 445 | 435 | else |
| 446 | 436 | hsw_activate_psr1(intel_dp); |
| @@ -460,7 +450,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, · 13 unmodified lines | ||
| 460 | 450 | * dynamically during PSR enable, and extracted from sink |
| 461 | 451 | * caps during eDP detection. |
| 462 | 452 | */ |
| 463 | − if (!dev_priv->psr.psr2_support) | |
| 453 | + if (!dev_priv->psr.sink_psr2_support) | |
| 464 | 454 | return false; |
| 465 | 455 | |
| 466 | 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, · 11 unmodified lines | ||
| 478 | 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 | 471 | return true; |
| 491 | 472 | } |
| 492 | 473 | |
| @@ -568,7 +549,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) · 75 unmodified lines | ||
| 568 | 549 | struct drm_device *dev = intel_dig_port->base.base.dev; |
| 569 | 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 | 553 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); |
| 573 | 554 | else |
| 574 | 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, · 11 unmodified lines | ||
| 586 | 567 | struct drm_device *dev = dig_port->base.base.dev; |
| 587 | 568 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 588 | 569 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
| 589 | − u32 chicken; | |
| 590 | 570 | |
| 591 | 571 | psr_aux_io_power_get(intel_dp); |
| 592 | 572 | |
| 593 | − if (dev_priv->psr.psr2_support) { | |
| 594 | − chicken = PSR2_VSC_ENABLE_PROG_HEADER; | |
| 595 | − if (dev_priv->psr.y_cord_support) | |
| 596 | − chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; | |
| 573 | + /* Only HSW and BDW have PSR AUX registers that need to be setup. SKL+ | |
| 574 | + * use hardcoded values PSR AUX transactions | |
| 575 | + */ | |
| 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 | 588 | I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); |
| 598 | 589 | |
| 599 | 590 | I915_WRITE(EDP_PSR_DEBUG, |
| @@ -644,7 +635,7 @@ void intel_psr_enable(struct intel_dp *intel_dp, · 44 unmodified lines | ||
| 644 | 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 | 639 | dev_priv->psr.busy_frontbuffer_bits = 0; |
| 649 | 640 | |
| 650 | 641 | dev_priv->psr.setup_vsc(intel_dp, crtc_state); |
| @@ -714,12 +705,7 @@ static void hsw_psr_disable(struct intel_dp *intel_dp, · 63 unmodified lines | ||
| 714 | 705 | i915_reg_t psr_status; |
| 715 | 706 | u32 psr_status_mask; |
| 716 | 707 | |
| 717 | − if (dev_priv->psr.aux_frame_sync) | |
| 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) { | |
| 708 | + if (dev_priv->psr.psr2_enabled) { | |
| 723 | 709 | psr_status = EDP_PSR2_STATUS; |
| 724 | 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, · 17 unmodified lines | ||
| 743 | 729 | |
| 744 | 730 | dev_priv->psr.active = false; |
| 745 | 731 | } else { |
| 746 | − if (dev_priv->psr.psr2_support) | |
| 732 | + if (dev_priv->psr.psr2_enabled) | |
| 747 | 733 | WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); |
| 748 | 734 | else |
| 749 | 735 | WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); |
| @@ -789,53 +775,59 @@ void intel_psr_disable(struct intel_dp *intel_dp, · 39 unmodified lines | ||
| 789 | 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 = | |
| 795 | − container_of(work, typeof(*dev_priv), psr.work.work); | |
| 796 | − struct intel_dp *intel_dp = dev_priv->psr.enabled; | |
| 797 | − struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; | |
| 798 | − enum pipe pipe = to_intel_crtc(crtc)->pipe; | |
| 780 | + struct intel_dp *intel_dp; | |
| 781 | + i915_reg_t reg; | |
| 782 | + u32 mask; | |
| 783 | + int err; | |
| 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 | 789 | if (HAS_DDI(dev_priv)) { |
| 806 | − if (dev_priv->psr.psr2_support) { | |
| 807 | − if (intel_wait_for_register(dev_priv, | |
| 808 | − EDP_PSR2_STATUS, | |
| 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 | − } | |
| 790 | + if (dev_priv->psr.psr2_enabled) { | |
| 791 | + reg = EDP_PSR2_STATUS; | |
| 792 | + mask = EDP_PSR2_STATUS_STATE_MASK; | |
| 815 | 793 | } else { |
| 816 | − if (intel_wait_for_register(dev_priv, | |
| 817 | − EDP_PSR_STATUS, | |
| 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 | − } | |
| 794 | + reg = EDP_PSR_STATUS; | |
| 795 | + mask = EDP_PSR_STATUS_STATE_MASK; | |
| 824 | 796 | } |
| 825 | 797 | } else { |
| 826 | − if (intel_wait_for_register(dev_priv, | |
| 827 | − VLV_PSRSTAT(pipe), | |
| 828 | − VLV_EDP_PSR_IN_TRANS, | |
| 829 | − 0, | |
| 830 | − 1)) { | |
| 831 | − DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); | |
| 832 | − return; | |
| 833 | − } | |
| 798 | + struct drm_crtc *crtc = | |
| 799 | + dp_to_dig_port(intel_dp)->base.base.crtc; | |
| 800 | + enum pipe pipe = to_intel_crtc(crtc)->pipe; | |
| 801 | + | |
| 802 | + reg = VLV_PSRSTAT(pipe); | |
| 803 | + mask = VLV_EDP_PSR_IN_TRANS; | |
| 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 | 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 | 831 | goto unlock; |
| 840 | 832 | |
| 841 | 833 | /* |
| @@ -846,7 +838,7 @@ static void intel_psr_work(struct work_struct *work) · 4 unmodified lines | ||
| 846 | 838 | if (dev_priv->psr.busy_frontbuffer_bits) |
| 847 | 839 | goto unlock; |
| 848 | 840 | |
| 849 | − intel_psr_activate(intel_dp); | |
| 841 | + intel_psr_activate(dev_priv->psr.enabled); | |
| 850 | 842 | unlock: |
| 851 | 843 | mutex_unlock(&dev_priv->psr.lock); |
| 852 | 844 | } |
| @@ -862,11 +854,7 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 862 | 854 | return; |
| 863 | 855 | |
| 864 | 856 | if (HAS_DDI(dev_priv)) { |
| 865 | − if (dev_priv->psr.aux_frame_sync) | |
| 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) { | |
| 857 | + if (dev_priv->psr.psr2_enabled) { | |
| 870 | 858 | val = I915_READ(EDP_PSR2_CTL); |
| 871 | 859 | WARN_ON(!(val & EDP_PSR2_ENABLE)); |
| 872 | 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, · 84 unmodified lines | ||
| 957 | 945 | * intel_psr_invalidate - Invalidade PSR |
| 958 | 946 | * @dev_priv: i915 device |
| 959 | 947 | * @frontbuffer_bits: frontbuffer plane tracking bits |
| 948 | + * @origin: which operation caused the invalidate | |
| 960 | 949 | * |
| 961 | 950 | * Since the hardware frontbuffer tracking has gaps we need to integrate |
| 962 | 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, · 3 unmodified lines | ||
| 966 | 955 | * Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits." |
| 967 | 956 | */ |
| 968 | 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 | 960 | struct drm_crtc *crtc; |
| 972 | 961 | enum pipe pipe; |
| @@ -974,6 +963,9 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, · 1 unmodified line | ||
| 974 | 963 | if (!CAN_PSR(dev_priv)) |
| 975 | 964 | return; |
| 976 | 965 | |
| 966 | + if (dev_priv->psr.has_hw_tracking && origin == ORIGIN_FLIP) | |
| 967 | + return; | |
| 968 | + | |
| 977 | 969 | mutex_lock(&dev_priv->psr.lock); |
| 978 | 970 | if (!dev_priv->psr.enabled) { |
| 979 | 971 | mutex_unlock(&dev_priv->psr.lock); |
| @@ -1014,6 +1006,9 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, · 34 unmodified lines | ||
| 1014 | 1006 | if (!CAN_PSR(dev_priv)) |
| 1015 | 1007 | return; |
| 1016 | 1008 | |
| 1009 | + if (dev_priv->psr.has_hw_tracking && origin == ORIGIN_FLIP) | |
| 1010 | + return; | |
| 1011 | + | |
| 1017 | 1012 | mutex_lock(&dev_priv->psr.lock); |
| 1018 | 1013 | if (!dev_priv->psr.enabled) { |
| 1019 | 1014 | mutex_unlock(&dev_priv->psr.lock); |
| @@ -1027,8 +1022,23 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, · 7 unmodified lines | ||
| 1027 | 1022 | dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; |
| 1028 | 1023 | |
| 1029 | 1024 | /* By definition flush = invalidate + flush */ |
| 1030 | − if (frontbuffer_bits) | |
| 1031 | − intel_psr_exit(dev_priv); | |
| 1025 | + if (frontbuffer_bits) { | |
| 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 | 1043 | if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) |
| 1034 | 1044 | if (!work_busy(&dev_priv->psr.work.work)) |
| @@ -1090,6 +1100,7 @@ void intel_psr_init(struct drm_i915_private *dev_priv) · 55 unmodified lines | ||
| 1090 | 1100 | dev_priv->psr.activate = vlv_psr_activate; |
| 1091 | 1101 | dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; |
| 1092 | 1102 | } else { |
| 1103 | + dev_priv->psr.has_hw_tracking = true; | |
| 1093 | 1104 | dev_priv->psr.enable_source = hsw_psr_enable_source; |
| 1094 | 1105 | dev_priv->psr.disable_source = hsw_psr_disable; |
| 1095 | 1106 | dev_priv->psr.enable_sink = hsw_psr_enable_sink; |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | #include "i915_gem_render_state.h" |
| 37 | 37 | #include "i915_trace.h" |
| 38 | 38 | #include "intel_drv.h" |
| 39 | +#include "intel_workarounds.h" | |
| 39 | 40 | |
| 40 | 41 | /* Rough estimate of the typical request size, performing a flush, |
| 41 | 42 | * set-context and then emitting the batch. |
| @@ -599,7 +600,7 @@ static int intel_rcs_ctx_init(struct i915_request *rq) · 557 unmodified lines | ||
| 599 | 600 | { |
| 600 | 601 | int ret; |
| 601 | 602 | |
| 602 | − ret = intel_ring_workarounds_emit(rq); | |
| 603 | + ret = intel_ctx_workarounds_emit(rq); | |
| 603 | 604 | if (ret != 0) |
| 604 | 605 | return ret; |
| 605 | 606 | |
| @@ -617,6 +618,10 @@ static int init_render_ring(struct intel_engine_cs *engine) · 11 unmodified lines | ||
| 617 | 618 | if (ret) |
| 618 | 619 | return ret; |
| 619 | 620 | |
| 621 | + ret = intel_whitelist_workarounds_apply(engine); | |
| 622 | + if (ret) | |
| 623 | + return ret; | |
| 624 | + | |
| 620 | 625 | /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ |
| 621 | 626 | if (IS_GEN(dev_priv, 4, 6)) |
| 622 | 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) · 35 unmodified lines | ||
| 658 | 663 | if (INTEL_GEN(dev_priv) >= 6) |
| 659 | 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 | 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) · 928 unmodified lines | ||
| 1593 | 1598 | if (intel_ring_update_space(ring) >= bytes) |
| 1594 | 1599 | return 0; |
| 1595 | 1600 | |
| 1601 | + GEM_BUG_ON(list_empty(&ring->request_list)); | |
| 1596 | 1602 | list_for_each_entry(target, &ring->request_list, ring_link) { |
| 1597 | 1603 | /* Would completion of this request free enough space? */ |
| 1598 | 1604 | if (bytes <= __intel_ring_space(target->postfix, |
| @@ -1692,17 +1698,18 @@ u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords) · 93 unmodified lines | ||
| 1692 | 1698 | need_wrap &= ~1; |
| 1693 | 1699 | GEM_BUG_ON(need_wrap > ring->space); |
| 1694 | 1700 | GEM_BUG_ON(ring->emit + need_wrap > ring->size); |
| 1701 | + GEM_BUG_ON(!IS_ALIGNED(need_wrap, sizeof(u64))); | |
| 1695 | 1702 | |
| 1696 | 1703 | /* Fill the tail with MI_NOOP */ |
| 1697 | − memset(ring->vaddr + ring->emit, 0, need_wrap); | |
| 1698 | − ring->emit = 0; | |
| 1704 | + memset64(ring->vaddr + ring->emit, 0, need_wrap / sizeof(u64)); | |
| 1699 | 1705 | ring->space -= need_wrap; |
| 1706 | + ring->emit = 0; | |
| 1700 | 1707 | } |
| 1701 | 1708 | |
| 1702 | 1709 | GEM_BUG_ON(ring->emit > ring->size - bytes); |
| 1703 | 1710 | GEM_BUG_ON(ring->space < bytes); |
| 1704 | 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 | 1713 | ring->emit += bytes; |
| 1707 | 1714 | ring->space -= bytes; |
| 1708 | 1715 | |
| @@ -1943,8 +1950,6 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, · 234 unmodified lines | ||
| 1943 | 1950 | static void intel_ring_init_irq(struct drm_i915_private *dev_priv, |
| 1944 | 1951 | struct intel_engine_cs *engine) |
| 1945 | 1952 | { |
| 1946 | − engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; | |
| 1947 | − | |
| 1948 | 1953 | if (INTEL_GEN(dev_priv) >= 6) { |
| 1949 | 1954 | engine->irq_enable = gen6_irq_enable; |
| 1950 | 1955 | engine->irq_disable = gen6_irq_disable; |
| @@ -2029,6 +2034,8 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) · 78 unmodified lines | ||
| 2029 | 2034 | if (HAS_L3_DPF(dev_priv)) |
| 2030 | 2035 | engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; |
| 2031 | 2036 | |
| 2037 | + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; | |
| 2038 | + | |
| 2032 | 2039 | if (INTEL_GEN(dev_priv) >= 6) { |
| 2033 | 2040 | engine->init_context = intel_rcs_ctx_init; |
| 2034 | 2041 | engine->emit_flush = gen7_render_ring_flush; |
| @@ -2079,7 +2086,6 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) · 44 unmodified lines | ||
| 2079 | 2086 | engine->emit_flush = gen6_bsd_ring_flush; |
| 2080 | 2087 | engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; |
| 2081 | 2088 | } else { |
| 2082 | − engine->mmio_base = BSD_RING_BASE; | |
| 2083 | 2089 | engine->emit_flush = bsd_ring_flush; |
| 2084 | 2090 | if (IS_GEN5(dev_priv)) |
| 2085 | 2091 | engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; |
| @@ -7,9 +7,11 @@ · 6 unmodified lines | ||
| 7 | 7 | #include "i915_gem_batch_pool.h" |
| 8 | 8 | #include "i915_gem_timeline.h" |
| 9 | 9 | |
| 10 | +#include "i915_reg.h" | |
| 10 | 11 | #include "i915_pmu.h" |
| 11 | 12 | #include "i915_request.h" |
| 12 | 13 | #include "i915_selftest.h" |
| 14 | +#include "intel_gpu_commands.h" | |
| 13 | 15 | |
| 14 | 16 | struct drm_printer; |
| 15 | 17 | |
| @@ -84,7 +86,7 @@ hangcheck_action_to_str(const enum intel_engine_hangcheck_action a) · 68 unmodified lines | ||
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | #define I915_MAX_SLICES 3 |
| 87 | −#define I915_MAX_SUBSLICES 3 | |
| 89 | +#define I915_MAX_SUBSLICES 8 | |
| 88 | 90 | |
| 89 | 91 | #define instdone_slice_mask(dev_priv__) \ |
| 90 | 92 | (INTEL_GEN(dev_priv__) == 7 ? \ |
| @@ -330,7 +332,6 @@ struct intel_engine_cs { · 239 unmodified lines | ||
| 330 | 332 | u8 instance; |
| 331 | 333 | u32 context_size; |
| 332 | 334 | u32 mmio_base; |
| 333 | − unsigned int irq_shift; | |
| 334 | 335 | |
| 335 | 336 | struct intel_ring *buffer; |
| 336 | 337 | struct intel_timeline *timeline; |
| @@ -561,6 +562,7 @@ struct intel_engine_cs { · 224 unmodified lines | ||
| 561 | 562 | |
| 562 | 563 | #define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) |
| 563 | 564 | #define I915_ENGINE_SUPPORTS_STATS BIT(1) |
| 565 | +#define I915_ENGINE_HAS_PREEMPTION BIT(2) | |
| 564 | 566 | unsigned int flags; |
| 565 | 567 | |
| 566 | 568 | /* |
| @@ -620,16 +622,29 @@ struct intel_engine_cs { · 53 unmodified lines | ||
| 620 | 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 | 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 | 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 | 648 | static inline void |
| 634 | 649 | execlists_set_active(struct intel_engine_execlists *execlists, |
| 635 | 650 | unsigned int bit) |
| @@ -637,6 +652,13 @@ execlists_set_active(struct intel_engine_execlists *execlists, · 1 unmodified line | ||
| 637 | 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 | 662 | static inline void |
| 641 | 663 | execlists_clear_active(struct intel_engine_execlists *execlists, |
| 642 | 664 | unsigned int bit) |
| @@ -651,6 +673,10 @@ execlists_is_active(const struct intel_engine_execlists *execlists, · 8 unmodified lines | ||
| 651 | 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 | 680 | void |
| 655 | 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) · 6 unmodified lines | ||
| 663 | 689 | return execlists->port_mask + 1; |
| 664 | 690 | } |
| 665 | 691 | |
| 666 | −static inline void | |
| 692 | +static inline struct execlist_port * | |
| 667 | 693 | execlists_port_complete(struct intel_engine_execlists * const execlists, |
| 668 | 694 | struct execlist_port * const port) |
| 669 | 695 | { |
| @@ -674,6 +700,8 @@ execlists_port_complete(struct intel_engine_execlists * const execlists, · 4 unmodified lines | ||
| 674 | 700 | |
| 675 | 701 | memmove(port, port + 1, m * sizeof(struct execlist_port)); |
| 676 | 702 | memset(port + m, 0, sizeof(struct execlist_port)); |
| 703 | + | |
| 704 | + return port; | |
| 677 | 705 | } |
| 678 | 706 | |
| 679 | 707 | static inline unsigned int |
| @@ -857,9 +885,6 @@ static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine) · 177 unmodified lines | ||
| 857 | 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 | 888 | void intel_engine_get_instdone(struct intel_engine_cs *engine, |
| 864 | 889 | struct intel_instdone *instdone); |
| 865 | 890 | |
| @@ -939,7 +964,7 @@ bool intel_engine_add_wait(struct intel_engine_cs *engine, · 73 unmodified lines | ||
| 939 | 964 | struct intel_wait *wait); |
| 940 | 965 | void intel_engine_remove_wait(struct intel_engine_cs *engine, |
| 941 | 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 | 968 | void intel_engine_cancel_signaling(struct i915_request *request); |
| 944 | 969 | |
| 945 | 970 | static inline bool intel_engine_has_waiter(const struct intel_engine_cs *engine) |
| @@ -48,6 +48,7 @@ bool intel_format_is_yuv(u32 format) · 47 unmodified lines | ||
| 48 | 48 | case DRM_FORMAT_UYVY: |
| 49 | 49 | case DRM_FORMAT_VYUY: |
| 50 | 50 | case DRM_FORMAT_YVYU: |
| 51 | + case DRM_FORMAT_NV12: | |
| 51 | 52 | return true; |
| 52 | 53 | default: |
| 53 | 54 | return false; |
| @@ -946,6 +947,7 @@ intel_check_sprite_plane(struct intel_plane *plane, · 892 unmodified lines | ||
| 946 | 947 | int max_scale, min_scale; |
| 947 | 948 | bool can_scale; |
| 948 | 949 | int ret; |
| 950 | + uint32_t pixel_format = 0; | |
| 949 | 951 | |
| 950 | 952 | *src = drm_plane_state_src(&state->base); |
| 951 | 953 | *dst = drm_plane_state_dest(&state->base); |
| @@ -969,11 +971,14 @@ intel_check_sprite_plane(struct intel_plane *plane, · 17 unmodified lines | ||
| 969 | 971 | |
| 970 | 972 | /* setup can_scale, min_scale, max_scale */ |
| 971 | 973 | if (INTEL_GEN(dev_priv) >= 9) { |
| 974 | + if (state->base.fb) | |
| 975 | + pixel_format = state->base.fb->format->format; | |
| 972 | 976 | /* use scaler when colorkey is not required */ |
| 973 | 977 | if (!state->ckey.flags) { |
| 974 | 978 | can_scale = 1; |
| 975 | 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 | 982 | } else { |
| 978 | 983 | can_scale = 0; |
| 979 | 984 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
| @@ -69,13 +69,15 @@ static int __get_platform_enable_guc(struct drm_i915_private *dev_priv) · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 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 */ | |
| 75 | − if (HAS_GUC(dev_priv) && intel_uc_is_using_guc() && | |
| 76 | − (IS_ENABLED(CONFIG_DRM_I915_DEBUG) || | |
| 77 | − IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))) | |
| 78 | − guc_log_level = 1 + GUC_LOG_VERBOSITY_MAX; | |
| 74 | + if (!HAS_GUC(dev_priv) || !intel_uc_is_using_guc()) | |
| 75 | + guc_log_level = GUC_LOG_LEVEL_DISABLED; | |
| 76 | + else if (IS_ENABLED(CONFIG_DRM_I915_DEBUG) || | |
| 77 | + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) | |
| 78 | + guc_log_level = GUC_LOG_LEVEL_MAX; | |
| 79 | + else | |
| 80 | + guc_log_level = GUC_LOG_LEVEL_NON_VERBOSE; | |
| 79 | 81 | |
| 80 | 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) · 1 unmodified line | ||
| 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 | 89 | * @dev_priv: device private |
| 88 | 90 | * |
| 89 | 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) · 9 unmodified lines | ||
| 99 | 101 | * unless GuC is enabled on given platform and the driver is compiled with |
| 100 | 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 | 106 | struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; |
| 105 | 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) · 36 unmodified lines | ||
| 142 | 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 | 148 | DRM_WARN("Incompatible option detected: %s=%d, %s!\n", |
| 147 | 149 | "guc_log_level", i915_modparams.guc_log_level, |
| 148 | 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 | 155 | i915_modparams.guc_log_level, |
| 154 | 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 | 160 | /* Make sure that sanitization was done */ |
| 158 | 161 | GEM_BUG_ON(i915_modparams.enable_guc < 0); |
| 159 | 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); | |
| 165 | − intel_huc_init_early(&dev_priv->huc); | |
| 166 | −} | |
| 167 | + struct intel_guc *guc = &i915->guc; | |
| 168 | + struct intel_huc *huc = &i915->huc; | |
| 167 | 169 | |
| 168 | −void intel_uc_init_fw(struct drm_i915_private *dev_priv) | |
| 169 | −{ | |
| 170 | − if (!USES_GUC(dev_priv)) | |
| 171 | − return; | |
| 170 | + intel_guc_init_early(guc); | |
| 171 | + intel_huc_init_early(huc); | |
| 172 | 172 | |
| 173 | − if (USES_HUC(dev_priv)) | |
| 174 | − intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw); | |
| 173 | + sanitize_options_early(i915); | |
| 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)) | |
| 182 | − return; | |
| 184 | + struct intel_guc *guc = &i915->guc; | |
| 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)) | |
| 187 | − intel_uc_fw_fini(&dev_priv->huc.fw); | |
| 190 | + if (USES_GUC(i915)) | |
| 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) · 30 unmodified lines | ||
| 223 | 227 | { |
| 224 | 228 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 225 | 229 | |
| 230 | + gen9_enable_guc_interrupts(dev_priv); | |
| 231 | + | |
| 226 | 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 | 235 | guc->send = intel_guc_send_mmio; |
| 236 | + guc->handler = intel_guc_to_host_event_handler_mmio; | |
| 230 | 237 | return 0; |
| 231 | 238 | } |
| 232 | 239 | |
| @@ -235,9 +242,12 @@ static void guc_disable_communication(struct intel_guc *guc) · 2 unmodified lines | ||
| 235 | 242 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 236 | 243 | |
| 237 | 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 | 249 | guc->send = intel_guc_send_nop; |
| 250 | + guc->handler = intel_guc_to_host_event_handler_nop; | |
| 241 | 251 | } |
| 242 | 252 | |
| 243 | 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) · 4 unmodified lines | ||
| 248 | 258 | if (!USES_GUC(dev_priv)) |
| 249 | 259 | return 0; |
| 250 | 260 | |
| 251 | − ret = intel_guc_init_wq(guc); | |
| 252 | − if (ret) { | |
| 253 | − DRM_ERROR("Couldn't allocate workqueues for GuC\n"); | |
| 254 | − goto err; | |
| 255 | − } | |
| 261 | + intel_guc_init_ggtt_pin_bias(guc); | |
| 256 | 262 | |
| 257 | − ret = intel_guc_log_relay_create(guc); | |
| 258 | − if (ret) { | |
| 259 | − DRM_ERROR("Couldn't allocate relay for GuC log\n"); | |
| 260 | − goto err_relay; | |
| 261 | − } | |
| 263 | + ret = intel_guc_init_wq(guc); | |
| 264 | + if (ret) | |
| 265 | + return ret; | |
| 262 | 266 | |
| 263 | 267 | return 0; |
| 264 | − | |
| 265 | −err_relay: | |
| 266 | − intel_guc_fini_wq(guc); | |
| 267 | −err: | |
| 268 | − return ret; | |
| 269 | 268 | } |
| 270 | 269 | |
| 271 | 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) · 4 unmodified lines | ||
| 276 | 275 | return; |
| 277 | 276 | |
| 278 | 277 | intel_guc_fini_wq(guc); |
| 279 | − | |
| 280 | − intel_guc_log_relay_destroy(guc); | |
| 281 | 278 | } |
| 282 | 279 | |
| 283 | 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) · 41 unmodified lines | ||
| 325 | 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 | 343 | int intel_uc_init_hw(struct drm_i915_private *dev_priv) |
| 329 | 344 | { |
| 330 | 345 | struct intel_guc *guc = &dev_priv->guc; |
| @@ -336,14 +351,8 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) · 5 unmodified lines | ||
| 336 | 351 | |
| 337 | 352 | GEM_BUG_ON(!HAS_GUC(dev_priv)); |
| 338 | 353 | |
| 339 | − guc_disable_communication(guc); | |
| 340 | 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 | 356 | /* WaEnableuKernelHeaderValidFix:skl */ |
| 348 | 357 | /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */ |
| 349 | 358 | if (IS_GEN9(dev_priv)) |
| @@ -390,12 +399,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) · 40 unmodified lines | ||
| 390 | 399 | } |
| 391 | 400 | |
| 392 | 401 | if (USES_GUC_SUBMISSION(dev_priv)) { |
| 393 | − if (i915_modparams.guc_log_level) | |
| 394 | − gen9_enable_guc_interrupts(dev_priv); | |
| 395 | − | |
| 396 | 402 | ret = intel_guc_submission_enable(guc); |
| 397 | 403 | if (ret) |
| 398 | − goto err_interrupts; | |
| 404 | + goto err_communication; | |
| 399 | 405 | } |
| 400 | 406 | |
| 401 | 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) · 8 unmodified lines | ||
| 410 | 416 | /* |
| 411 | 417 | * We've failed to load the firmware :( |
| 412 | 418 | */ |
| 413 | −err_interrupts: | |
| 414 | − gen9_disable_guc_interrupts(dev_priv); | |
| 415 | 419 | err_communication: |
| 416 | 420 | guc_disable_communication(guc); |
| 417 | 421 | err_log_capture: |
| @@ -441,9 +445,6 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv) · 23 unmodified lines | ||
| 441 | 445 | intel_guc_submission_disable(guc); |
| 442 | 446 | |
| 443 | 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 | 450 | int intel_uc_suspend(struct drm_i915_private *i915) |
| @@ -479,8 +480,7 @@ int intel_uc_resume(struct drm_i915_private *i915) · 29 unmodified lines | ||
| 479 | 480 | if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) |
| 480 | 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 | 485 | err = intel_guc_resume(guc); |
| 486 | 486 | if (err) { |
| @@ -28,13 +28,12 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "intel_huc.h" |
| 29 | 29 | #include "i915_params.h" |
| 30 | 30 | |
| 31 | −void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); | |
| 32 | 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 | 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 | 34 | int intel_uc_init_misc(struct drm_i915_private *dev_priv); |
| 37 | 35 | void intel_uc_fini_misc(struct drm_i915_private *dev_priv); |
| 36 | +void intel_uc_sanitize(struct drm_i915_private *dev_priv); | |
| 38 | 37 | int intel_uc_init_hw(struct drm_i915_private *dev_priv); |
| 39 | 38 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv); |
| 40 | 39 | int intel_uc_init(struct drm_i915_private *dev_priv); |
| @@ -95,15 +95,6 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, · 94 unmodified lines | ||
| 95 | 95 | uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; |
| 96 | 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 | 98 | /* now RSA */ |
| 108 | 99 | if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) { |
| 109 | 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, · 99 unmodified lines | ||
| 209 | 200 | struct i915_vma *vma)) |
| 210 | 201 | { |
| 211 | 202 | struct i915_vma *vma; |
| 203 | + u32 ggtt_pin_bias; | |
| 212 | 204 | int err; |
| 213 | 205 | |
| 214 | 206 | DRM_DEBUG_DRIVER("%s fw load %s\n", |
| @@ -230,8 +222,9 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, · 15 unmodified lines | ||
| 230 | 222 | goto fail; |
| 231 | 223 | } |
| 232 | 224 | |
| 225 | + ggtt_pin_bias = to_i915(uc_fw->obj->base.dev)->guc.ggtt_pin_bias; | |
| 233 | 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 | 228 | if (IS_ERR(vma)) { |
| 236 | 229 | err = PTR_ERR(vma); |
| 237 | 230 | DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n", |
| @@ -115,6 +115,28 @@ static inline bool intel_uc_fw_is_selected(struct intel_uc_fw *uc_fw) · 114 unmodified lines | ||
| 115 | 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 | 140 | void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, |
| 119 | 141 | struct intel_uc_fw *uc_fw); |
| 120 | 142 | int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, |
| @@ -62,6 +62,11 @@ static inline void · 61 unmodified lines | ||
| 62 | 62 | fw_domain_reset(struct drm_i915_private *i915, |
| 63 | 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 | 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, · 1285 unmodified lines | ||
| 1353 | 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 | 1378 | static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) |
| 1357 | 1379 | { |
| 1358 | 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) · 206 unmodified lines | ||
| 1565 | 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 | 1624 | void intel_uncore_fini(struct drm_i915_private *dev_priv) |
| 1569 | 1625 | { |
| 1570 | 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) · 75 unmodified lines | ||
| 1646 | 1702 | const i915_reg_t mode = RING_MI_MODE(base); |
| 1647 | 1703 | |
| 1648 | 1704 | I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); |
| 1649 | − if (intel_wait_for_register_fw(dev_priv, | |
| 1650 | − mode, | |
| 1651 | − MODE_IDLE, | |
| 1652 | − MODE_IDLE, | |
| 1653 | − 500)) | |
| 1705 | + if (__intel_wait_for_register_fw(dev_priv, | |
| 1706 | + mode, MODE_IDLE, MODE_IDLE, | |
| 1707 | + 500, 0, | |
| 1708 | + NULL)) | |
| 1654 | 1709 | DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", |
| 1655 | 1710 | engine->name); |
| 1656 | 1711 | |
| @@ -1804,9 +1859,10 @@ static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv, · 147 unmodified lines | ||
| 1804 | 1859 | __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask); |
| 1805 | 1860 | |
| 1806 | 1861 | /* Wait for the device to ack the reset requests */ |
| 1807 | − err = intel_wait_for_register_fw(dev_priv, | |
| 1808 | − GEN6_GDRST, hw_domain_mask, 0, | |
| 1809 | − 500); | |
| 1862 | + err = __intel_wait_for_register_fw(dev_priv, | |
| 1863 | + GEN6_GDRST, hw_domain_mask, 0, | |
| 1864 | + 500, 0, | |
| 1865 | + NULL); | |
| 1810 | 1866 | if (err) |
| 1811 | 1867 | DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n", |
| 1812 | 1868 | hw_domain_mask); |
| @@ -1853,6 +1909,50 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv, · 40 unmodified lines | ||
| 1853 | 1909 | return gen6_hw_domain_reset(dev_priv, hw_mask); |
| 1854 | 1910 | } |
| 1855 | 1911 | |
| 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 | + | |
| 1856 | 1956 | /** |
| 1857 | 1957 | * __intel_wait_for_register_fw - wait until register matches expected state |
| 1858 | 1958 | * @dev_priv: the i915 device |
| @@ -1940,7 +2040,7 @@ int __intel_wait_for_register(struct drm_i915_private *dev_priv, · 81 unmodified lines | ||
| 1940 | 2040 | u32 reg_value; |
| 1941 | 2041 | int ret; |
| 1942 | 2042 | |
| 1943 | − might_sleep(); | |
| 2043 | + might_sleep_if(slow_timeout_ms); | |
| 1944 | 2044 | |
| 1945 | 2045 | spin_lock_irq(&dev_priv->uncore.lock); |
| 1946 | 2046 | intel_uncore_forcewake_get__locked(dev_priv, fw); |
| @@ -1952,7 +2052,7 @@ int __intel_wait_for_register(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 1952 | 2052 | intel_uncore_forcewake_put__locked(dev_priv, fw); |
| 1953 | 2053 | spin_unlock_irq(&dev_priv->uncore.lock); |
| 1954 | 2054 | |
| 1955 | − if (ret) | |
| 2055 | + if (ret && slow_timeout_ms) | |
| 1956 | 2056 | ret = __wait_for(reg_value = I915_READ_NOTRACE(reg), |
| 1957 | 2057 | (reg_value & mask) == value, |
| 1958 | 2058 | slow_timeout_ms * 1000, 10, 1000); |
| @@ -1971,11 +2071,12 @@ static int gen8_reset_engine_start(struct intel_engine_cs *engine) · 12 unmodified lines | ||
| 1971 | 2071 | I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), |
| 1972 | 2072 | _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); |
| 1973 | 2073 | |
| 1974 | − ret = intel_wait_for_register_fw(dev_priv, | |
| 1975 | − RING_RESET_CTL(engine->mmio_base), | |
| 1976 | − RESET_CTL_READY_TO_RESET, | |
| 1977 | − RESET_CTL_READY_TO_RESET, | |
| 1978 | − 700); | |
| 2074 | + ret = __intel_wait_for_register_fw(dev_priv, | |
| 2075 | + RING_RESET_CTL(engine->mmio_base), | |
| 2076 | + RESET_CTL_READY_TO_RESET, | |
| 2077 | + RESET_CTL_READY_TO_RESET, | |
| 2078 | + 700, 0, | |
| 2079 | + NULL); | |
| 1979 | 2080 | if (ret) |
| 1980 | 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, · 18 unmodified lines | ||
| 2000 | 2101 | if (gen8_reset_engine_start(engine)) |
| 2001 | 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 | 2109 | not_ready: |
| 2006 | 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) · 31 unmodified lines | ||
| 2038 | 2142 | int retry; |
| 2039 | 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 | 2163 | * request may be dropped and never completes (causing -EIO). |
| 2045 | 2164 | */ |
| 2046 | 2165 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
| 2047 | 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 | 2170 | * dead gpu (on elk). Also as modern gpu as kbl can suffer |
| 2051 | 2171 | * from system hang if batchbuffer is progressing when |
| 2052 | 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) · 7 unmodified lines | ||
| 2060 | 2180 | i915_stop_engines(dev_priv, engine_mask); |
| 2061 | 2181 | |
| 2062 | 2182 | ret = -ENODEV; |
| 2063 | − if (reset) | |
| 2183 | + if (reset) { | |
| 2184 | + GEM_TRACE("engine_mask=%x\n", engine_mask); | |
| 2064 | 2185 | ret = reset(dev_priv, engine_mask); |
| 2065 | − if (ret != -ETIMEDOUT) | |
| 2186 | + } | |
| 2187 | + if (ret != -ETIMEDOUT || engine_mask != ALL_ENGINES) | |
| 2066 | 2188 | break; |
| 2067 | 2189 | |
| 2068 | 2190 | cond_resched(); |
| @@ -2085,12 +2207,14 @@ bool intel_has_reset_engine(struct drm_i915_private *dev_priv) · 16 unmodified lines | ||
| 2085 | 2207 | |
| 2086 | 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 | 2212 | int ret; |
| 2089 | 2213 | |
| 2090 | 2214 | GEM_BUG_ON(!HAS_GUC(dev_priv)); |
| 2091 | 2215 | |
| 2092 | 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 | 2218 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
| 2095 | 2219 | |
| 2096 | 2220 | return ret; |
| @@ -140,6 +140,7 @@ struct intel_uncore { · 139 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | void intel_uncore_sanitize(struct drm_i915_private *dev_priv); |
| 142 | 142 | void intel_uncore_init(struct drm_i915_private *dev_priv); |
| 143 | +void intel_uncore_prune(struct drm_i915_private *dev_priv); | |
| 143 | 144 | bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); |
| 144 | 145 | bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); |
| 145 | 146 | void intel_uncore_fini(struct drm_i915_private *dev_priv); |
| @@ -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 | +} | |
| @@ -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 | |
| @@ -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 | +} | |
| @@ -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 | |
| @@ -20,4 +20,5 @@ selftest(evict, i915_gem_evict_live_selftests) · 19 unmodified lines | ||
| 20 | 20 | selftest(hugepages, i915_gem_huge_page_live_selftests) |
| 21 | 21 | selftest(contexts, i915_gem_context_live_selftests) |
| 22 | 22 | selftest(hangcheck, intel_hangcheck_live_selftests) |
| 23 | +selftest(execlists, intel_execlists_live_selftests) | |
| 23 | 24 | selftest(guc, intel_guc_live_selftest) |
| @@ -14,6 +14,7 @@ selftest(fence, i915_sw_fence_mock_selftests) · 13 unmodified lines | ||
| 14 | 14 | selftest(scatterlist, scatterlist_mock_selftests) |
| 15 | 15 | selftest(syncmap, i915_syncmap_mock_selftests) |
| 16 | 16 | selftest(uncore, intel_uncore_mock_selftests) |
| 17 | +selftest(engine, intel_engine_cs_mock_selftests) | |
| 17 | 18 | selftest(breadcrumbs, intel_breadcrumbs_mock_selftests) |
| 18 | 19 | selftest(timelines, i915_gem_timeline_mock_selftests) |
| 19 | 20 | selftest(requests, i915_request_mock_selftests) |
| @@ -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 | +} | |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/kthread.h> |
| 26 | 26 | |
| 27 | 27 | #include "../i915_selftest.h" |
| 28 | +#include "i915_random.h" | |
| 28 | 29 | |
| 29 | 30 | #include "mock_context.h" |
| 30 | 31 | #include "mock_drm.h" |
| @@ -260,8 +261,11 @@ static void wedge_me(struct work_struct *work) · 229 unmodified lines | ||
| 260 | 261 | { |
| 261 | 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 | − w->symbol); | |
| 264 | + pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); | |
| 265 | + | |
| 266 | + GEM_TRACE("%pS timed out.\n", w->symbol); | |
| 267 | + GEM_TRACE_DUMP(); | |
| 268 | + | |
| 265 | 269 | i915_gem_set_wedged(w->i915); |
| 266 | 270 | } |
| 267 | 271 | |
| @@ -318,7 +322,7 @@ static void hang_fini(struct hang *h) · 50 unmodified lines | ||
| 318 | 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 | 327 | return !(wait_for_us(i915_seqno_passed(hws_seqno(h, rq), |
| 324 | 328 | rq->fence.seqno), |
| @@ -433,7 +437,7 @@ static int igt_global_reset(void *arg) · 108 unmodified lines | ||
| 433 | 437 | mutex_lock(&i915->drm.struct_mutex); |
| 434 | 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 | 442 | if (i915_reset_count(&i915->gpu_error) == reset_count) { |
| 439 | 443 | pr_err("No GPU reset recorded!\n"); |
| @@ -483,6 +487,8 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) · 43 unmodified lines | ||
| 483 | 487 | |
| 484 | 488 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
| 485 | 489 | do { |
| 490 | + u32 seqno = intel_engine_get_seqno(engine); | |
| 491 | + | |
| 486 | 492 | if (active) { |
| 487 | 493 | struct i915_request *rq; |
| 488 | 494 | |
| @@ -498,7 +504,7 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) · 9 unmodified lines | ||
| 498 | 504 | __i915_request_add(rq, true); |
| 499 | 505 | mutex_unlock(&i915->drm.struct_mutex); |
| 500 | 506 | |
| 501 | − if (!wait_for_hang(&h, rq)) { | |
| 507 | + if (!wait_until_running(&h, rq)) { | |
| 502 | 508 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
| 503 | 509 | |
| 504 | 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) · 6 unmodified lines | ||
| 511 | 517 | break; |
| 512 | 518 | } |
| 513 | 519 | |
| 520 | + GEM_BUG_ON(!rq->global_seqno); | |
| 521 | + seqno = rq->global_seqno - 1; | |
| 514 | 522 | i915_request_put(rq); |
| 515 | 523 | } |
| 516 | 524 | |
| 517 | − engine->hangcheck.stalled = true; | |
| 518 | − engine->hangcheck.seqno = | |
| 519 | − intel_engine_get_seqno(engine); | |
| 520 | − | |
| 521 | − err = i915_reset_engine(engine, I915_RESET_QUIET); | |
| 525 | + err = i915_reset_engine(engine, NULL); | |
| 522 | 526 | if (err) { |
| 523 | 527 | pr_err("i915_reset_engine failed\n"); |
| 524 | 528 | break; |
| @@ -538,8 +542,6 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) · 13 unmodified lines | ||
| 538 | 542 | err = -EINVAL; |
| 539 | 543 | break; |
| 540 | 544 | } |
| 541 | − | |
| 542 | − engine->hangcheck.stalled = false; | |
| 543 | 545 | } while (time_before(jiffies, end_time)); |
| 544 | 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) · 27 unmodified lines | ||
| 573 | 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 | 590 | static int active_engine(void *data) |
| 577 | 591 | { |
| 578 | − struct intel_engine_cs *engine = data; | |
| 579 | − struct i915_request *rq[2] = {}; | |
| 580 | − struct i915_gem_context *ctx[2]; | |
| 592 | + I915_RND_STATE(prng); | |
| 593 | + struct active_engine *arg = data; | |
| 594 | + struct intel_engine_cs *engine = arg->engine; | |
| 595 | + struct i915_request *rq[8] = {}; | |
| 596 | + struct i915_gem_context *ctx[ARRAY_SIZE(rq)]; | |
| 581 | 597 | struct drm_file *file; |
| 582 | 598 | unsigned long count = 0; |
| 583 | 599 | int err = 0; |
| @@ -586,25 +602,20 @@ static int active_engine(void *data) · 2 unmodified lines | ||
| 586 | 602 | if (IS_ERR(file)) |
| 587 | 603 | return PTR_ERR(file); |
| 588 | 604 | |
| 589 | − mutex_lock(&engine->i915->drm.struct_mutex); | |
| 590 | − ctx[0] = live_context(engine->i915, file); | |
| 591 | − mutex_unlock(&engine->i915->drm.struct_mutex); | |
| 592 | − if (IS_ERR(ctx[0])) { | |
| 593 | − err = PTR_ERR(ctx[0]); | |
| 594 | − goto err_file; | |
| 595 | − } | |
| 596 | − | |
| 597 | − mutex_lock(&engine->i915->drm.struct_mutex); | |
| 598 | − ctx[1] = live_context(engine->i915, file); | |
| 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; | |
| 605 | + for (count = 0; count < ARRAY_SIZE(ctx); count++) { | |
| 606 | + mutex_lock(&engine->i915->drm.struct_mutex); | |
| 607 | + ctx[count] = live_context(engine->i915, file); | |
| 608 | + mutex_unlock(&engine->i915->drm.struct_mutex); | |
| 609 | + if (IS_ERR(ctx[count])) { | |
| 610 | + err = PTR_ERR(ctx[count]); | |
| 611 | + while (--count) | |
| 612 | + i915_gem_context_put(ctx[count]); | |
| 613 | + goto err_file; | |
| 614 | + } | |
| 604 | 615 | } |
| 605 | 616 | |
| 606 | 617 | while (!kthread_should_stop()) { |
| 607 | − unsigned int idx = count++ & 1; | |
| 618 | + unsigned int idx = count++ & (ARRAY_SIZE(rq) - 1); | |
| 608 | 619 | struct i915_request *old = rq[idx]; |
| 609 | 620 | struct i915_request *new; |
| 610 | 621 | |
| @@ -616,14 +627,28 @@ static int active_engine(void *data) · 5 unmodified lines | ||
| 616 | 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 | 634 | rq[idx] = i915_request_get(new); |
| 620 | 635 | i915_request_add(new); |
| 621 | 636 | mutex_unlock(&engine->i915->drm.struct_mutex); |
| 622 | 637 | |
| 623 | 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 | 648 | i915_request_put(old); |
| 626 | 649 | } |
| 650 | + | |
| 651 | + cond_resched(); | |
| 627 | 652 | } |
| 628 | 653 | |
| 629 | 654 | for (count = 0; count < ARRAY_SIZE(rq); count++) |
| @@ -634,8 +659,9 @@ err_file: · 4 unmodified lines | ||
| 634 | 659 | return err; |
| 635 | 660 | } |
| 636 | 661 | |
| 637 | −static int __igt_reset_engine_others(struct drm_i915_private *i915, | |
| 638 | − bool active) | |
| 662 | +static int __igt_reset_engines(struct drm_i915_private *i915, | |
| 663 | + const char *test_name, | |
| 664 | + unsigned int flags) | |
| 639 | 665 | { |
| 640 | 666 | struct intel_engine_cs *engine, *other; |
| 641 | 667 | enum intel_engine_id id, tmp; |
| @@ -649,50 +675,61 @@ static int __igt_reset_engine_others(struct drm_i915_private *i915, · 7 unmodified lines | ||
| 649 | 675 | if (!intel_has_reset_engine(i915)) |
| 650 | 676 | return 0; |
| 651 | 677 | |
| 652 | − if (active) { | |
| 678 | + if (flags & TEST_ACTIVE) { | |
| 653 | 679 | mutex_lock(&i915->drm.struct_mutex); |
| 654 | 680 | err = hang_init(&h, i915); |
| 655 | 681 | mutex_unlock(&i915->drm.struct_mutex); |
| 656 | 682 | if (err) |
| 657 | 683 | return err; |
| 684 | + | |
| 685 | + if (flags & TEST_PRIORITY) | |
| 686 | + h.ctx->priority = 1024; | |
| 658 | 687 | } |
| 659 | 688 | |
| 660 | 689 | for_each_engine(engine, i915, id) { |
| 661 | − struct task_struct *threads[I915_NUM_ENGINES] = {}; | |
| 662 | − unsigned long resets[I915_NUM_ENGINES]; | |
| 690 | + struct active_engine threads[I915_NUM_ENGINES] = {}; | |
| 663 | 691 | unsigned long global = i915_reset_count(&i915->gpu_error); |
| 664 | − unsigned long count = 0; | |
| 692 | + unsigned long count = 0, reported; | |
| 665 | 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 | 697 | continue; |
| 669 | 698 | |
| 670 | 699 | memset(threads, 0, sizeof(threads)); |
| 671 | 700 | for_each_engine(other, i915, tmp) { |
| 672 | 701 | struct task_struct *tsk; |
| 673 | 702 | |
| 674 | − resets[tmp] = i915_reset_engine_count(&i915->gpu_error, | |
| 675 | − other); | |
| 703 | + threads[tmp].resets = | |
| 704 | + i915_reset_engine_count(&i915->gpu_error, | |
| 705 | + other); | |
| 676 | 706 | |
| 677 | − if (other == engine) | |
| 707 | + if (!(flags & TEST_OTHERS)) | |
| 678 | 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 | 717 | "igt/%s", other->name); |
| 682 | 718 | if (IS_ERR(tsk)) { |
| 683 | 719 | err = PTR_ERR(tsk); |
| 684 | 720 | goto unwind; |
| 685 | 721 | } |
| 686 | 722 | |
| 687 | − threads[tmp] = tsk; | |
| 723 | + threads[tmp].task = tsk; | |
| 688 | 724 | get_task_struct(tsk); |
| 689 | 725 | } |
| 690 | 726 | |
| 691 | 727 | set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
| 692 | 728 | do { |
| 693 | − if (active) { | |
| 694 | − struct i915_request *rq; | |
| 729 | + u32 seqno = intel_engine_get_seqno(engine); | |
| 730 | + struct i915_request *rq = NULL; | |
| 695 | 731 | |
| 732 | + if (flags & TEST_ACTIVE) { | |
| 696 | 733 | mutex_lock(&i915->drm.struct_mutex); |
| 697 | 734 | rq = hang_create_request(&h, engine); |
| 698 | 735 | if (IS_ERR(rq)) { |
| @@ -705,7 +742,7 @@ static int __igt_reset_engine_others(struct drm_i915_private *i915, · 6 unmodified lines | ||
| 705 | 742 | __i915_request_add(rq, true); |
| 706 | 743 | mutex_unlock(&i915->drm.struct_mutex); |
| 707 | 744 | |
| 708 | − if (!wait_for_hang(&h, rq)) { | |
| 745 | + if (!wait_until_running(&h, rq)) { | |
| 709 | 746 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
| 710 | 747 | |
| 711 | 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, · 6 unmodified lines | ||
| 718 | 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; | |
| 725 | − engine->hangcheck.seqno = | |
| 726 | − intel_engine_get_seqno(engine); | |
| 727 | − | |
| 728 | − err = i915_reset_engine(engine, I915_RESET_QUIET); | |
| 762 | + err = i915_reset_engine(engine, NULL); | |
| 729 | 763 | if (err) { |
| 730 | − pr_err("i915_reset_engine(%s:%s) failed, err=%d\n", | |
| 731 | − engine->name, active ? "active" : "idle", err); | |
| 764 | + pr_err("i915_reset_engine(%s:%s): failed, err=%d\n", | |
| 765 | + engine->name, test_name, err); | |
| 732 | 766 | break; |
| 733 | 767 | } |
| 734 | 768 | |
| 735 | − engine->hangcheck.stalled = false; | |
| 736 | 769 | count++; |
| 770 | + | |
| 771 | + if (rq) { | |
| 772 | + i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); | |
| 773 | + i915_request_put(rq); | |
| 774 | + } | |
| 737 | 775 | } while (time_before(jiffies, end_time)); |
| 738 | 776 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
| 739 | 777 | pr_info("i915_reset_engine(%s:%s): %lu resets\n", |
| 740 | − engine->name, active ? "active" : "idle", count); | |
| 741 | − | |
| 742 | − if (i915_reset_engine_count(&i915->gpu_error, engine) - | |
| 743 | − resets[engine->id] != (active ? count : 0)) { | |
| 744 | − pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu\n", | |
| 745 | − engine->name, active ? "active" : "idle", count, | |
| 746 | − i915_reset_engine_count(&i915->gpu_error, | |
| 747 | − engine) - resets[engine->id]); | |
| 778 | + engine->name, test_name, count); | |
| 779 | + | |
| 780 | + reported = i915_reset_engine_count(&i915->gpu_error, engine); | |
| 781 | + reported -= threads[engine->id].resets; | |
| 782 | + if (reported != (flags & TEST_ACTIVE ? count : 0)) { | |
| 783 | + pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu, expected %lu reported\n", | |
| 784 | + engine->name, test_name, count, reported, | |
| 785 | + (flags & TEST_ACTIVE ? count : 0)); | |
| 748 | 786 | if (!err) |
| 749 | 787 | err = -EINVAL; |
| 750 | 788 | } |
| @@ -753,24 +791,26 @@ unwind: · 2 unmodified lines | ||
| 753 | 791 | for_each_engine(other, i915, tmp) { |
| 754 | 792 | int ret; |
| 755 | 793 | |
| 756 | − if (!threads[tmp]) | |
| 794 | + if (!threads[tmp].task) | |
| 757 | 795 | continue; |
| 758 | 796 | |
| 759 | − ret = kthread_stop(threads[tmp]); | |
| 797 | + ret = kthread_stop(threads[tmp].task); | |
| 760 | 798 | if (ret) { |
| 761 | 799 | pr_err("kthread for other engine %s failed, err=%d\n", |
| 762 | 800 | other->name, ret); |
| 763 | 801 | if (!err) |
| 764 | 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, | |
| 769 | − other)) { | |
| 806 | + if (other != engine && | |
| 807 | + threads[tmp].resets != | |
| 808 | + i915_reset_engine_count(&i915->gpu_error, other)) { | |
| 770 | 809 | pr_err("Innocent engine %s was reset (count=%ld)\n", |
| 771 | 810 | other->name, |
| 772 | 811 | i915_reset_engine_count(&i915->gpu_error, |
| 773 | − other) - resets[tmp]); | |
| 812 | + other) - | |
| 813 | + threads[tmp].resets); | |
| 774 | 814 | if (!err) |
| 775 | 815 | err = -EINVAL; |
| 776 | 816 | } |
| @@ -794,7 +834,7 @@ unwind: · 17 unmodified lines | ||
| 794 | 834 | if (i915_terminally_wedged(&i915->gpu_error)) |
| 795 | 835 | err = -EIO; |
| 796 | 836 | |
| 797 | − if (active) { | |
| 837 | + if (flags & TEST_ACTIVE) { | |
| 798 | 838 | mutex_lock(&i915->drm.struct_mutex); |
| 799 | 839 | hang_fini(&h); |
| 800 | 840 | mutex_unlock(&i915->drm.struct_mutex); |
| @@ -803,27 +843,56 @@ unwind: · 2 unmodified lines | ||
| 803 | 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); | |
| 809 | −} | |
| 848 | + static const struct { | |
| 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) | |
| 812 | −{ | |
| 813 | − return __igt_reset_engine_others(arg, true); | |
| 870 | + for (p = phases; p->name; p++) { | |
| 871 | + if (p->flags & TEST_PRIORITY) { | |
| 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; | |
| 821 | − rq->engine->hangcheck.seqno = intel_engine_get_seqno(rq->engine); | |
| 889 | + error->stalled_mask = mask; | |
| 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); | |
| 826 | − wake_up_all(&rq->i915->gpu_error.wait_queue); | |
| 895 | + wake_up_all(&error->wait_queue); | |
| 827 | 896 | |
| 828 | 897 | return reset_count; |
| 829 | 898 | } |
| @@ -858,21 +927,20 @@ static int igt_wait_reset(void *arg) · 28 unmodified lines | ||
| 858 | 927 | i915_request_get(rq); |
| 859 | 928 | __i915_request_add(rq, true); |
| 860 | 929 | |
| 861 | − if (!wait_for_hang(&h, rq)) { | |
| 930 | + if (!wait_until_running(&h, rq)) { | |
| 862 | 931 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
| 863 | 932 | |
| 864 | 933 | pr_err("%s: Failed to start request %x, at %x\n", |
| 865 | 934 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); |
| 866 | 935 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); |
| 867 | 936 | |
| 868 | − i915_reset(i915, 0); | |
| 869 | 937 | i915_gem_set_wedged(i915); |
| 870 | 938 | |
| 871 | 939 | err = -EIO; |
| 872 | 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 | 945 | timeout = i915_request_wait(rq, I915_WAIT_LOCKED, 10); |
| 878 | 946 | if (timeout < 0) { |
| @@ -903,6 +971,23 @@ unlock: · 24 unmodified lines | ||
| 903 | 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 | 991 | static int igt_reset_queue(void *arg) |
| 907 | 992 | { |
| 908 | 993 | struct drm_i915_private *i915 = arg; |
| @@ -951,27 +1036,49 @@ static int igt_reset_queue(void *arg) · 42 unmodified lines | ||
| 951 | 1036 | i915_request_get(rq); |
| 952 | 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 | 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", | |
| 958 | − __func__, prev->fence.seqno, hws_seqno(&h, prev)); | |
| 959 | − intel_engine_dump(prev->engine, &p, | |
| 960 | − "%s\n", prev->engine->name); | |
| 1064 | + pr_err("%s(%s): Failed to start request %x, at %x\n", | |
| 1065 | + __func__, engine->name, | |
| 1066 | + prev->fence.seqno, hws_seqno(&h, prev)); | |
| 1067 | + intel_engine_dump(engine, &p, | |
| 1068 | + "%s\n", engine->name); | |
| 961 | 1069 | |
| 962 | 1070 | i915_request_put(rq); |
| 963 | 1071 | i915_request_put(prev); |
| 964 | 1072 | |
| 965 | − i915_reset(i915, 0); | |
| 966 | 1073 | i915_gem_set_wedged(i915); |
| 967 | 1074 | |
| 968 | 1075 | err = -EIO; |
| 969 | 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 | 1083 | GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, |
| 977 | 1084 | &i915->gpu_error.flags)); |
| @@ -1044,7 +1151,7 @@ static int igt_handle_error(void *arg) · 66 unmodified lines | ||
| 1044 | 1151 | if (!intel_has_reset_engine(i915)) |
| 1045 | 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 | 1155 | return 0; |
| 1049 | 1156 | |
| 1050 | 1157 | mutex_lock(&i915->drm.struct_mutex); |
| @@ -1062,14 +1169,13 @@ static int igt_handle_error(void *arg) · 11 unmodified lines | ||
| 1062 | 1169 | i915_request_get(rq); |
| 1063 | 1170 | __i915_request_add(rq, true); |
| 1064 | 1171 | |
| 1065 | − if (!wait_for_hang(&h, rq)) { | |
| 1172 | + if (!wait_until_running(&h, rq)) { | |
| 1066 | 1173 | struct drm_printer p = drm_info_printer(i915->drm.dev); |
| 1067 | 1174 | |
| 1068 | 1175 | pr_err("%s: Failed to start request %x, at %x\n", |
| 1069 | 1176 | __func__, rq->fence.seqno, hws_seqno(&h, rq)); |
| 1070 | 1177 | intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); |
| 1071 | 1178 | |
| 1072 | − i915_reset(i915, 0); | |
| 1073 | 1179 | i915_gem_set_wedged(i915); |
| 1074 | 1180 | |
| 1075 | 1181 | err = -EIO; |
| @@ -1081,10 +1187,7 @@ static int igt_handle_error(void *arg) · 5 unmodified lines | ||
| 1081 | 1187 | /* Temporarily disable error capture */ |
| 1082 | 1188 | error = xchg(&i915->gpu_error.first_error, (void *)-1); |
| 1083 | 1189 | |
| 1084 | − engine->hangcheck.stalled = true; | |
| 1085 | − engine->hangcheck.seqno = intel_engine_get_seqno(engine); | |
| 1086 | − | |
| 1087 | − i915_handle_error(i915, intel_engine_flag(engine), "%s", __func__); | |
| 1190 | + i915_handle_error(i915, ENGINE_MASK(engine->id), 0, NULL); | |
| 1088 | 1191 | |
| 1089 | 1192 | xchg(&i915->gpu_error.first_error, error); |
| 1090 | 1193 | |
| @@ -1112,8 +1215,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) · 21 unmodified lines | ||
| 1112 | 1215 | SUBTEST(igt_hang_sanitycheck), |
| 1113 | 1216 | SUBTEST(igt_reset_idle_engine), |
| 1114 | 1217 | SUBTEST(igt_reset_active_engine), |
| 1115 | − SUBTEST(igt_reset_idle_engine_others), | |
| 1116 | − SUBTEST(igt_reset_active_engine_others), | |
| 1218 | + SUBTEST(igt_reset_engines), | |
| 1117 | 1219 | SUBTEST(igt_wait_reset), |
| 1118 | 1220 | SUBTEST(igt_reset_queue), |
| 1119 | 1221 | SUBTEST(igt_handle_error), |
| @@ -1129,6 +1231,10 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) · 9 unmodified lines | ||
| 1129 | 1231 | |
| 1130 | 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 | 1238 | i915_modparams.enable_hangcheck = saved_hangcheck; |
| 1133 | 1239 | intel_runtime_pm_put(i915); |
| 1134 | 1240 | |
| @@ -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 | +} | |
| @@ -478,6 +478,7 @@ · 477 unmodified lines | ||
| 478 | 478 | # define DP_PSR_FRAME_CAPTURE (1 << 3) |
| 479 | 479 | # define DP_PSR_SELECTIVE_UPDATE (1 << 4) |
| 480 | 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 | 483 | #define DP_ADAPTER_CTRL 0x1a0 |
| 483 | 484 | # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) |
| @@ -794,6 +795,15 @@ · 310 unmodified lines | ||
| 794 | 795 | # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) |
| 795 | 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 | 807 | #define DP_RECEIVER_ALPM_STATUS 0x200b /* eDP 1.4 */ |
| 798 | 808 | # define DP_ALPM_LOCK_TIMEOUT_ERROR (1 << 0) |
| 799 | 809 | |