More change sets for 4.16: - Many improvements for selftests and other igt tests (Chris) - Forcewake with PUNIT->PMIC bus fixes and robustness (Hans) - Define an engine class for uABI (Tvrtko) - Context switch fixes and improvements (Chris) - GT powersavings and power gating simplification and fixes (Chris) - Other general driver clean-ups (Chris, Lucas, Ville) - Removing old, useless and/or bad workarounds (Chris, Oscar, Radhakrishna) - IPS, pipe config, etc in preparation for another Fast Boot attempt (Maarten) - OA perf fixes and support to Coffee Lake and Cannonlake (Lionel) - Fixes around GPU fault registers (Michel) - GEM Proxy (Tina) - Refactor of Geminilake and Cannonlake plane color handling (James) - Generalize transcoder loop (Mika Kahola) - New HW Workaround for Cannonlake and Geminilake (Rodrigo) - Resume GuC before using GEM (Chris) - Stolen Memory handling improvements (Ville) - Initialize entry in PPAT for older compilers (Chris) - Other fixes and robustness improvements on execbuf (Chris) - Improve logs of GEM_BUG_ON (Mika Kuoppala) - Rework with massive rename of GuC functions and files (Sagar) - Don't sanitize frame start delay if pipe is off (Ville) - Cannonlake clock fixes (Rodrigo) - Cannonlake HDMI 2.0 support (Rodrigo) - Add a GuC doorbells selftest (Michel) - Add might_sleep() check to our wait_for() (Chris) Many GVT changes for 4.16: - CSB HWSP update support (Weinan) - GVT debug helpers, dyndbg and debugfs (Chuanxiao, Shuo) - full virtualized opregion (Xiaolin) - VM health check for sane fallback (Fred) - workload submission code refactor for future enabling (Zhi) - Updated repo URL in MAINTAINERS (Zhenyu) - other many misc fixes * tag 'drm-intel-next-2017-11-17-1' of git://anongit.freedesktop.org/drm/drm-intel: (260 commits) drm/i915: Update DRIVER_DATE to 20171117 drm/i915: Add a policy note for removing workarounds drm/i915/selftests: Report ENOMEM clearly for an allocation failure Revert "drm/i915: Display WA #1133 WaFbcSkipSegments:cnl, glk" drm/i915: Calculate g4x intermediate watermarks correctly drm/i915: Calculate vlv/chv intermediate watermarks correctly, v3. drm/i915: Pass crtc_state to ips toggle functions, v2 drm/i915: Pass idle crtc_state to intel_dp_sink_crc drm/i915: Enable FIFO underrun reporting after initial fastset, v4. drm/i915: Mark the userptr invalidate workqueue as WQ_MEM_RECLAIM drm/i915: Add might_sleep() check to wait_for() drm/i915/selftests: Add a GuC doorbells selftest drm/i915/cnl: Extend HDMI 2.0 support to CNL. drm/i915/cnl: Simplify dco_fraction calculation. drm/i915/cnl: Don't blindly replace qdiv. drm/i915/cnl: Fix wrpll math for higher freqs. drm/i915/cnl: Fix, simplify and unify wrpll variable sizes. drm/i915/cnl: Remove useless conversion. drm/i915/cnl: Remove spurious central_freq. drm/i915/selftests: exercise_ggtt may have nothing to do ...
Unified · Split
| @@ -350,10 +350,10 @@ GuC-specific firmware loader · 349 unmodified lines | ||
| 350 | 350 | GuC-based command submission |
| 351 | 351 | ---------------------------- |
| 352 | 352 | |
| 353 | −.. kernel-doc:: drivers/gpu/drm/i915/i915_guc_submission.c | |
| 353 | +.. kernel-doc:: drivers/gpu/drm/i915/intel_guc_submission.c | |
| 354 | 354 | :doc: GuC-based command submission |
| 355 | 355 | |
| 356 | −.. kernel-doc:: drivers/gpu/drm/i915/i915_guc_submission.c | |
| 356 | +.. kernel-doc:: drivers/gpu/drm/i915/intel_guc_submission.c | |
| 357 | 357 | :internal: |
| 358 | 358 | |
| 359 | 359 | GuC Firmware Layout |
| @@ -7030,7 +7030,7 @@ M: Zhi Wang <zhi.a.wang@intel.com> · 7029 unmodified lines | ||
| 7030 | 7030 | L: intel-gvt-dev@lists.freedesktop.org |
| 7031 | 7031 | L: intel-gfx@lists.freedesktop.org |
| 7032 | 7032 | W: https://01.org/igvt-g |
| 7033 | −T: git https://github.com/01org/gvt-linux.git | |
| 7033 | +T: git https://github.com/intel/gvt-linux.git | |
| 7034 | 7034 | S: Supported |
| 7035 | 7035 | F: drivers/gpu/drm/i915/gvt/ |
| 7036 | 7036 | |
| @@ -146,6 +146,18 @@ int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb); · 145 unmodified lines | ||
| 146 | 146 | */ |
| 147 | 147 | int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb); |
| 148 | 148 | |
| 149 | +/** | |
| 150 | + * iosf_mbi_unregister_pmic_bus_access_notifier_unlocked - Unregister PMIC bus | |
| 151 | + * notifier, unlocked | |
| 152 | + * | |
| 153 | + * Like iosf_mbi_unregister_pmic_bus_access_notifier(), but for use when the | |
| 154 | + * caller has already called iosf_mbi_punit_acquire() itself. | |
| 155 | + * | |
| 156 | + * @nb: notifier_block to unregister | |
| 157 | + */ | |
| 158 | +int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( | |
| 159 | + struct notifier_block *nb); | |
| 160 | + | |
| 149 | 161 | /** |
| 150 | 162 | * iosf_mbi_call_pmic_bus_access_notifier_chain - Call PMIC bus notifier chain |
| 151 | 163 | * |
| @@ -154,6 +166,11 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb); · 2 unmodified lines | ||
| 154 | 166 | */ |
| 155 | 167 | int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v); |
| 156 | 168 | |
| 169 | +/** | |
| 170 | + * iosf_mbi_assert_punit_acquired - Assert that the P-Unit has been acquired. | |
| 171 | + */ | |
| 172 | +void iosf_mbi_assert_punit_acquired(void); | |
| 173 | + | |
| 157 | 174 | #else /* CONFIG_IOSF_MBI is not enabled */ |
| 158 | 175 | static inline |
| 159 | 176 | bool iosf_mbi_available(void) |
| @@ -197,12 +214,20 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) · 37 unmodified lines | ||
| 197 | 214 | return 0; |
| 198 | 215 | } |
| 199 | 216 | |
| 217 | +static inline int | |
| 218 | +iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(struct notifier_block *nb) | |
| 219 | +{ | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | + | |
| 200 | 223 | static inline |
| 201 | 224 | int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) |
| 202 | 225 | { |
| 203 | 226 | return 0; |
| 204 | 227 | } |
| 205 | 228 | |
| 229 | +static inline void iosf_mbi_assert_punit_acquired(void) {} | |
| 230 | + | |
| 206 | 231 | #endif /* CONFIG_IOSF_MBI */ |
| 207 | 232 | |
| 208 | 233 | #endif /* IOSF_MBI_SYMS_H */ |
| @@ -218,14 +218,23 @@ int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb) · 217 unmodified lines | ||
| 218 | 218 | } |
| 219 | 219 | EXPORT_SYMBOL(iosf_mbi_register_pmic_bus_access_notifier); |
| 220 | 220 | |
| 221 | +int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( | |
| 222 | + struct notifier_block *nb) | |
| 223 | +{ | |
| 224 | + iosf_mbi_assert_punit_acquired(); | |
| 225 | + | |
| 226 | + return blocking_notifier_chain_unregister( | |
| 227 | + &iosf_mbi_pmic_bus_access_notifier, nb); | |
| 228 | +} | |
| 229 | +EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier_unlocked); | |
| 230 | + | |
| 221 | 231 | int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) |
| 222 | 232 | { |
| 223 | 233 | int ret; |
| 224 | 234 | |
| 225 | 235 | /* Wait for the bus to go inactive before unregistering */ |
| 226 | 236 | mutex_lock(&iosf_mbi_punit_mutex); |
| 227 | − ret = blocking_notifier_chain_unregister( | |
| 228 | − &iosf_mbi_pmic_bus_access_notifier, nb); | |
| 237 | + ret = iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(nb); | |
| 229 | 238 | mutex_unlock(&iosf_mbi_punit_mutex); |
| 230 | 239 | |
| 231 | 240 | return ret; |
| @@ -239,6 +248,12 @@ int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) · 7 unmodified lines | ||
| 239 | 248 | } |
| 240 | 249 | EXPORT_SYMBOL(iosf_mbi_call_pmic_bus_access_notifier_chain); |
| 241 | 250 | |
| 251 | +void iosf_mbi_assert_punit_acquired(void) | |
| 252 | +{ | |
| 253 | + WARN_ON(!mutex_is_locked(&iosf_mbi_punit_mutex)); | |
| 254 | +} | |
| 255 | +EXPORT_SYMBOL(iosf_mbi_assert_punit_acquired); | |
| 256 | + | |
| 242 | 257 | #ifdef CONFIG_IOSF_MBI_DEBUG |
| 243 | 258 | static u32 dbg_mdr; |
| 244 | 259 | static u32 dbg_mcr; |
| @@ -28,6 +28,7 @@ config DRM_I915_DEBUG · 27 unmodified lines | ||
| 28 | 28 | select SW_SYNC # signaling validation framework (igt/syncobj*) |
| 29 | 29 | select DRM_I915_SW_FENCE_DEBUG_OBJECTS |
| 30 | 30 | select DRM_I915_SELFTEST |
| 31 | + select DRM_I915_TRACE_GEM | |
| 31 | 32 | default n |
| 32 | 33 | help |
| 33 | 34 | Choose this option to turn on extra driver debugging that may affect |
| @@ -49,6 +50,19 @@ config DRM_I915_DEBUG_GEM · 15 unmodified lines | ||
| 49 | 50 | |
| 50 | 51 | If in doubt, say "N". |
| 51 | 52 | |
| 53 | +config DRM_I915_TRACE_GEM | |
| 54 | + bool "Insert extra ftrace output from the GEM internals" | |
| 55 | + select TRACING | |
| 56 | + default n | |
| 57 | + help | |
| 58 | + Enable additional and verbose debugging output that will spam | |
| 59 | + ordinary tests, but may be vital for post-mortem debugging when | |
| 60 | + used with /proc/sys/kernel/ftrace_dump_on_oops | |
| 61 | + | |
| 62 | + Recommended for driver developers only. | |
| 63 | + | |
| 64 | + If in doubt, say "N". | |
| 65 | + | |
| 52 | 66 | config DRM_I915_SW_FENCE_DEBUG_OBJECTS |
| 53 | 67 | bool "Enable additional driver debugging for fence objects" |
| 54 | 68 | depends on DRM_I915 |
| @@ -90,6 +104,20 @@ config DRM_I915_SELFTEST · 35 unmodified lines | ||
| 90 | 104 | |
| 91 | 105 | If in doubt, say "N". |
| 92 | 106 | |
| 107 | +config DRM_I915_SELFTEST_BROKEN | |
| 108 | + bool "Enable broken and dangerous selftests" | |
| 109 | + depends on DRM_I915_SELFTEST | |
| 110 | + depends on BROKEN | |
| 111 | + default n | |
| 112 | + help | |
| 113 | + This option enables the execution of selftests that are "dangerous" | |
| 114 | + and may trigger unintended HW side-effects as they break strict | |
| 115 | + rules given in the HW specification. For science. | |
| 116 | + | |
| 117 | + Recommended for masochistic driver developers only. | |
| 118 | + | |
| 119 | + If in doubt, say "N". | |
| 120 | + | |
| 93 | 121 | config DRM_I915_LOW_LEVEL_TRACEPOINTS |
| 94 | 122 | bool "Enable low level request tracing events" |
| 95 | 123 | depends on DRM_I915 |
| @@ -3,7 +3,26 @@ · 2 unmodified lines | ||
| 3 | 3 | # Makefile for the drm device driver. This driver provides support for the |
| 4 | 4 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
| 5 | 5 | |
| 6 | −subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror | |
| 6 | +# Add a set of useful warning flags and enable -Werror for CI to prevent | |
| 7 | +# trivial mistakes from creeping in. We have to do this piecemeal as we reject | |
| 8 | +# any patch that isn't warning clean, so turning on -Wall -Wextra (or W=1) we | |
| 9 | +# need to filter out dubious warnings. Still it is our interest | |
| 10 | +# to keep running locally with W=1 C=1 until we are completely clean. | |
| 11 | +# | |
| 12 | +# Note the danger in using -Wall -Wextra is that when CI updates gcc we | |
| 13 | +# will most likely get a sudden build breakage... Hopefully we will fix | |
| 14 | +# new warnings before CI updates! | |
| 15 | +subdir-ccflags-y := -Wall -Wextra | |
| 16 | +subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) | |
| 17 | +subdir-ccflags-y += $(call cc-disable-warning, type-limits) | |
| 18 | +subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) | |
| 19 | +subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) | |
| 20 | +subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror | |
| 21 | + | |
| 22 | +# Fine grained warnings disable | |
| 23 | +CFLAGS_i915_pci.o = $(call cc-disable-warning, override-init) | |
| 24 | +CFLAGS_intel_fbdev.o = $(call cc-disable-warning, override-init) | |
| 25 | + | |
| 7 | 26 | subdir-ccflags-y += \ |
| 8 | 27 | $(call as-instr,movntdqa (%eax)$(comma)%xmm0,-DCONFIG_AS_MOVNTDQA) |
| 9 | 28 | |
| @@ -64,10 +83,10 @@ i915-y += intel_uc.o \ · 54 unmodified lines | ||
| 64 | 83 | intel_uc_fw.o \ |
| 65 | 84 | intel_guc.o \ |
| 66 | 85 | intel_guc_ct.o \ |
| 67 | − intel_guc_log.o \ | |
| 68 | 86 | intel_guc_fw.o \ |
| 69 | − intel_huc.o \ | |
| 70 | − i915_guc_submission.o | |
| 87 | + intel_guc_log.o \ | |
| 88 | + intel_guc_submission.o \ | |
| 89 | + intel_huc.o | |
| 71 | 90 | |
| 72 | 91 | # autogenerated null render state |
| 73 | 92 | i915-y += intel_renderstate_gen6.o \ |
| @@ -144,7 +163,9 @@ i915-y += i915_perf.o \ · 70 unmodified lines | ||
| 144 | 163 | i915_oa_kblgt2.o \ |
| 145 | 164 | i915_oa_kblgt3.o \ |
| 146 | 165 | i915_oa_glk.o \ |
| 147 | − i915_oa_cflgt2.o | |
| 166 | + i915_oa_cflgt2.o \ | |
| 167 | + i915_oa_cflgt3.o \ | |
| 168 | + i915_oa_cnl.o | |
| 148 | 169 | |
| 149 | 170 | ifeq ($(CONFIG_DRM_I915_GVT),y) |
| 150 | 171 | i915-y += intel_gvt.o |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | GVT_DIR := gvt |
| 3 | 3 | GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ |
| 4 | 4 | interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ |
| 5 | − execlist.o scheduler.o sched_policy.o render.o cmd_parser.o | |
| 5 | + execlist.o scheduler.o sched_policy.o render.o cmd_parser.o debugfs.o | |
| 6 | 6 | |
| 7 | 7 | ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) |
| 8 | 8 | i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) |
| @@ -208,6 +208,20 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu, · 207 unmodified lines | ||
| 208 | 208 | return 0; |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | +static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu, | |
| 212 | + unsigned int offset, void *p_data, unsigned int bytes) | |
| 213 | +{ | |
| 214 | + u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset); | |
| 215 | + u32 new = *(u32 *)(p_data); | |
| 216 | + | |
| 217 | + if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK) | |
| 218 | + /* We don't have rom, return size of 0. */ | |
| 219 | + *pval = 0; | |
| 220 | + else | |
| 221 | + vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); | |
| 222 | + return 0; | |
| 223 | +} | |
| 224 | + | |
| 211 | 225 | static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, |
| 212 | 226 | void *p_data, unsigned int bytes) |
| 213 | 227 | { |
| @@ -300,6 +314,11 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, · 86 unmodified lines | ||
| 300 | 314 | } |
| 301 | 315 | |
| 302 | 316 | switch (rounddown(offset, 4)) { |
| 317 | + case PCI_ROM_ADDRESS: | |
| 318 | + if (WARN_ON(!IS_ALIGNED(offset, 4))) | |
| 319 | + return -EINVAL; | |
| 320 | + return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes); | |
| 321 | + | |
| 303 | 322 | case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: |
| 304 | 323 | if (WARN_ON(!IS_ALIGNED(offset, 4))) |
| 305 | 324 | return -EINVAL; |
| @@ -375,6 +394,8 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, · 69 unmodified lines | ||
| 375 | 394 | pci_resource_len(gvt->dev_priv->drm.pdev, 0); |
| 376 | 395 | vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = |
| 377 | 396 | pci_resource_len(gvt->dev_priv->drm.pdev, 2); |
| 397 | + | |
| 398 | + memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); | |
| 378 | 399 | } |
| 379 | 400 | |
| 380 | 401 | /** |
| @@ -709,18 +709,13 @@ static void parser_exec_state_dump(struct parser_exec_state *s) · 708 unmodified lines | ||
| 709 | 709 | |
| 710 | 710 | print_opcode(cmd_val(s, 0), s->ring_id); |
| 711 | 711 | |
| 712 | − /* print the whole page to trace */ | |
| 713 | − pr_err(" ip_va=%p: %08x %08x %08x %08x\n", | |
| 714 | − s->ip_va, cmd_val(s, 0), cmd_val(s, 1), | |
| 715 | − cmd_val(s, 2), cmd_val(s, 3)); | |
| 716 | − | |
| 717 | 712 | s->ip_va = (u32 *)((((u64)s->ip_va) >> 12) << 12); |
| 718 | 713 | |
| 719 | 714 | while (cnt < 1024) { |
| 720 | − pr_err("ip_va=%p: ", s->ip_va); | |
| 715 | + gvt_dbg_cmd("ip_va=%p: ", s->ip_va); | |
| 721 | 716 | for (i = 0; i < 8; i++) |
| 722 | − pr_err("%08x ", cmd_val(s, i)); | |
| 723 | − pr_err("\n"); | |
| 717 | + gvt_dbg_cmd("%08x ", cmd_val(s, i)); | |
| 718 | + gvt_dbg_cmd("\n"); | |
| 724 | 719 | |
| 725 | 720 | s->ip_va += 8 * sizeof(u32); |
| 726 | 721 | cnt += 8; |
| @@ -825,7 +820,7 @@ static int force_nonpriv_reg_handler(struct parser_exec_state *s, · 98 unmodified lines | ||
| 825 | 820 | if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data)) { |
| 826 | 821 | gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n", |
| 827 | 822 | offset, data); |
| 828 | − return -EINVAL; | |
| 823 | + return -EPERM; | |
| 829 | 824 | } |
| 830 | 825 | return 0; |
| 831 | 826 | } |
| @@ -839,7 +834,7 @@ static int cmd_reg_handler(struct parser_exec_state *s, · 7 unmodified lines | ||
| 839 | 834 | if (offset + 4 > gvt->device_info.mmio_size) { |
| 840 | 835 | gvt_vgpu_err("%s access to (%x) outside of MMIO range\n", |
| 841 | 836 | cmd, offset); |
| 842 | − return -EINVAL; | |
| 837 | + return -EFAULT; | |
| 843 | 838 | } |
| 844 | 839 | |
| 845 | 840 | if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) { |
| @@ -854,8 +849,8 @@ static int cmd_reg_handler(struct parser_exec_state *s, · 8 unmodified lines | ||
| 854 | 849 | } |
| 855 | 850 | |
| 856 | 851 | if (is_force_nonpriv_mmio(offset) && |
| 857 | − force_nonpriv_reg_handler(s, offset, index)) | |
| 858 | − return -EINVAL; | |
| 852 | + force_nonpriv_reg_handler(s, offset, index)) | |
| 853 | + return -EPERM; | |
| 859 | 854 | |
| 860 | 855 | if (offset == i915_mmio_reg_offset(DERRMR) || |
| 861 | 856 | offset == i915_mmio_reg_offset(FORCEWAKE_MT)) { |
| @@ -894,11 +889,14 @@ static int cmd_handler_lri(struct parser_exec_state *s) · 32 unmodified lines | ||
| 894 | 889 | i915_mmio_reg_offset(DERRMR)) |
| 895 | 890 | ret |= 0; |
| 896 | 891 | else |
| 897 | − ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; | |
| 892 | + ret |= (cmd_reg_inhibit(s, i)) ? | |
| 893 | + -EBADRQC : 0; | |
| 898 | 894 | } |
| 899 | 895 | if (ret) |
| 900 | 896 | break; |
| 901 | 897 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lri"); |
| 898 | + if (ret) | |
| 899 | + break; | |
| 902 | 900 | } |
| 903 | 901 | return ret; |
| 904 | 902 | } |
| @@ -912,11 +910,15 @@ static int cmd_handler_lrr(struct parser_exec_state *s) · 7 unmodified lines | ||
| 912 | 910 | if (IS_BROADWELL(s->vgpu->gvt->dev_priv)) |
| 913 | 911 | ret |= ((cmd_reg_inhibit(s, i) || |
| 914 | 912 | (cmd_reg_inhibit(s, i + 1)))) ? |
| 915 | − -EINVAL : 0; | |
| 913 | + -EBADRQC : 0; | |
| 916 | 914 | if (ret) |
| 917 | 915 | break; |
| 918 | 916 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrr-src"); |
| 917 | + if (ret) | |
| 918 | + break; | |
| 919 | 919 | ret |= cmd_reg_handler(s, cmd_reg(s, i + 1), i, "lrr-dst"); |
| 920 | + if (ret) | |
| 921 | + break; | |
| 920 | 922 | } |
| 921 | 923 | return ret; |
| 922 | 924 | } |
| @@ -934,15 +936,19 @@ static int cmd_handler_lrm(struct parser_exec_state *s) · 11 unmodified lines | ||
| 934 | 936 | |
| 935 | 937 | for (i = 1; i < cmd_len;) { |
| 936 | 938 | if (IS_BROADWELL(gvt->dev_priv)) |
| 937 | − ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; | |
| 939 | + ret |= (cmd_reg_inhibit(s, i)) ? -EBADRQC : 0; | |
| 938 | 940 | if (ret) |
| 939 | 941 | break; |
| 940 | 942 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrm"); |
| 943 | + if (ret) | |
| 944 | + break; | |
| 941 | 945 | if (cmd_val(s, 0) & (1 << 22)) { |
| 942 | 946 | gma = cmd_gma(s, i + 1); |
| 943 | 947 | if (gmadr_bytes == 8) |
| 944 | 948 | gma |= (cmd_gma_hi(s, i + 2)) << 32; |
| 945 | 949 | ret |= cmd_address_audit(s, gma, sizeof(u32), false); |
| 950 | + if (ret) | |
| 951 | + break; | |
| 946 | 952 | } |
| 947 | 953 | i += gmadr_dw_number(s) + 1; |
| 948 | 954 | } |
| @@ -958,11 +964,15 @@ static int cmd_handler_srm(struct parser_exec_state *s) · 9 unmodified lines | ||
| 958 | 964 | |
| 959 | 965 | for (i = 1; i < cmd_len;) { |
| 960 | 966 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "srm"); |
| 967 | + if (ret) | |
| 968 | + break; | |
| 961 | 969 | if (cmd_val(s, 0) & (1 << 22)) { |
| 962 | 970 | gma = cmd_gma(s, i + 1); |
| 963 | 971 | if (gmadr_bytes == 8) |
| 964 | 972 | gma |= (cmd_gma_hi(s, i + 2)) << 32; |
| 965 | 973 | ret |= cmd_address_audit(s, gma, sizeof(u32), false); |
| 974 | + if (ret) | |
| 975 | + break; | |
| 966 | 976 | } |
| 967 | 977 | i += gmadr_dw_number(s) + 1; |
| 968 | 978 | } |
| @@ -1116,7 +1126,7 @@ static int gen8_decode_mi_display_flip(struct parser_exec_state *s, · 147 unmodified lines | ||
| 1116 | 1126 | |
| 1117 | 1127 | v = (dword0 & GENMASK(21, 19)) >> 19; |
| 1118 | 1128 | if (WARN_ON(v >= ARRAY_SIZE(gen8_plane_code))) |
| 1119 | − return -EINVAL; | |
| 1129 | + return -EBADRQC; | |
| 1120 | 1130 | |
| 1121 | 1131 | info->pipe = gen8_plane_code[v].pipe; |
| 1122 | 1132 | info->plane = gen8_plane_code[v].plane; |
| @@ -1136,7 +1146,7 @@ static int gen8_decode_mi_display_flip(struct parser_exec_state *s, · 13 unmodified lines | ||
| 1136 | 1146 | info->surf_reg = SPRSURF(info->pipe); |
| 1137 | 1147 | } else { |
| 1138 | 1148 | WARN_ON(1); |
| 1139 | − return -EINVAL; | |
| 1149 | + return -EBADRQC; | |
| 1140 | 1150 | } |
| 1141 | 1151 | return 0; |
| 1142 | 1152 | } |
| @@ -1185,7 +1195,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s, · 42 unmodified lines | ||
| 1185 | 1195 | |
| 1186 | 1196 | default: |
| 1187 | 1197 | gvt_vgpu_err("unknown plane code %d\n", plane); |
| 1188 | − return -EINVAL; | |
| 1198 | + return -EBADRQC; | |
| 1189 | 1199 | } |
| 1190 | 1200 | |
| 1191 | 1201 | info->stride_val = (dword1 & GENMASK(15, 6)) >> 6; |
| @@ -1348,10 +1358,13 @@ static unsigned long get_gma_bb_from_cmd(struct parser_exec_state *s, int index) · 156 unmodified lines | ||
| 1348 | 1358 | { |
| 1349 | 1359 | unsigned long addr; |
| 1350 | 1360 | unsigned long gma_high, gma_low; |
| 1351 | − int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | |
| 1361 | + struct intel_vgpu *vgpu = s->vgpu; | |
| 1362 | + int gmadr_bytes = vgpu->gvt->device_info.gmadr_bytes_in_cmd; | |
| 1352 | 1363 | |
| 1353 | − if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) | |
| 1364 | + if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) { | |
| 1365 | + gvt_vgpu_err("invalid gma bytes %d\n", gmadr_bytes); | |
| 1354 | 1366 | return INTEL_GVT_INVALID_ADDR; |
| 1367 | + } | |
| 1355 | 1368 | |
| 1356 | 1369 | gma_low = cmd_val(s, index) & BATCH_BUFFER_ADDR_MASK; |
| 1357 | 1370 | if (gmadr_bytes == 4) { |
| @@ -1374,16 +1387,16 @@ static inline int cmd_address_audit(struct parser_exec_state *s, · 16 unmodified lines | ||
| 1374 | 1387 | if (op_size > max_surface_size) { |
| 1375 | 1388 | gvt_vgpu_err("command address audit fail name %s\n", |
| 1376 | 1389 | s->info->name); |
| 1377 | − return -EINVAL; | |
| 1390 | + return -EFAULT; | |
| 1378 | 1391 | } |
| 1379 | 1392 | |
| 1380 | 1393 | if (index_mode) { |
| 1381 | − if (guest_gma >= GTT_PAGE_SIZE / sizeof(u64)) { | |
| 1382 | − ret = -EINVAL; | |
| 1394 | + if (guest_gma >= I915_GTT_PAGE_SIZE / sizeof(u64)) { | |
| 1395 | + ret = -EFAULT; | |
| 1383 | 1396 | goto err; |
| 1384 | 1397 | } |
| 1385 | 1398 | } else if (!intel_gvt_ggtt_validate_range(vgpu, guest_gma, op_size)) { |
| 1386 | − ret = -EINVAL; | |
| 1399 | + ret = -EFAULT; | |
| 1387 | 1400 | goto err; |
| 1388 | 1401 | } |
| 1389 | 1402 | |
| @@ -1439,7 +1452,7 @@ static inline int unexpected_cmd(struct parser_exec_state *s) · 49 unmodified lines | ||
| 1439 | 1452 | |
| 1440 | 1453 | gvt_vgpu_err("Unexpected %s in command buffer!\n", s->info->name); |
| 1441 | 1454 | |
| 1442 | − return -EINVAL; | |
| 1455 | + return -EBADRQC; | |
| 1443 | 1456 | } |
| 1444 | 1457 | |
| 1445 | 1458 | static int cmd_handler_mi_semaphore_wait(struct parser_exec_state *s) |
| @@ -1545,10 +1558,10 @@ static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm, · 99 unmodified lines | ||
| 1545 | 1558 | return -EFAULT; |
| 1546 | 1559 | } |
| 1547 | 1560 | |
| 1548 | − offset = gma & (GTT_PAGE_SIZE - 1); | |
| 1561 | + offset = gma & (I915_GTT_PAGE_SIZE - 1); | |
| 1549 | 1562 | |
| 1550 | − copy_len = (end_gma - gma) >= (GTT_PAGE_SIZE - offset) ? | |
| 1551 | − GTT_PAGE_SIZE - offset : end_gma - gma; | |
| 1563 | + copy_len = (end_gma - gma) >= (I915_GTT_PAGE_SIZE - offset) ? | |
| 1564 | + I915_GTT_PAGE_SIZE - offset : end_gma - gma; | |
| 1552 | 1565 | |
| 1553 | 1566 | intel_gvt_hypervisor_read_gpa(vgpu, gpa, va + len, copy_len); |
| 1554 | 1567 | |
| @@ -1576,110 +1589,113 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s) · 21 unmodified lines | ||
| 1576 | 1589 | return 1; |
| 1577 | 1590 | } |
| 1578 | 1591 | |
| 1579 | −static int find_bb_size(struct parser_exec_state *s) | |
| 1592 | +static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size) | |
| 1580 | 1593 | { |
| 1581 | 1594 | unsigned long gma = 0; |
| 1582 | 1595 | struct cmd_info *info; |
| 1583 | − int bb_size = 0; | |
| 1584 | 1596 | uint32_t cmd_len = 0; |
| 1585 | − bool met_bb_end = false; | |
| 1597 | + bool bb_end = false; | |
| 1586 | 1598 | struct intel_vgpu *vgpu = s->vgpu; |
| 1587 | 1599 | u32 cmd; |
| 1588 | 1600 | |
| 1601 | + *bb_size = 0; | |
| 1602 | + | |
| 1589 | 1603 | /* get the start gm address of the batch buffer */ |
| 1590 | 1604 | gma = get_gma_bb_from_cmd(s, 1); |
| 1591 | − cmd = cmd_val(s, 0); | |
| 1605 | + if (gma == INTEL_GVT_INVALID_ADDR) | |
| 1606 | + return -EFAULT; | |
| 1592 | 1607 | |
| 1608 | + cmd = cmd_val(s, 0); | |
| 1593 | 1609 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); |
| 1594 | 1610 | if (info == NULL) { |
| 1595 | 1611 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", |
| 1596 | 1612 | cmd, get_opcode(cmd, s->ring_id)); |
| 1597 | − return -EINVAL; | |
| 1613 | + return -EBADRQC; | |
| 1598 | 1614 | } |
| 1599 | 1615 | do { |
| 1600 | − copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | |
| 1601 | − gma, gma + 4, &cmd); | |
| 1616 | + if (copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | |
| 1617 | + gma, gma + 4, &cmd) < 0) | |
| 1618 | + return -EFAULT; | |
| 1602 | 1619 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); |
| 1603 | 1620 | if (info == NULL) { |
| 1604 | 1621 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", |
| 1605 | 1622 | cmd, get_opcode(cmd, s->ring_id)); |
| 1606 | − return -EINVAL; | |
| 1623 | + return -EBADRQC; | |
| 1607 | 1624 | } |
| 1608 | 1625 | |
| 1609 | 1626 | if (info->opcode == OP_MI_BATCH_BUFFER_END) { |
| 1610 | − met_bb_end = true; | |
| 1627 | + bb_end = true; | |
| 1611 | 1628 | } else if (info->opcode == OP_MI_BATCH_BUFFER_START) { |
| 1612 | − if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) { | |
| 1629 | + if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) | |
| 1613 | 1630 | /* chained batch buffer */ |
| 1614 | − met_bb_end = true; | |
| 1615 | − } | |
| 1631 | + bb_end = true; | |
| 1616 | 1632 | } |
| 1617 | 1633 | cmd_len = get_cmd_length(info, cmd) << 2; |
| 1618 | − bb_size += cmd_len; | |
| 1634 | + *bb_size += cmd_len; | |
| 1619 | 1635 | gma += cmd_len; |
| 1636 | + } while (!bb_end); | |
| 1620 | 1637 | |
| 1621 | − } while (!met_bb_end); | |
| 1622 | − | |
| 1623 | − return bb_size; | |
| 1638 | + return 0; | |
| 1624 | 1639 | } |
| 1625 | 1640 | |
| 1626 | 1641 | static int perform_bb_shadow(struct parser_exec_state *s) |
| 1627 | 1642 | { |
| 1628 | − struct intel_shadow_bb_entry *entry_obj; | |
| 1629 | 1643 | struct intel_vgpu *vgpu = s->vgpu; |
| 1644 | + struct intel_vgpu_shadow_bb *bb; | |
| 1630 | 1645 | unsigned long gma = 0; |
| 1631 | − int bb_size; | |
| 1632 | − void *dst = NULL; | |
| 1646 | + unsigned long bb_size; | |
| 1633 | 1647 | int ret = 0; |
| 1634 | 1648 | |
| 1635 | 1649 | /* get the start gm address of the batch buffer */ |
| 1636 | 1650 | gma = get_gma_bb_from_cmd(s, 1); |
| 1651 | + if (gma == INTEL_GVT_INVALID_ADDR) | |
| 1652 | + return -EFAULT; | |
| 1637 | 1653 | |
| 1638 | − /* get the size of the batch buffer */ | |
| 1639 | − bb_size = find_bb_size(s); | |
| 1640 | − if (bb_size < 0) | |
| 1641 | − return -EINVAL; | |
| 1654 | + ret = find_bb_size(s, &bb_size); | |
| 1655 | + if (ret) | |
| 1656 | + return ret; | |
| 1642 | 1657 | |
| 1643 | − /* allocate shadow batch buffer */ | |
| 1644 | − entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL); | |
| 1645 | − if (entry_obj == NULL) | |
| 1658 | + bb = kzalloc(sizeof(*bb), GFP_KERNEL); | |
| 1659 | + if (!bb) | |
| 1646 | 1660 | return -ENOMEM; |
| 1647 | 1661 | |
| 1648 | − entry_obj->obj = | |
| 1649 | − i915_gem_object_create(s->vgpu->gvt->dev_priv, | |
| 1650 | − roundup(bb_size, PAGE_SIZE)); | |
| 1651 | − if (IS_ERR(entry_obj->obj)) { | |
| 1652 | − ret = PTR_ERR(entry_obj->obj); | |
| 1653 | − goto free_entry; | |
| 1662 | + bb->obj = i915_gem_object_create(s->vgpu->gvt->dev_priv, | |
| 1663 | + roundup(bb_size, PAGE_SIZE)); | |
| 1664 | + if (IS_ERR(bb->obj)) { | |
| 1665 | + ret = PTR_ERR(bb->obj); | |
| 1666 | + goto err_free_bb; | |
| 1654 | 1667 | } |
| 1655 | − entry_obj->len = bb_size; | |
| 1656 | − INIT_LIST_HEAD(&entry_obj->list); | |
| 1657 | 1668 | |
| 1658 | − dst = i915_gem_object_pin_map(entry_obj->obj, I915_MAP_WB); | |
| 1659 | − if (IS_ERR(dst)) { | |
| 1660 | − ret = PTR_ERR(dst); | |
| 1661 | − goto put_obj; | |
| 1662 | − } | |
| 1669 | + ret = i915_gem_obj_prepare_shmem_write(bb->obj, &bb->clflush); | |
| 1670 | + if (ret) | |
| 1671 | + goto err_free_obj; | |
| 1663 | 1672 | |
| 1664 | − ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false); | |
| 1665 | − if (ret) { | |
| 1666 | − gvt_vgpu_err("failed to set shadow batch to CPU\n"); | |
| 1667 | − goto unmap_src; | |
| 1673 | + bb->va = i915_gem_object_pin_map(bb->obj, I915_MAP_WB); | |
| 1674 | + if (IS_ERR(bb->va)) { | |
| 1675 | + ret = PTR_ERR(bb->va); | |
| 1676 | + goto err_finish_shmem_access; | |
| 1668 | 1677 | } |
| 1669 | 1678 | |
| 1670 | − entry_obj->va = dst; | |
| 1671 | − entry_obj->bb_start_cmd_va = s->ip_va; | |
| 1679 | + if (bb->clflush & CLFLUSH_BEFORE) { | |
| 1680 | + drm_clflush_virt_range(bb->va, bb->obj->base.size); | |
| 1681 | + bb->clflush &= ~CLFLUSH_BEFORE; | |
| 1682 | + } | |
| 1672 | 1683 | |
| 1673 | − /* copy batch buffer to shadow batch buffer*/ | |
| 1674 | 1684 | ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, |
| 1675 | 1685 | gma, gma + bb_size, |
| 1676 | − dst); | |
| 1686 | + bb->va); | |
| 1677 | 1687 | if (ret < 0) { |
| 1678 | 1688 | gvt_vgpu_err("fail to copy guest ring buffer\n"); |
| 1679 | − goto unmap_src; | |
| 1689 | + ret = -EFAULT; | |
| 1690 | + goto err_unmap; | |
| 1680 | 1691 | } |
| 1681 | 1692 | |
| 1682 | − list_add(&entry_obj->list, &s->workload->shadow_bb); | |
| 1693 | + INIT_LIST_HEAD(&bb->list); | |
| 1694 | + list_add(&bb->list, &s->workload->shadow_bb); | |
| 1695 | + | |
| 1696 | + bb->accessing = true; | |
| 1697 | + bb->bb_start_cmd_va = s->ip_va; | |
| 1698 | + | |
| 1683 | 1699 | /* |
| 1684 | 1700 | * ip_va saves the virtual address of the shadow batch buffer, while |
| 1685 | 1701 | * ip_gma saves the graphics address of the original batch buffer. |
| @@ -1688,17 +1704,17 @@ static int perform_bb_shadow(struct parser_exec_state *s) · 2 unmodified lines | ||
| 1688 | 1704 | * buffer's gma in pair. After all, we don't want to pin the shadow |
| 1689 | 1705 | * buffer here (too early). |
| 1690 | 1706 | */ |
| 1691 | − s->ip_va = dst; | |
| 1707 | + s->ip_va = bb->va; | |
| 1692 | 1708 | s->ip_gma = gma; |
| 1693 | − | |
| 1694 | 1709 | return 0; |
| 1695 | − | |
| 1696 | −unmap_src: | |
| 1697 | − i915_gem_object_unpin_map(entry_obj->obj); | |
| 1698 | −put_obj: | |
| 1699 | − i915_gem_object_put(entry_obj->obj); | |
| 1700 | −free_entry: | |
| 1701 | − kfree(entry_obj); | |
| 1710 | +err_unmap: | |
| 1711 | + i915_gem_object_unpin_map(bb->obj); | |
| 1712 | +err_finish_shmem_access: | |
| 1713 | + i915_gem_obj_finish_shmem_access(bb->obj); | |
| 1714 | +err_free_obj: | |
| 1715 | + i915_gem_object_put(bb->obj); | |
| 1716 | +err_free_bb: | |
| 1717 | + kfree(bb); | |
| 1702 | 1718 | return ret; |
| 1703 | 1719 | } |
| 1704 | 1720 | |
| @@ -1710,13 +1726,13 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s) · 5 unmodified lines | ||
| 1710 | 1726 | |
| 1711 | 1727 | if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { |
| 1712 | 1728 | gvt_vgpu_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n"); |
| 1713 | − return -EINVAL; | |
| 1729 | + return -EFAULT; | |
| 1714 | 1730 | } |
| 1715 | 1731 | |
| 1716 | 1732 | second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1; |
| 1717 | 1733 | if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) { |
| 1718 | 1734 | gvt_vgpu_err("Jumping to 2nd level BB from RB is not allowed\n"); |
| 1719 | − return -EINVAL; | |
| 1735 | + return -EFAULT; | |
| 1720 | 1736 | } |
| 1721 | 1737 | |
| 1722 | 1738 | s->saved_buf_addr_type = s->buf_addr_type; |
| @@ -1740,7 +1756,6 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s) · 17 unmodified lines | ||
| 1740 | 1756 | if (ret < 0) |
| 1741 | 1757 | return ret; |
| 1742 | 1758 | } |
| 1743 | − | |
| 1744 | 1759 | return ret; |
| 1745 | 1760 | } |
| 1746 | 1761 | |
| @@ -2430,7 +2445,7 @@ static int cmd_parser_exec(struct parser_exec_state *s) · 683 unmodified lines | ||
| 2430 | 2445 | if (info == NULL) { |
| 2431 | 2446 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", |
| 2432 | 2447 | cmd, get_opcode(cmd, s->ring_id)); |
| 2433 | − return -EINVAL; | |
| 2448 | + return -EBADRQC; | |
| 2434 | 2449 | } |
| 2435 | 2450 | |
| 2436 | 2451 | s->info = info; |
| @@ -2465,6 +2480,10 @@ static inline bool gma_out_of_range(unsigned long gma, · 28 unmodified lines | ||
| 2465 | 2480 | return (gma > gma_tail) && (gma < gma_head); |
| 2466 | 2481 | } |
| 2467 | 2482 | |
| 2483 | +/* Keep the consistent return type, e.g EBADRQC for unknown | |
| 2484 | + * cmd, EFAULT for invalid address, EPERM for nonpriv. later | |
| 2485 | + * works as the input of VM healthy status. | |
| 2486 | + */ | |
| 2468 | 2487 | static int command_scan(struct parser_exec_state *s, |
| 2469 | 2488 | unsigned long rb_head, unsigned long rb_tail, |
| 2470 | 2489 | unsigned long rb_start, unsigned long rb_len) |
| @@ -2487,7 +2506,7 @@ static int command_scan(struct parser_exec_state *s, · 16 unmodified lines | ||
| 2487 | 2506 | s->ip_gma, rb_start, |
| 2488 | 2507 | gma_bottom); |
| 2489 | 2508 | parser_exec_state_dump(s); |
| 2490 | − return -EINVAL; | |
| 2509 | + return -EFAULT; | |
| 2491 | 2510 | } |
| 2492 | 2511 | if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) { |
| 2493 | 2512 | gvt_vgpu_err("ip_gma %lx out of range." |
| @@ -2516,7 +2535,7 @@ static int scan_workload(struct intel_vgpu_workload *workload) · 22 unmodified lines | ||
| 2516 | 2535 | int ret = 0; |
| 2517 | 2536 | |
| 2518 | 2537 | /* ring base is page aligned */ |
| 2519 | − if (WARN_ON(!IS_ALIGNED(workload->rb_start, GTT_PAGE_SIZE))) | |
| 2538 | + if (WARN_ON(!IS_ALIGNED(workload->rb_start, I915_GTT_PAGE_SIZE))) | |
| 2520 | 2539 | return -EINVAL; |
| 2521 | 2540 | |
| 2522 | 2541 | gma_head = workload->rb_start + workload->rb_head; |
| @@ -2565,7 +2584,8 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) · 42 unmodified lines | ||
| 2565 | 2584 | wa_ctx); |
| 2566 | 2585 | |
| 2567 | 2586 | /* ring base is page aligned */ |
| 2568 | − if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE))) | |
| 2587 | + if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, | |
| 2588 | + I915_GTT_PAGE_SIZE))) | |
| 2569 | 2589 | return -EINVAL; |
| 2570 | 2590 | |
| 2571 | 2591 | ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t); |
| @@ -2604,6 +2624,7 @@ out: · 32 unmodified lines | ||
| 2604 | 2624 | static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) |
| 2605 | 2625 | { |
| 2606 | 2626 | struct intel_vgpu *vgpu = workload->vgpu; |
| 2627 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 2607 | 2628 | unsigned long gma_head, gma_tail, gma_top, guest_rb_size; |
| 2608 | 2629 | void *shadow_ring_buffer_va; |
| 2609 | 2630 | int ring_id = workload->ring_id; |
| @@ -2619,19 +2640,21 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) · 9 unmodified lines | ||
| 2619 | 2640 | gma_tail = workload->rb_start + workload->rb_tail; |
| 2620 | 2641 | gma_top = workload->rb_start + guest_rb_size; |
| 2621 | 2642 | |
| 2622 | − if (workload->rb_len > vgpu->reserve_ring_buffer_size[ring_id]) { | |
| 2623 | − void *va = vgpu->reserve_ring_buffer_va[ring_id]; | |
| 2643 | + if (workload->rb_len > s->ring_scan_buffer_size[ring_id]) { | |
| 2644 | + void *p; | |
| 2645 | + | |
| 2624 | 2646 | /* realloc the new ring buffer if needed */ |
| 2625 | − vgpu->reserve_ring_buffer_va[ring_id] = | |
| 2626 | − krealloc(va, workload->rb_len, GFP_KERNEL); | |
| 2627 | − if (!vgpu->reserve_ring_buffer_va[ring_id]) { | |
| 2628 | − gvt_vgpu_err("fail to alloc reserve ring buffer\n"); | |
| 2647 | + p = krealloc(s->ring_scan_buffer[ring_id], workload->rb_len, | |
| 2648 | + GFP_KERNEL); | |
| 2649 | + if (!p) { | |
| 2650 | + gvt_vgpu_err("fail to re-alloc ring scan buffer\n"); | |
| 2629 | 2651 | return -ENOMEM; |
| 2630 | 2652 | } |
| 2631 | − vgpu->reserve_ring_buffer_size[ring_id] = workload->rb_len; | |
| 2653 | + s->ring_scan_buffer[ring_id] = p; | |
| 2654 | + s->ring_scan_buffer_size[ring_id] = workload->rb_len; | |
| 2632 | 2655 | } |
| 2633 | 2656 | |
| 2634 | − shadow_ring_buffer_va = vgpu->reserve_ring_buffer_va[ring_id]; | |
| 2657 | + shadow_ring_buffer_va = s->ring_scan_buffer[ring_id]; | |
| 2635 | 2658 | |
| 2636 | 2659 | /* get shadow ring buffer va */ |
| 2637 | 2660 | workload->shadow_ring_buffer_va = shadow_ring_buffer_va; |
| @@ -25,41 +25,41 @@ · 24 unmodified lines | ||
| 25 | 25 | #define __GVT_DEBUG_H__ |
| 26 | 26 | |
| 27 | 27 | #define gvt_err(fmt, args...) \ |
| 28 | − DRM_ERROR("gvt: "fmt, ##args) | |
| 28 | + pr_err("gvt: "fmt, ##args) | |
| 29 | 29 | |
| 30 | 30 | #define gvt_vgpu_err(fmt, args...) \ |
| 31 | 31 | do { \ |
| 32 | 32 | if (IS_ERR_OR_NULL(vgpu)) \ |
| 33 | − DRM_DEBUG_DRIVER("gvt: "fmt, ##args); \ | |
| 33 | + pr_err("gvt: "fmt, ##args); \ | |
| 34 | 34 | else \ |
| 35 | − DRM_DEBUG_DRIVER("gvt: vgpu %d: "fmt, vgpu->id, ##args);\ | |
| 35 | + pr_err("gvt: vgpu %d: "fmt, vgpu->id, ##args);\ | |
| 36 | 36 | } while (0) |
| 37 | 37 | |
| 38 | 38 | #define gvt_dbg_core(fmt, args...) \ |
| 39 | − DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) | |
| 39 | + pr_debug("gvt: core: "fmt, ##args) | |
| 40 | 40 | |
| 41 | 41 | #define gvt_dbg_irq(fmt, args...) \ |
| 42 | − DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args) | |
| 42 | + pr_debug("gvt: irq: "fmt, ##args) | |
| 43 | 43 | |
| 44 | 44 | #define gvt_dbg_mm(fmt, args...) \ |
| 45 | − DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args) | |
| 45 | + pr_debug("gvt: mm: "fmt, ##args) | |
| 46 | 46 | |
| 47 | 47 | #define gvt_dbg_mmio(fmt, args...) \ |
| 48 | − DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args) | |
| 48 | + pr_debug("gvt: mmio: "fmt, ##args) | |
| 49 | 49 | |
| 50 | 50 | #define gvt_dbg_dpy(fmt, args...) \ |
| 51 | − DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args) | |
| 51 | + pr_debug("gvt: dpy: "fmt, ##args) | |
| 52 | 52 | |
| 53 | 53 | #define gvt_dbg_el(fmt, args...) \ |
| 54 | − DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args) | |
| 54 | + pr_debug("gvt: el: "fmt, ##args) | |
| 55 | 55 | |
| 56 | 56 | #define gvt_dbg_sched(fmt, args...) \ |
| 57 | − DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args) | |
| 57 | + pr_debug("gvt: sched: "fmt, ##args) | |
| 58 | 58 | |
| 59 | 59 | #define gvt_dbg_render(fmt, args...) \ |
| 60 | − DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args) | |
| 60 | + pr_debug("gvt: render: "fmt, ##args) | |
| 61 | 61 | |
| 62 | 62 | #define gvt_dbg_cmd(fmt, args...) \ |
| 63 | − DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args) | |
| 63 | + pr_debug("gvt: cmd: "fmt, ##args) | |
| 64 | 64 | |
| 65 | 65 | #endif |
| @@ -0,0 +1,212 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright(c) 2011-2017 Intel Corporation. All rights reserved. | |
| 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 FROM, | |
| 20 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | + * SOFTWARE. | |
| 22 | + */ | |
| 23 | +#include <linux/debugfs.h> | |
| 24 | +#include <linux/list_sort.h> | |
| 25 | +#include "i915_drv.h" | |
| 26 | +#include "gvt.h" | |
| 27 | + | |
| 28 | +struct mmio_diff_param { | |
| 29 | + struct intel_vgpu *vgpu; | |
| 30 | + int total; | |
| 31 | + int diff; | |
| 32 | + struct list_head diff_mmio_list; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +struct diff_mmio { | |
| 36 | + struct list_head node; | |
| 37 | + u32 offset; | |
| 38 | + u32 preg; | |
| 39 | + u32 vreg; | |
| 40 | +}; | |
| 41 | + | |
| 42 | +/* Compare two diff_mmio items. */ | |
| 43 | +static int mmio_offset_compare(void *priv, | |
| 44 | + struct list_head *a, struct list_head *b) | |
| 45 | +{ | |
| 46 | + struct diff_mmio *ma; | |
| 47 | + struct diff_mmio *mb; | |
| 48 | + | |
| 49 | + ma = container_of(a, struct diff_mmio, node); | |
| 50 | + mb = container_of(b, struct diff_mmio, node); | |
| 51 | + if (ma->offset < mb->offset) | |
| 52 | + return -1; | |
| 53 | + else if (ma->offset > mb->offset) | |
| 54 | + return 1; | |
| 55 | + return 0; | |
| 56 | +} | |
| 57 | + | |
| 58 | +static inline int mmio_diff_handler(struct intel_gvt *gvt, | |
| 59 | + u32 offset, void *data) | |
| 60 | +{ | |
| 61 | + struct drm_i915_private *dev_priv = gvt->dev_priv; | |
| 62 | + struct mmio_diff_param *param = data; | |
| 63 | + struct diff_mmio *node; | |
| 64 | + u32 preg, vreg; | |
| 65 | + | |
| 66 | + preg = I915_READ_NOTRACE(_MMIO(offset)); | |
| 67 | + vreg = vgpu_vreg(param->vgpu, offset); | |
| 68 | + | |
| 69 | + if (preg != vreg) { | |
| 70 | + node = kmalloc(sizeof(*node), GFP_KERNEL); | |
| 71 | + if (!node) | |
| 72 | + return -ENOMEM; | |
| 73 | + | |
| 74 | + node->offset = offset; | |
| 75 | + node->preg = preg; | |
| 76 | + node->vreg = vreg; | |
| 77 | + list_add(&node->node, ¶m->diff_mmio_list); | |
| 78 | + param->diff++; | |
| 79 | + } | |
| 80 | + param->total++; | |
| 81 | + return 0; | |
| 82 | +} | |
| 83 | + | |
| 84 | +/* Show the all the different values of tracked mmio. */ | |
| 85 | +static int vgpu_mmio_diff_show(struct seq_file *s, void *unused) | |
| 86 | +{ | |
| 87 | + struct intel_vgpu *vgpu = s->private; | |
| 88 | + struct intel_gvt *gvt = vgpu->gvt; | |
| 89 | + struct mmio_diff_param param = { | |
| 90 | + .vgpu = vgpu, | |
| 91 | + .total = 0, | |
| 92 | + .diff = 0, | |
| 93 | + }; | |
| 94 | + struct diff_mmio *node, *next; | |
| 95 | + | |
| 96 | + INIT_LIST_HEAD(¶m.diff_mmio_list); | |
| 97 | + | |
| 98 | + mutex_lock(&gvt->lock); | |
| 99 | + spin_lock_bh(&gvt->scheduler.mmio_context_lock); | |
| 100 | + | |
| 101 | + mmio_hw_access_pre(gvt->dev_priv); | |
| 102 | + /* Recognize all the diff mmios to list. */ | |
| 103 | + intel_gvt_for_each_tracked_mmio(gvt, mmio_diff_handler, ¶m); | |
| 104 | + mmio_hw_access_post(gvt->dev_priv); | |
| 105 | + | |
| 106 | + spin_unlock_bh(&gvt->scheduler.mmio_context_lock); | |
| 107 | + mutex_unlock(&gvt->lock); | |
| 108 | + | |
| 109 | + /* In an ascending order by mmio offset. */ | |
| 110 | + list_sort(NULL, ¶m.diff_mmio_list, mmio_offset_compare); | |
| 111 | + | |
| 112 | + seq_printf(s, "%-8s %-8s %-8s %-8s\n", "Offset", "HW", "vGPU", "Diff"); | |
| 113 | + list_for_each_entry_safe(node, next, ¶m.diff_mmio_list, node) { | |
| 114 | + u32 diff = node->preg ^ node->vreg; | |
| 115 | + | |
| 116 | + seq_printf(s, "%08x %08x %08x %*pbl\n", | |
| 117 | + node->offset, node->preg, node->vreg, | |
| 118 | + 32, &diff); | |
| 119 | + list_del(&node->node); | |
| 120 | + kfree(node); | |
| 121 | + } | |
| 122 | + seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff); | |
| 123 | + return 0; | |
| 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 | +}; | |
| 137 | + | |
| 138 | +/** | |
| 139 | + * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU | |
| 140 | + * @vgpu: a vGPU | |
| 141 | + * | |
| 142 | + * Returns: | |
| 143 | + * Zero on success, negative error code if failed. | |
| 144 | + */ | |
| 145 | +int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu) | |
| 146 | +{ | |
| 147 | + struct dentry *ent; | |
| 148 | + char name[10] = ""; | |
| 149 | + | |
| 150 | + sprintf(name, "vgpu%d", vgpu->id); | |
| 151 | + vgpu->debugfs = debugfs_create_dir(name, vgpu->gvt->debugfs_root); | |
| 152 | + if (!vgpu->debugfs) | |
| 153 | + return -ENOMEM; | |
| 154 | + | |
| 155 | + ent = debugfs_create_bool("active", 0444, vgpu->debugfs, | |
| 156 | + &vgpu->active); | |
| 157 | + if (!ent) | |
| 158 | + return -ENOMEM; | |
| 159 | + | |
| 160 | + ent = debugfs_create_file("mmio_diff", 0444, vgpu->debugfs, | |
| 161 | + vgpu, &vgpu_mmio_diff_fops); | |
| 162 | + if (!ent) | |
| 163 | + return -ENOMEM; | |
| 164 | + | |
| 165 | + return 0; | |
| 166 | +} | |
| 167 | + | |
| 168 | +/** | |
| 169 | + * intel_gvt_debugfs_remove_vgpu - remove debugfs entries of a vGPU | |
| 170 | + * @vgpu: a vGPU | |
| 171 | + */ | |
| 172 | +void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu) | |
| 173 | +{ | |
| 174 | + debugfs_remove_recursive(vgpu->debugfs); | |
| 175 | + vgpu->debugfs = NULL; | |
| 176 | +} | |
| 177 | + | |
| 178 | +/** | |
| 179 | + * intel_gvt_debugfs_init - register gvt debugfs root entry | |
| 180 | + * @gvt: GVT device | |
| 181 | + * | |
| 182 | + * Returns: | |
| 183 | + * zero on success, negative if failed. | |
| 184 | + */ | |
| 185 | +int intel_gvt_debugfs_init(struct intel_gvt *gvt) | |
| 186 | +{ | |
| 187 | + struct drm_minor *minor = gvt->dev_priv->drm.primary; | |
| 188 | + struct dentry *ent; | |
| 189 | + | |
| 190 | + gvt->debugfs_root = debugfs_create_dir("gvt", minor->debugfs_root); | |
| 191 | + if (!gvt->debugfs_root) { | |
| 192 | + gvt_err("Cannot create debugfs dir\n"); | |
| 193 | + return -ENOMEM; | |
| 194 | + } | |
| 195 | + | |
| 196 | + ent = debugfs_create_ulong("num_tracked_mmio", 0444, gvt->debugfs_root, | |
| 197 | + &gvt->mmio.num_tracked_mmio); | |
| 198 | + if (!ent) | |
| 199 | + return -ENOMEM; | |
| 200 | + | |
| 201 | + return 0; | |
| 202 | +} | |
| 203 | + | |
| 204 | +/** | |
| 205 | + * intel_gvt_debugfs_clean - remove debugfs entries | |
| 206 | + * @gvt: GVT device | |
| 207 | + */ | |
| 208 | +void intel_gvt_debugfs_clean(struct intel_gvt *gvt) | |
| 209 | +{ | |
| 210 | + debugfs_remove_recursive(gvt->debugfs_root); | |
| 211 | + gvt->debugfs_root = NULL; | |
| 212 | +} | |
| @@ -46,8 +46,6 @@ · 45 unmodified lines | ||
| 46 | 46 | #define same_context(a, b) (((a)->context_id == (b)->context_id) && \ |
| 47 | 47 | ((a)->lrca == (b)->lrca)) |
| 48 | 48 | |
| 49 | −static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask); | |
| 50 | − | |
| 51 | 49 | static int context_switch_events[] = { |
| 52 | 50 | [RCS] = RCS_AS_CONTEXT_SWITCH, |
| 53 | 51 | [BCS] = BCS_AS_CONTEXT_SWITCH, |
| @@ -135,6 +133,8 @@ static void emulate_csb_update(struct intel_vgpu_execlist *execlist, · 81 unmodified lines | ||
| 135 | 133 | struct execlist_context_status_pointer_format ctx_status_ptr; |
| 136 | 134 | u32 write_pointer; |
| 137 | 135 | u32 ctx_status_ptr_reg, ctx_status_buf_reg, offset; |
| 136 | + unsigned long hwsp_gpa; | |
| 137 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 138 | 138 | |
| 139 | 139 | ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, |
| 140 | 140 | _EL_OFFSET_STATUS_PTR); |
| @@ -160,6 +160,20 @@ static void emulate_csb_update(struct intel_vgpu_execlist *execlist, · 19 unmodified lines | ||
| 160 | 160 | ctx_status_ptr.write_ptr = write_pointer; |
| 161 | 161 | vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; |
| 162 | 162 | |
| 163 | + /* Update the CSB and CSB write pointer in HWSP */ | |
| 164 | + hwsp_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | |
| 165 | + vgpu->hws_pga[ring_id]); | |
| 166 | + if (hwsp_gpa != INTEL_GVT_INVALID_ADDR) { | |
| 167 | + intel_gvt_hypervisor_write_gpa(vgpu, | |
| 168 | + hwsp_gpa + I915_HWS_CSB_BUF0_INDEX * 4 + | |
| 169 | + write_pointer * 8, | |
| 170 | + status, 8); | |
| 171 | + intel_gvt_hypervisor_write_gpa(vgpu, | |
| 172 | + hwsp_gpa + | |
| 173 | + intel_hws_csb_write_index(dev_priv) * 4, | |
| 174 | + &write_pointer, 4); | |
| 175 | + } | |
| 176 | + | |
| 163 | 177 | gvt_dbg_el("vgpu%d: w pointer %u reg %x csb l %x csb h %x\n", |
| 164 | 178 | vgpu->id, write_pointer, offset, status->ldw, status->udw); |
| 165 | 179 | |
| @@ -358,218 +372,47 @@ static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, · 192 unmodified lines | ||
| 358 | 372 | return 0; |
| 359 | 373 | } |
| 360 | 374 | |
| 361 | −static void free_workload(struct intel_vgpu_workload *workload) | |
| 362 | −{ | |
| 363 | − intel_vgpu_unpin_mm(workload->shadow_mm); | |
| 364 | − intel_gvt_mm_unreference(workload->shadow_mm); | |
| 365 | − kmem_cache_free(workload->vgpu->workloads, workload); | |
| 366 | −} | |
| 367 | − | |
| 368 | 375 | #define get_desc_from_elsp_dwords(ed, i) \ |
| 369 | 376 | ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) |
| 370 | 377 | |
| 371 | −static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |
| 372 | −{ | |
| 373 | − const int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | |
| 374 | − struct intel_shadow_bb_entry *entry_obj; | |
| 375 | − | |
| 376 | − /* pin the gem object to ggtt */ | |
| 377 | − list_for_each_entry(entry_obj, &workload->shadow_bb, list) { | |
| 378 | − struct i915_vma *vma; | |
| 379 | − | |
| 380 | − vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0); | |
| 381 | − if (IS_ERR(vma)) { | |
| 382 | − return PTR_ERR(vma); | |
| 383 | − } | |
| 384 | − | |
| 385 | − /* FIXME: we are not tracking our pinned VMA leaving it | |
| 386 | − * up to the core to fix up the stray pin_count upon | |
| 387 | − * free. | |
| 388 | − */ | |
| 389 | − | |
| 390 | − /* update the relocate gma with shadow batch buffer*/ | |
| 391 | − entry_obj->bb_start_cmd_va[1] = i915_ggtt_offset(vma); | |
| 392 | − if (gmadr_bytes == 8) | |
| 393 | − entry_obj->bb_start_cmd_va[2] = 0; | |
| 394 | − } | |
| 395 | − return 0; | |
| 396 | −} | |
| 397 | − | |
| 398 | −static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |
| 399 | −{ | |
| 400 | − struct intel_vgpu_workload *workload = container_of(wa_ctx, | |
| 401 | − struct intel_vgpu_workload, | |
| 402 | − wa_ctx); | |
| 403 | − int ring_id = workload->ring_id; | |
| 404 | − struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | |
| 405 | − struct drm_i915_gem_object *ctx_obj = | |
| 406 | − shadow_ctx->engine[ring_id].state->obj; | |
| 407 | − struct execlist_ring_context *shadow_ring_context; | |
| 408 | − struct page *page; | |
| 409 | − | |
| 410 | − page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | |
| 411 | − shadow_ring_context = kmap_atomic(page); | |
| 412 | − | |
| 413 | − shadow_ring_context->bb_per_ctx_ptr.val = | |
| 414 | − (shadow_ring_context->bb_per_ctx_ptr.val & | |
| 415 | − (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma; | |
| 416 | − shadow_ring_context->rcs_indirect_ctx.val = | |
| 417 | − (shadow_ring_context->rcs_indirect_ctx.val & | |
| 418 | − (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; | |
| 419 | − | |
| 420 | − kunmap_atomic(shadow_ring_context); | |
| 421 | − return 0; | |
| 422 | −} | |
| 423 | − | |
| 424 | −static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |
| 425 | −{ | |
| 426 | − struct i915_vma *vma; | |
| 427 | − unsigned char *per_ctx_va = | |
| 428 | − (unsigned char *)wa_ctx->indirect_ctx.shadow_va + | |
| 429 | − wa_ctx->indirect_ctx.size; | |
| 430 | − | |
| 431 | − if (wa_ctx->indirect_ctx.size == 0) | |
| 432 | − return 0; | |
| 433 | − | |
| 434 | − vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, | |
| 435 | − 0, CACHELINE_BYTES, 0); | |
| 436 | − if (IS_ERR(vma)) { | |
| 437 | − return PTR_ERR(vma); | |
| 438 | − } | |
| 439 | − | |
| 440 | − /* FIXME: we are not tracking our pinned VMA leaving it | |
| 441 | − * up to the core to fix up the stray pin_count upon | |
| 442 | − * free. | |
| 443 | − */ | |
| 444 | − | |
| 445 | − wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma); | |
| 446 | − | |
| 447 | − wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1); | |
| 448 | − memset(per_ctx_va, 0, CACHELINE_BYTES); | |
| 449 | − | |
| 450 | − update_wa_ctx_2_shadow_ctx(wa_ctx); | |
| 451 | − return 0; | |
| 452 | −} | |
| 453 | − | |
| 454 | −static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |
| 455 | −{ | |
| 456 | − /* release all the shadow batch buffer */ | |
| 457 | − if (!list_empty(&workload->shadow_bb)) { | |
| 458 | − struct intel_shadow_bb_entry *entry_obj = | |
| 459 | − list_first_entry(&workload->shadow_bb, | |
| 460 | − struct intel_shadow_bb_entry, | |
| 461 | − list); | |
| 462 | − struct intel_shadow_bb_entry *temp; | |
| 463 | − | |
| 464 | − list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, | |
| 465 | − list) { | |
| 466 | − i915_gem_object_unpin_map(entry_obj->obj); | |
| 467 | − i915_gem_object_put(entry_obj->obj); | |
| 468 | − list_del(&entry_obj->list); | |
| 469 | − kfree(entry_obj); | |
| 470 | − } | |
| 471 | − } | |
| 472 | −} | |
| 473 | − | |
| 474 | 378 | static int prepare_execlist_workload(struct intel_vgpu_workload *workload) |
| 475 | 379 | { |
| 476 | 380 | struct intel_vgpu *vgpu = workload->vgpu; |
| 381 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 477 | 382 | struct execlist_ctx_descriptor_format ctx[2]; |
| 478 | 383 | int ring_id = workload->ring_id; |
| 479 | 384 | int ret; |
| 480 | 385 | |
| 481 | − ret = intel_vgpu_pin_mm(workload->shadow_mm); | |
| 482 | − if (ret) { | |
| 483 | − gvt_vgpu_err("fail to vgpu pin mm\n"); | |
| 484 | − goto out; | |
| 485 | − } | |
| 486 | − | |
| 487 | − ret = intel_vgpu_sync_oos_pages(workload->vgpu); | |
| 488 | − if (ret) { | |
| 489 | − gvt_vgpu_err("fail to vgpu sync oos pages\n"); | |
| 490 | − goto err_unpin_mm; | |
| 491 | − } | |
| 492 | − | |
| 493 | − ret = intel_vgpu_flush_post_shadow(workload->vgpu); | |
| 494 | − if (ret) { | |
| 495 | − gvt_vgpu_err("fail to flush post shadow\n"); | |
| 496 | − goto err_unpin_mm; | |
| 497 | − } | |
| 498 | − | |
| 499 | − ret = intel_gvt_generate_request(workload); | |
| 500 | − if (ret) { | |
| 501 | − gvt_vgpu_err("fail to generate request\n"); | |
| 502 | − goto err_unpin_mm; | |
| 503 | − } | |
| 504 | − | |
| 505 | − ret = prepare_shadow_batch_buffer(workload); | |
| 506 | − if (ret) { | |
| 507 | − gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n"); | |
| 508 | − goto err_unpin_mm; | |
| 509 | − } | |
| 510 | − | |
| 511 | − ret = prepare_shadow_wa_ctx(&workload->wa_ctx); | |
| 512 | − if (ret) { | |
| 513 | − gvt_vgpu_err("fail to prepare_shadow_wa_ctx\n"); | |
| 514 | − goto err_shadow_batch; | |
| 515 | − } | |
| 516 | − | |
| 517 | 386 | if (!workload->emulate_schedule_in) |
| 518 | 387 | return 0; |
| 519 | 388 | |
| 520 | − ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); | |
| 521 | − ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); | |
| 389 | + ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); | |
| 390 | + ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); | |
| 522 | 391 | |
| 523 | − ret = emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); | |
| 524 | − if (!ret) | |
| 525 | − goto out; | |
| 526 | − else | |
| 392 | + ret = emulate_execlist_schedule_in(&s->execlist[ring_id], ctx); | |
| 393 | + if (ret) { | |
| 527 | 394 | gvt_vgpu_err("fail to emulate execlist schedule in\n"); |
| 528 | − | |
| 529 | − release_shadow_wa_ctx(&workload->wa_ctx); | |
| 530 | −err_shadow_batch: | |
| 531 | − release_shadow_batch_buffer(workload); | |
| 532 | −err_unpin_mm: | |
| 533 | − intel_vgpu_unpin_mm(workload->shadow_mm); | |
| 534 | −out: | |
| 535 | − return ret; | |
| 395 | + return ret; | |
| 396 | + } | |
| 397 | + return 0; | |
| 536 | 398 | } |
| 537 | 399 | |
| 538 | 400 | static int complete_execlist_workload(struct intel_vgpu_workload *workload) |
| 539 | 401 | { |
| 540 | 402 | struct intel_vgpu *vgpu = workload->vgpu; |
| 541 | 403 | int ring_id = workload->ring_id; |
| 542 | − struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; | |
| 404 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 405 | + struct intel_vgpu_execlist *execlist = &s->execlist[ring_id]; | |
| 543 | 406 | struct intel_vgpu_workload *next_workload; |
| 544 | 407 | struct list_head *next = workload_q_head(vgpu, ring_id)->next; |
| 545 | 408 | bool lite_restore = false; |
| 546 | − int ret; | |
| 409 | + int ret = 0; | |
| 547 | 410 | |
| 548 | 411 | gvt_dbg_el("complete workload %p status %d\n", workload, |
| 549 | 412 | workload->status); |
| 550 | 413 | |
| 551 | − if (!workload->status) { | |
| 552 | − release_shadow_batch_buffer(workload); | |
| 553 | − release_shadow_wa_ctx(&workload->wa_ctx); | |
| 554 | − } | |
| 555 | − | |
| 556 | − if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) { | |
| 557 | − /* if workload->status is not successful means HW GPU | |
| 558 | − * has occurred GPU hang or something wrong with i915/GVT, | |
| 559 | − * and GVT won't inject context switch interrupt to guest. | |
| 560 | − * So this error is a vGPU hang actually to the guest. | |
| 561 | − * According to this we should emunlate a vGPU hang. If | |
| 562 | − * there are pending workloads which are already submitted | |
| 563 | − * from guest, we should clean them up like HW GPU does. | |
| 564 | − * | |
| 565 | − * if it is in middle of engine resetting, the pending | |
| 566 | − * workloads won't be submitted to HW GPU and will be | |
| 567 | − * cleaned up during the resetting process later, so doing | |
| 568 | − * the workload clean up here doesn't have any impact. | |
| 569 | − **/ | |
| 570 | − clean_workloads(vgpu, ENGINE_MASK(ring_id)); | |
| 414 | + if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) | |
| 571 | 415 | goto out; |
| 572 | − } | |
| 573 | 416 | |
| 574 | 417 | if (!list_empty(workload_q_head(vgpu, ring_id))) { |
| 575 | 418 | struct execlist_ctx_descriptor_format *this_desc, *next_desc; |
| @@ -584,213 +427,60 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload) · 8 unmodified lines | ||
| 584 | 427 | |
| 585 | 428 | if (lite_restore) { |
| 586 | 429 | gvt_dbg_el("next context == current - no schedule-out\n"); |
| 587 | − free_workload(workload); | |
| 588 | − return 0; | |
| 430 | + goto out; | |
| 589 | 431 | } |
| 590 | 432 | |
| 591 | 433 | ret = emulate_execlist_ctx_schedule_out(execlist, &workload->ctx_desc); |
| 592 | − if (ret) | |
| 593 | − goto err; | |
| 594 | 434 | out: |
| 595 | − free_workload(workload); | |
| 596 | − return 0; | |
| 597 | −err: | |
| 598 | − free_workload(workload); | |
| 435 | + intel_vgpu_unpin_mm(workload->shadow_mm); | |
| 436 | + intel_vgpu_destroy_workload(workload); | |
| 599 | 437 | return ret; |
| 600 | 438 | } |
| 601 | 439 | |
| 602 | −#define RING_CTX_OFF(x) \ | |
| 603 | − offsetof(struct execlist_ring_context, x) | |
| 604 | − | |
| 605 | −static void read_guest_pdps(struct intel_vgpu *vgpu, | |
| 606 | − u64 ring_context_gpa, u32 pdp[8]) | |
| 607 | −{ | |
| 608 | − u64 gpa; | |
| 609 | − int i; | |
| 610 | − | |
| 611 | − gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val); | |
| 612 | − | |
| 613 | − for (i = 0; i < 8; i++) | |
| 614 | − intel_gvt_hypervisor_read_gpa(vgpu, | |
| 615 | − gpa + i * 8, &pdp[7 - i], 4); | |
| 616 | −} | |
| 617 | − | |
| 618 | −static int prepare_mm(struct intel_vgpu_workload *workload) | |
| 619 | −{ | |
| 620 | − struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; | |
| 621 | − struct intel_vgpu_mm *mm; | |
| 622 | − struct intel_vgpu *vgpu = workload->vgpu; | |
| 623 | − int page_table_level; | |
| 624 | − u32 pdp[8]; | |
| 625 | − | |
| 626 | − if (desc->addressing_mode == 1) { /* legacy 32-bit */ | |
| 627 | − page_table_level = 3; | |
| 628 | − } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ | |
| 629 | − page_table_level = 4; | |
| 630 | − } else { | |
| 631 | − gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n"); | |
| 632 | − return -EINVAL; | |
| 633 | − } | |
| 634 | − | |
| 635 | − read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); | |
| 636 | − | |
| 637 | − mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); | |
| 638 | − if (mm) { | |
| 639 | − intel_gvt_mm_reference(mm); | |
| 640 | − } else { | |
| 641 | − | |
| 642 | − mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, | |
| 643 | − pdp, page_table_level, 0); | |
| 644 | − if (IS_ERR(mm)) { | |
| 645 | − gvt_vgpu_err("fail to create mm object.\n"); | |
| 646 | − return PTR_ERR(mm); | |
| 647 | − } | |
| 648 | − } | |
| 649 | − workload->shadow_mm = mm; | |
| 650 | − return 0; | |
| 651 | −} | |
| 652 | − | |
| 653 | −#define get_last_workload(q) \ | |
| 654 | − (list_empty(q) ? NULL : container_of(q->prev, \ | |
| 655 | − struct intel_vgpu_workload, list)) | |
| 656 | − | |
| 657 | 440 | static int submit_context(struct intel_vgpu *vgpu, int ring_id, |
| 658 | 441 | struct execlist_ctx_descriptor_format *desc, |
| 659 | 442 | bool emulate_schedule_in) |
| 660 | 443 | { |
| 661 | − struct list_head *q = workload_q_head(vgpu, ring_id); | |
| 662 | − struct intel_vgpu_workload *last_workload = get_last_workload(q); | |
| 444 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 663 | 445 | struct intel_vgpu_workload *workload = NULL; |
| 664 | − struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 665 | − u64 ring_context_gpa; | |
| 666 | − u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx; | |
| 667 | − int ret; | |
| 668 | − | |
| 669 | − ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | |
| 670 | − (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT)); | |
| 671 | − if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { | |
| 672 | − gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca); | |
| 673 | − return -EINVAL; | |
| 674 | − } | |
| 675 | − | |
| 676 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 677 | − RING_CTX_OFF(ring_header.val), &head, 4); | |
| 678 | 446 | |
| 679 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 680 | − RING_CTX_OFF(ring_tail.val), &tail, 4); | |
| 447 | + workload = intel_vgpu_create_workload(vgpu, ring_id, desc); | |
| 448 | + if (IS_ERR(workload)) | |
| 449 | + return PTR_ERR(workload); | |
| 681 | 450 | |
| 682 | − head &= RB_HEAD_OFF_MASK; | |
| 683 | − tail &= RB_TAIL_OFF_MASK; | |
| 684 | − | |
| 685 | − if (last_workload && same_context(&last_workload->ctx_desc, desc)) { | |
| 686 | − gvt_dbg_el("ring id %d cur workload == last\n", ring_id); | |
| 687 | − gvt_dbg_el("ctx head %x real head %lx\n", head, | |
| 688 | − last_workload->rb_tail); | |
| 689 | − /* | |
| 690 | − * cannot use guest context head pointer here, | |
| 691 | − * as it might not be updated at this time | |
| 692 | − */ | |
| 693 | − head = last_workload->rb_tail; | |
| 694 | − } | |
| 695 | − | |
| 696 | − gvt_dbg_el("ring id %d begin a new workload\n", ring_id); | |
| 697 | − | |
| 698 | − workload = kmem_cache_zalloc(vgpu->workloads, GFP_KERNEL); | |
| 699 | − if (!workload) | |
| 700 | − return -ENOMEM; | |
| 701 | − | |
| 702 | − /* record some ring buffer register values for scan and shadow */ | |
| 703 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 704 | − RING_CTX_OFF(rb_start.val), &start, 4); | |
| 705 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 706 | − RING_CTX_OFF(rb_ctrl.val), &ctl, 4); | |
| 707 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 708 | − RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); | |
| 709 | − | |
| 710 | − INIT_LIST_HEAD(&workload->list); | |
| 711 | − INIT_LIST_HEAD(&workload->shadow_bb); | |
| 712 | − | |
| 713 | − init_waitqueue_head(&workload->shadow_ctx_status_wq); | |
| 714 | − atomic_set(&workload->shadow_ctx_active, 0); | |
| 715 | − | |
| 716 | − workload->vgpu = vgpu; | |
| 717 | − workload->ring_id = ring_id; | |
| 718 | − workload->ctx_desc = *desc; | |
| 719 | − workload->ring_context_gpa = ring_context_gpa; | |
| 720 | − workload->rb_head = head; | |
| 721 | − workload->rb_tail = tail; | |
| 722 | − workload->rb_start = start; | |
| 723 | − workload->rb_ctl = ctl; | |
| 724 | 451 | workload->prepare = prepare_execlist_workload; |
| 725 | 452 | workload->complete = complete_execlist_workload; |
| 726 | − workload->status = -EINPROGRESS; | |
| 727 | 453 | workload->emulate_schedule_in = emulate_schedule_in; |
| 728 | − workload->shadowed = false; | |
| 729 | − | |
| 730 | − if (ring_id == RCS) { | |
| 731 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 732 | − RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4); | |
| 733 | − intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 734 | − RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4); | |
| 735 | − | |
| 736 | − workload->wa_ctx.indirect_ctx.guest_gma = | |
| 737 | − indirect_ctx & INDIRECT_CTX_ADDR_MASK; | |
| 738 | − workload->wa_ctx.indirect_ctx.size = | |
| 739 | − (indirect_ctx & INDIRECT_CTX_SIZE_MASK) * | |
| 740 | − CACHELINE_BYTES; | |
| 741 | − workload->wa_ctx.per_ctx.guest_gma = | |
| 742 | − per_ctx & PER_CTX_ADDR_MASK; | |
| 743 | − workload->wa_ctx.per_ctx.valid = per_ctx & 1; | |
| 744 | − } | |
| 745 | 454 | |
| 746 | 455 | if (emulate_schedule_in) |
| 747 | − workload->elsp_dwords = vgpu->execlist[ring_id].elsp_dwords; | |
| 748 | − | |
| 749 | − gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n", | |
| 750 | − workload, ring_id, head, tail, start, ctl); | |
| 456 | + workload->elsp_dwords = s->execlist[ring_id].elsp_dwords; | |
| 751 | 457 | |
| 752 | 458 | gvt_dbg_el("workload %p emulate schedule_in %d\n", workload, |
| 753 | 459 | emulate_schedule_in); |
| 754 | 460 | |
| 755 | − ret = prepare_mm(workload); | |
| 756 | − if (ret) { | |
| 757 | − kmem_cache_free(vgpu->workloads, workload); | |
| 758 | − return ret; | |
| 759 | − } | |
| 760 | − | |
| 761 | − /* Only scan and shadow the first workload in the queue | |
| 762 | − * as there is only one pre-allocated buf-obj for shadow. | |
| 763 | − */ | |
| 764 | − if (list_empty(workload_q_head(vgpu, ring_id))) { | |
| 765 | − intel_runtime_pm_get(dev_priv); | |
| 766 | − mutex_lock(&dev_priv->drm.struct_mutex); | |
| 767 | − intel_gvt_scan_and_shadow_workload(workload); | |
| 768 | − mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 769 | − intel_runtime_pm_put(dev_priv); | |
| 770 | − } | |
| 771 | − | |
| 772 | 461 | queue_workload(workload); |
| 773 | 462 | return 0; |
| 774 | 463 | } |
| 775 | 464 | |
| 776 | 465 | int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id) |
| 777 | 466 | { |
| 778 | − struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; | |
| 779 | − struct execlist_ctx_descriptor_format desc[2]; | |
| 467 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 468 | + struct intel_vgpu_execlist *execlist = &s->execlist[ring_id]; | |
| 469 | + struct execlist_ctx_descriptor_format *desc[2]; | |
| 780 | 470 | int i, ret; |
| 781 | 471 | |
| 782 | − desc[0] = *get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1); | |
| 783 | − desc[1] = *get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0); | |
| 472 | + desc[0] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0); | |
| 473 | + desc[1] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1); | |
| 784 | 474 | |
| 785 | − if (!desc[0].valid) { | |
| 475 | + if (!desc[0]->valid) { | |
| 786 | 476 | gvt_vgpu_err("invalid elsp submission, desc0 is invalid\n"); |
| 787 | 477 | goto inv_desc; |
| 788 | 478 | } |
| 789 | 479 | |
| 790 | 480 | for (i = 0; i < ARRAY_SIZE(desc); i++) { |
| 791 | − if (!desc[i].valid) | |
| 481 | + if (!desc[i]->valid) | |
| 792 | 482 | continue; |
| 793 | − if (!desc[i].privilege_access) { | |
| 483 | + if (!desc[i]->privilege_access) { | |
| 794 | 484 | gvt_vgpu_err("unexpected GGTT elsp submission\n"); |
| 795 | 485 | goto inv_desc; |
| 796 | 486 | } |
| @@ -798,9 +488,9 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id) · 1 unmodified line | ||
| 798 | 488 | |
| 799 | 489 | /* submit workload */ |
| 800 | 490 | for (i = 0; i < ARRAY_SIZE(desc); i++) { |
| 801 | − if (!desc[i].valid) | |
| 491 | + if (!desc[i]->valid) | |
| 802 | 492 | continue; |
| 803 | − ret = submit_context(vgpu, ring_id, &desc[i], i == 0); | |
| 493 | + ret = submit_context(vgpu, ring_id, desc[i], i == 0); | |
| 804 | 494 | if (ret) { |
| 805 | 495 | gvt_vgpu_err("failed to submit desc %d\n", i); |
| 806 | 496 | return ret; |
| @@ -811,13 +501,14 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id) · 4 unmodified lines | ||
| 811 | 501 | |
| 812 | 502 | inv_desc: |
| 813 | 503 | gvt_vgpu_err("descriptors content: desc0 %08x %08x desc1 %08x %08x\n", |
| 814 | − desc[0].udw, desc[0].ldw, desc[1].udw, desc[1].ldw); | |
| 504 | + desc[0]->udw, desc[0]->ldw, desc[1]->udw, desc[1]->ldw); | |
| 815 | 505 | return -EINVAL; |
| 816 | 506 | } |
| 817 | 507 | |
| 818 | 508 | static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) |
| 819 | 509 | { |
| 820 | − struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; | |
| 510 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 511 | + struct intel_vgpu_execlist *execlist = &s->execlist[ring_id]; | |
| 821 | 512 | struct execlist_context_status_pointer_format ctx_status_ptr; |
| 822 | 513 | u32 ctx_status_ptr_reg; |
| 823 | 514 | |
| @@ -837,91 +528,40 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) · 13 unmodified lines | ||
| 837 | 528 | vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; |
| 838 | 529 | } |
| 839 | 530 | |
| 840 | −static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) | |
| 841 | −{ | |
| 842 | − struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 843 | − struct intel_engine_cs *engine; | |
| 844 | − struct intel_vgpu_workload *pos, *n; | |
| 845 | − unsigned int tmp; | |
| 846 | − | |
| 847 | − /* free the unsubmited workloads in the queues. */ | |
| 848 | − for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { | |
| 849 | − list_for_each_entry_safe(pos, n, | |
| 850 | − &vgpu->workload_q_head[engine->id], list) { | |
| 851 | − list_del_init(&pos->list); | |
| 852 | − free_workload(pos); | |
| 853 | − } | |
| 854 | − | |
| 855 | − clear_bit(engine->id, vgpu->shadow_ctx_desc_updated); | |
| 856 | − } | |
| 857 | −} | |
| 858 | − | |
| 859 | −void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) | |
| 531 | +void clean_execlist(struct intel_vgpu *vgpu) | |
| 860 | 532 | { |
| 861 | 533 | enum intel_engine_id i; |
| 862 | 534 | struct intel_engine_cs *engine; |
| 863 | 535 | |
| 864 | − clean_workloads(vgpu, ALL_ENGINES); | |
| 865 | − kmem_cache_destroy(vgpu->workloads); | |
| 866 | − | |
| 867 | 536 | for_each_engine(engine, vgpu->gvt->dev_priv, i) { |
| 868 | − kfree(vgpu->reserve_ring_buffer_va[i]); | |
| 869 | − vgpu->reserve_ring_buffer_va[i] = NULL; | |
| 870 | − vgpu->reserve_ring_buffer_size[i] = 0; | |
| 871 | − } | |
| 537 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 872 | 538 | |
| 873 | −} | |
| 874 | − | |
| 875 | −#define RESERVE_RING_BUFFER_SIZE ((1 * PAGE_SIZE)/8) | |
| 876 | −int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) | |
| 877 | −{ | |
| 878 | − enum intel_engine_id i; | |
| 879 | − struct intel_engine_cs *engine; | |
| 880 | − | |
| 881 | − /* each ring has a virtual execlist engine */ | |
| 882 | − for_each_engine(engine, vgpu->gvt->dev_priv, i) { | |
| 883 | − init_vgpu_execlist(vgpu, i); | |
| 884 | − INIT_LIST_HEAD(&vgpu->workload_q_head[i]); | |
| 885 | − } | |
| 886 | − | |
| 887 | − vgpu->workloads = kmem_cache_create("gvt-g_vgpu_workload", | |
| 888 | − sizeof(struct intel_vgpu_workload), 0, | |
| 889 | − SLAB_HWCACHE_ALIGN, | |
| 890 | − NULL); | |
| 891 | − | |
| 892 | − if (!vgpu->workloads) | |
| 893 | − return -ENOMEM; | |
| 894 | − | |
| 895 | − /* each ring has a shadow ring buffer until vgpu destroyed */ | |
| 896 | − for_each_engine(engine, vgpu->gvt->dev_priv, i) { | |
| 897 | − vgpu->reserve_ring_buffer_va[i] = | |
| 898 | − kmalloc(RESERVE_RING_BUFFER_SIZE, GFP_KERNEL); | |
| 899 | − if (!vgpu->reserve_ring_buffer_va[i]) { | |
| 900 | − gvt_vgpu_err("fail to alloc reserve ring buffer\n"); | |
| 901 | − goto out; | |
| 902 | − } | |
| 903 | − vgpu->reserve_ring_buffer_size[i] = RESERVE_RING_BUFFER_SIZE; | |
| 539 | + kfree(s->ring_scan_buffer[i]); | |
| 540 | + s->ring_scan_buffer[i] = NULL; | |
| 541 | + s->ring_scan_buffer_size[i] = 0; | |
| 904 | 542 | } |
| 905 | − return 0; | |
| 906 | −out: | |
| 907 | − for_each_engine(engine, vgpu->gvt->dev_priv, i) { | |
| 908 | − if (vgpu->reserve_ring_buffer_size[i]) { | |
| 909 | − kfree(vgpu->reserve_ring_buffer_va[i]); | |
| 910 | − vgpu->reserve_ring_buffer_va[i] = NULL; | |
| 911 | − vgpu->reserve_ring_buffer_size[i] = 0; | |
| 912 | − } | |
| 913 | − } | |
| 914 | − return -ENOMEM; | |
| 915 | 543 | } |
| 916 | 544 | |
| 917 | −void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, | |
| 545 | +void reset_execlist(struct intel_vgpu *vgpu, | |
| 918 | 546 | unsigned long engine_mask) |
| 919 | 547 | { |
| 920 | 548 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; |
| 921 | 549 | struct intel_engine_cs *engine; |
| 922 | 550 | unsigned int tmp; |
| 923 | 551 | |
| 924 | − clean_workloads(vgpu, engine_mask); | |
| 925 | 552 | for_each_engine_masked(engine, dev_priv, engine_mask, tmp) |
| 926 | 553 | init_vgpu_execlist(vgpu, engine->id); |
| 927 | 554 | } |
| 555 | + | |
| 556 | +int init_execlist(struct intel_vgpu *vgpu) | |
| 557 | +{ | |
| 558 | + reset_execlist(vgpu, ALL_ENGINES); | |
| 559 | + return 0; | |
| 560 | +} | |
| 561 | + | |
| 562 | +const struct intel_vgpu_submission_ops intel_vgpu_execlist_submission_ops = { | |
| 563 | + .name = "execlist", | |
| 564 | + .init = init_execlist, | |
| 565 | + .reset = reset_execlist, | |
| 566 | + .clean = clean_execlist, | |
| 567 | +}; | |
| @@ -36,10 +36,6 @@ · 35 unmodified lines | ||
| 36 | 36 | #define _GVT_EXECLIST_H_ |
| 37 | 37 | |
| 38 | 38 | struct execlist_ctx_descriptor_format { |
| 39 | − union { | |
| 40 | − u32 udw; | |
| 41 | − u32 context_id; | |
| 42 | − }; | |
| 43 | 39 | union { |
| 44 | 40 | u32 ldw; |
| 45 | 41 | struct { |
| @@ -54,6 +50,10 @@ struct execlist_ctx_descriptor_format { · 8 unmodified lines | ||
| 54 | 50 | u32 lrca : 20; |
| 55 | 51 | }; |
| 56 | 52 | }; |
| 53 | + union { | |
| 54 | + u32 udw; | |
| 55 | + u32 context_id; | |
| 56 | + }; | |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | struct execlist_status_format { |
| @@ -66,20 +66,23 @@ static struct bin_attribute firmware_attr = { · 65 unmodified lines | ||
| 66 | 66 | .mmap = NULL, |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | −static int expose_firmware_sysfs(struct intel_gvt *gvt) | |
| 69 | +static int mmio_snapshot_handler(struct intel_gvt *gvt, u32 offset, void *data) | |
| 70 | 70 | { |
| 71 | 71 | struct drm_i915_private *dev_priv = gvt->dev_priv; |
| 72 | + | |
| 73 | + *(u32 *)(data + offset) = I915_READ_NOTRACE(_MMIO(offset)); | |
| 74 | + return 0; | |
| 75 | +} | |
| 76 | + | |
| 77 | +static int expose_firmware_sysfs(struct intel_gvt *gvt) | |
| 78 | +{ | |
| 72 | 79 | struct intel_gvt_device_info *info = &gvt->device_info; |
| 73 | 80 | struct pci_dev *pdev = gvt->dev_priv->drm.pdev; |
| 74 | − struct intel_gvt_mmio_info *e; | |
| 75 | − struct gvt_mmio_block *block = gvt->mmio.mmio_block; | |
| 76 | − int num = gvt->mmio.num_mmio_block; | |
| 77 | 81 | struct gvt_firmware_header *h; |
| 78 | 82 | void *firmware; |
| 79 | 83 | void *p; |
| 80 | 84 | unsigned long size, crc32_start; |
| 81 | − int i, j; | |
| 82 | − int ret; | |
| 85 | + int i, ret; | |
| 83 | 86 | |
| 84 | 87 | size = sizeof(*h) + info->mmio_size + info->cfg_space_size; |
| 85 | 88 | firmware = vzalloc(size); |
| @@ -104,15 +107,8 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt) · 18 unmodified lines | ||
| 104 | 107 | |
| 105 | 108 | p = firmware + h->mmio_offset; |
| 106 | 109 | |
| 107 | − hash_for_each(gvt->mmio.mmio_info_table, i, e, node) | |
| 108 | − *(u32 *)(p + e->offset) = I915_READ_NOTRACE(_MMIO(e->offset)); | |
| 109 | − | |
| 110 | − for (i = 0; i < num; i++, block++) { | |
| 111 | − for (j = 0; j < block->size; j += 4) | |
| 112 | − *(u32 *)(p + INTEL_GVT_MMIO_OFFSET(block->offset) + j) = | |
| 113 | − I915_READ_NOTRACE(_MMIO(INTEL_GVT_MMIO_OFFSET( | |
| 114 | − block->offset) + j)); | |
| 115 | − } | |
| 110 | + /* Take a snapshot of hw mmio registers. */ | |
| 111 | + intel_gvt_for_each_tracked_mmio(gvt, mmio_snapshot_handler, p); | |
| 116 | 112 | |
| 117 | 113 | memcpy(gvt->firmware.mmio, p, info->mmio_size); |
| 118 | 114 | |
| @@ -94,12 +94,12 @@ int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, · 93 unmodified lines | ||
| 94 | 94 | u64 h_addr; |
| 95 | 95 | int ret; |
| 96 | 96 | |
| 97 | − ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << GTT_PAGE_SHIFT, | |
| 97 | + ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << I915_GTT_PAGE_SHIFT, | |
| 98 | 98 | &h_addr); |
| 99 | 99 | if (ret) |
| 100 | 100 | return ret; |
| 101 | 101 | |
| 102 | − *h_index = h_addr >> GTT_PAGE_SHIFT; | |
| 102 | + *h_index = h_addr >> I915_GTT_PAGE_SHIFT; | |
| 103 | 103 | return 0; |
| 104 | 104 | } |
| 105 | 105 | |
| @@ -109,12 +109,12 @@ int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, · 3 unmodified lines | ||
| 109 | 109 | u64 g_addr; |
| 110 | 110 | int ret; |
| 111 | 111 | |
| 112 | − ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << GTT_PAGE_SHIFT, | |
| 112 | + ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << I915_GTT_PAGE_SHIFT, | |
| 113 | 113 | &g_addr); |
| 114 | 114 | if (ret) |
| 115 | 115 | return ret; |
| 116 | 116 | |
| 117 | − *g_index = g_addr >> GTT_PAGE_SHIFT; | |
| 117 | + *g_index = g_addr >> I915_GTT_PAGE_SHIFT; | |
| 118 | 118 | return 0; |
| 119 | 119 | } |
| 120 | 120 | |
| @@ -156,13 +156,15 @@ int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, · 35 unmodified lines | ||
| 156 | 156 | |
| 157 | 157 | struct gtt_type_table_entry { |
| 158 | 158 | int entry_type; |
| 159 | + int pt_type; | |
| 159 | 160 | int next_pt_type; |
| 160 | 161 | int pse_entry_type; |
| 161 | 162 | }; |
| 162 | 163 | |
| 163 | −#define GTT_TYPE_TABLE_ENTRY(type, e_type, npt_type, pse_type) \ | |
| 164 | +#define GTT_TYPE_TABLE_ENTRY(type, e_type, cpt_type, npt_type, pse_type) \ | |
| 164 | 165 | [type] = { \ |
| 165 | 166 | .entry_type = e_type, \ |
| 167 | + .pt_type = cpt_type, \ | |
| 166 | 168 | .next_pt_type = npt_type, \ |
| 167 | 169 | .pse_entry_type = pse_type, \ |
| 168 | 170 | } |
| @@ -170,55 +172,68 @@ struct gtt_type_table_entry { · 1 unmodified line | ||
| 170 | 172 | static struct gtt_type_table_entry gtt_type_table[] = { |
| 171 | 173 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L4_ENTRY, |
| 172 | 174 | GTT_TYPE_PPGTT_ROOT_L4_ENTRY, |
| 175 | + GTT_TYPE_INVALID, | |
| 173 | 176 | GTT_TYPE_PPGTT_PML4_PT, |
| 174 | 177 | GTT_TYPE_INVALID), |
| 175 | 178 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_PT, |
| 176 | 179 | GTT_TYPE_PPGTT_PML4_ENTRY, |
| 180 | + GTT_TYPE_PPGTT_PML4_PT, | |
| 177 | 181 | GTT_TYPE_PPGTT_PDP_PT, |
| 178 | 182 | GTT_TYPE_INVALID), |
| 179 | 183 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_ENTRY, |
| 180 | 184 | GTT_TYPE_PPGTT_PML4_ENTRY, |
| 185 | + GTT_TYPE_PPGTT_PML4_PT, | |
| 181 | 186 | GTT_TYPE_PPGTT_PDP_PT, |
| 182 | 187 | GTT_TYPE_INVALID), |
| 183 | 188 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_PT, |
| 184 | 189 | GTT_TYPE_PPGTT_PDP_ENTRY, |
| 190 | + GTT_TYPE_PPGTT_PDP_PT, | |
| 185 | 191 | GTT_TYPE_PPGTT_PDE_PT, |
| 186 | 192 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), |
| 187 | 193 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L3_ENTRY, |
| 188 | 194 | GTT_TYPE_PPGTT_ROOT_L3_ENTRY, |
| 195 | + GTT_TYPE_INVALID, | |
| 189 | 196 | GTT_TYPE_PPGTT_PDE_PT, |
| 190 | 197 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), |
| 191 | 198 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_ENTRY, |
| 192 | 199 | GTT_TYPE_PPGTT_PDP_ENTRY, |
| 200 | + GTT_TYPE_PPGTT_PDP_PT, | |
| 193 | 201 | GTT_TYPE_PPGTT_PDE_PT, |
| 194 | 202 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), |
| 195 | 203 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_PT, |
| 196 | 204 | GTT_TYPE_PPGTT_PDE_ENTRY, |
| 205 | + GTT_TYPE_PPGTT_PDE_PT, | |
| 197 | 206 | GTT_TYPE_PPGTT_PTE_PT, |
| 198 | 207 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), |
| 199 | 208 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_ENTRY, |
| 200 | 209 | GTT_TYPE_PPGTT_PDE_ENTRY, |
| 210 | + GTT_TYPE_PPGTT_PDE_PT, | |
| 201 | 211 | GTT_TYPE_PPGTT_PTE_PT, |
| 202 | 212 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), |
| 203 | 213 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT, |
| 204 | 214 | GTT_TYPE_PPGTT_PTE_4K_ENTRY, |
| 215 | + GTT_TYPE_PPGTT_PTE_PT, | |
| 205 | 216 | GTT_TYPE_INVALID, |
| 206 | 217 | GTT_TYPE_INVALID), |
| 207 | 218 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY, |
| 208 | 219 | GTT_TYPE_PPGTT_PTE_4K_ENTRY, |
| 220 | + GTT_TYPE_PPGTT_PTE_PT, | |
| 209 | 221 | GTT_TYPE_INVALID, |
| 210 | 222 | GTT_TYPE_INVALID), |
| 211 | 223 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY, |
| 212 | 224 | GTT_TYPE_PPGTT_PDE_ENTRY, |
| 225 | + GTT_TYPE_PPGTT_PDE_PT, | |
| 213 | 226 | GTT_TYPE_INVALID, |
| 214 | 227 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), |
| 215 | 228 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_1G_ENTRY, |
| 216 | 229 | GTT_TYPE_PPGTT_PDP_ENTRY, |
| 230 | + GTT_TYPE_PPGTT_PDP_PT, | |
| 217 | 231 | GTT_TYPE_INVALID, |
| 218 | 232 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), |
| 219 | 233 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_GGTT_PTE, |
| 220 | 234 | GTT_TYPE_GGTT_PTE, |
| 221 | 235 | GTT_TYPE_INVALID, |
| 236 | + GTT_TYPE_INVALID, | |
| 222 | 237 | GTT_TYPE_INVALID), |
| 223 | 238 | }; |
| 224 | 239 | |
| @@ -227,6 +242,11 @@ static inline int get_next_pt_type(int type) · 2 unmodified lines | ||
| 227 | 242 | return gtt_type_table[type].next_pt_type; |
| 228 | 243 | } |
| 229 | 244 | |
| 245 | +static inline int get_pt_type(int type) | |
| 246 | +{ | |
| 247 | + return gtt_type_table[type].pt_type; | |
| 248 | +} | |
| 249 | + | |
| 230 | 250 | static inline int get_entry_type(int type) |
| 231 | 251 | { |
| 232 | 252 | return gtt_type_table[type].entry_type; |
| @@ -351,7 +371,7 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e) · 118 unmodified lines | ||
| 351 | 371 | return false; |
| 352 | 372 | |
| 353 | 373 | e->type = get_entry_type(e->type); |
| 354 | − if (!(e->val64 & (1 << 7))) | |
| 374 | + if (!(e->val64 & BIT(7))) | |
| 355 | 375 | return false; |
| 356 | 376 | |
| 357 | 377 | e->type = get_pse_type(e->type); |
| @@ -369,12 +389,17 @@ static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e) · 11 unmodified lines | ||
| 369 | 389 | || e->type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) |
| 370 | 390 | return (e->val64 != 0); |
| 371 | 391 | else |
| 372 | − return (e->val64 & (1 << 0)); | |
| 392 | + return (e->val64 & BIT(0)); | |
| 373 | 393 | } |
| 374 | 394 | |
| 375 | 395 | static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e) |
| 376 | 396 | { |
| 377 | − e->val64 &= ~(1 << 0); | |
| 397 | + e->val64 &= ~BIT(0); | |
| 398 | +} | |
| 399 | + | |
| 400 | +static void gtt_entry_set_present(struct intel_gvt_gtt_entry *e) | |
| 401 | +{ | |
| 402 | + e->val64 |= BIT(0); | |
| 378 | 403 | } |
| 379 | 404 | |
| 380 | 405 | /* |
| @@ -382,7 +407,7 @@ static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e) · 1 unmodified line | ||
| 382 | 407 | */ |
| 383 | 408 | static unsigned long gma_to_ggtt_pte_index(unsigned long gma) |
| 384 | 409 | { |
| 385 | − unsigned long x = (gma >> GTT_PAGE_SHIFT); | |
| 410 | + unsigned long x = (gma >> I915_GTT_PAGE_SHIFT); | |
| 386 | 411 | |
| 387 | 412 | trace_gma_index(__func__, gma, x); |
| 388 | 413 | return x; |
| @@ -406,6 +431,7 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = { · 17 unmodified lines | ||
| 406 | 431 | .get_entry = gtt_get_entry64, |
| 407 | 432 | .set_entry = gtt_set_entry64, |
| 408 | 433 | .clear_present = gtt_entry_clear_present, |
| 434 | + .set_present = gtt_entry_set_present, | |
| 409 | 435 | .test_present = gen8_gtt_test_present, |
| 410 | 436 | .test_pse = gen8_gtt_test_pse, |
| 411 | 437 | .get_pfn = gen8_gtt_get_pfn, |
| @@ -494,7 +520,7 @@ static inline int ppgtt_spt_get_entry( · 82 unmodified lines | ||
| 494 | 520 | return -EINVAL; |
| 495 | 521 | |
| 496 | 522 | ret = ops->get_entry(page_table, e, index, guest, |
| 497 | − spt->guest_page.gfn << GTT_PAGE_SHIFT, | |
| 523 | + spt->guest_page.track.gfn << I915_GTT_PAGE_SHIFT, | |
| 498 | 524 | spt->vgpu); |
| 499 | 525 | if (ret) |
| 500 | 526 | return ret; |
| @@ -516,7 +542,7 @@ static inline int ppgtt_spt_set_entry( · 15 unmodified lines | ||
| 516 | 542 | return -EINVAL; |
| 517 | 543 | |
| 518 | 544 | return ops->set_entry(page_table, e, index, guest, |
| 519 | − spt->guest_page.gfn << GTT_PAGE_SHIFT, | |
| 545 | + spt->guest_page.track.gfn << I915_GTT_PAGE_SHIFT, | |
| 520 | 546 | spt->vgpu); |
| 521 | 547 | } |
| 522 | 548 | |
| @@ -537,88 +563,103 @@ static inline int ppgtt_spt_set_entry( · 14 unmodified lines | ||
| 537 | 563 | spt->shadow_page.type, e, index, false) |
| 538 | 564 | |
| 539 | 565 | /** |
| 540 | − * intel_vgpu_init_guest_page - init a guest page data structure | |
| 566 | + * intel_vgpu_init_page_track - init a page track data structure | |
| 541 | 567 | * @vgpu: a vGPU |
| 542 | − * @p: a guest page data structure | |
| 568 | + * @t: a page track data structure | |
| 543 | 569 | * @gfn: guest memory page frame number |
| 544 | − * @handler: function will be called when target guest memory page has | |
| 570 | + * @handler: the function will be called when target guest memory page has | |
| 545 | 571 | * been modified. |
| 546 | 572 | * |
| 547 | − * This function is called when user wants to track a guest memory page. | |
| 573 | + * This function is called when a user wants to prepare a page track data | |
| 574 | + * structure to track a guest memory page. | |
| 548 | 575 | * |
| 549 | 576 | * Returns: |
| 550 | 577 | * Zero on success, negative error code if failed. |
| 551 | 578 | */ |
| 552 | −int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, | |
| 553 | − struct intel_vgpu_guest_page *p, | |
| 579 | +int intel_vgpu_init_page_track(struct intel_vgpu *vgpu, | |
| 580 | + struct intel_vgpu_page_track *t, | |
| 554 | 581 | unsigned long gfn, |
| 555 | 582 | int (*handler)(void *, u64, void *, int), |
| 556 | 583 | void *data) |
| 557 | 584 | { |
| 558 | − INIT_HLIST_NODE(&p->node); | |
| 585 | + INIT_HLIST_NODE(&t->node); | |
| 559 | 586 | |
| 560 | − p->writeprotection = false; | |
| 561 | − p->gfn = gfn; | |
| 562 | − p->handler = handler; | |
| 563 | − p->data = data; | |
| 564 | − p->oos_page = NULL; | |
| 565 | − p->write_cnt = 0; | |
| 587 | + t->tracked = false; | |
| 588 | + t->gfn = gfn; | |
| 589 | + t->handler = handler; | |
| 590 | + t->data = data; | |
| 566 | 591 | |
| 567 | − hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn); | |
| 592 | + hash_add(vgpu->gtt.tracked_guest_page_hash_table, &t->node, t->gfn); | |
| 568 | 593 | return 0; |
| 569 | 594 | } |
| 570 | 595 | |
| 571 | −static int detach_oos_page(struct intel_vgpu *vgpu, | |
| 572 | − struct intel_vgpu_oos_page *oos_page); | |
| 573 | − | |
| 574 | 596 | /** |
| 575 | − * intel_vgpu_clean_guest_page - release the resource owned by guest page data | |
| 576 | − * structure | |
| 597 | + * intel_vgpu_clean_page_track - release a page track data structure | |
| 577 | 598 | * @vgpu: a vGPU |
| 578 | − * @p: a tracked guest page | |
| 599 | + * @t: a page track data structure | |
| 579 | 600 | * |
| 580 | − * This function is called when user tries to stop tracking a guest memory | |
| 581 | − * page. | |
| 601 | + * This function is called before a user frees a page track data structure. | |
| 582 | 602 | */ |
| 583 | −void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, | |
| 584 | − struct intel_vgpu_guest_page *p) | |
| 603 | +void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu, | |
| 604 | + struct intel_vgpu_page_track *t) | |
| 585 | 605 | { |
| 586 | − if (!hlist_unhashed(&p->node)) | |
| 587 | − hash_del(&p->node); | |
| 588 | − | |
| 589 | − if (p->oos_page) | |
| 590 | − detach_oos_page(vgpu, p->oos_page); | |
| 606 | + if (!hlist_unhashed(&t->node)) | |
| 607 | + hash_del(&t->node); | |
| 591 | 608 | |
| 592 | − if (p->writeprotection) | |
| 593 | − intel_gvt_hypervisor_unset_wp_page(vgpu, p); | |
| 609 | + if (t->tracked) | |
| 610 | + intel_gvt_hypervisor_disable_page_track(vgpu, t); | |
| 594 | 611 | } |
| 595 | 612 | |
| 596 | 613 | /** |
| 597 | − * intel_vgpu_find_guest_page - find a guest page data structure by GFN. | |
| 614 | + * intel_vgpu_find_tracked_page - find a tracked guest page | |
| 598 | 615 | * @vgpu: a vGPU |
| 599 | 616 | * @gfn: guest memory page frame number |
| 600 | 617 | * |
| 601 | − * This function is called when emulation logic wants to know if a trapped GFN | |
| 602 | − * is a tracked guest page. | |
| 618 | + * This function is called when the emulation layer wants to figure out if a | |
| 619 | + * trapped GFN is a tracked guest page. | |
| 603 | 620 | * |
| 604 | 621 | * Returns: |
| 605 | − * Pointer to guest page data structure, NULL if failed. | |
| 622 | + * Pointer to page track data structure, NULL if not found. | |
| 606 | 623 | */ |
| 607 | −struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( | |
| 624 | +struct intel_vgpu_page_track *intel_vgpu_find_tracked_page( | |
| 608 | 625 | struct intel_vgpu *vgpu, unsigned long gfn) |
| 609 | 626 | { |
| 610 | − struct intel_vgpu_guest_page *p; | |
| 627 | + struct intel_vgpu_page_track *t; | |
| 611 | 628 | |
| 612 | − hash_for_each_possible(vgpu->gtt.guest_page_hash_table, | |
| 613 | − p, node, gfn) { | |
| 614 | − if (p->gfn == gfn) | |
| 615 | − return p; | |
| 629 | + hash_for_each_possible(vgpu->gtt.tracked_guest_page_hash_table, | |
| 630 | + t, node, gfn) { | |
| 631 | + if (t->gfn == gfn) | |
| 632 | + return t; | |
| 616 | 633 | } |
| 617 | 634 | return NULL; |
| 618 | 635 | } |
| 619 | 636 | |
| 637 | +static int init_guest_page(struct intel_vgpu *vgpu, | |
| 638 | + struct intel_vgpu_guest_page *p, | |
| 639 | + unsigned long gfn, | |
| 640 | + int (*handler)(void *, u64, void *, int), | |
| 641 | + void *data) | |
| 642 | +{ | |
| 643 | + p->oos_page = NULL; | |
| 644 | + p->write_cnt = 0; | |
| 645 | + | |
| 646 | + return intel_vgpu_init_page_track(vgpu, &p->track, gfn, handler, data); | |
| 647 | +} | |
| 648 | + | |
| 649 | +static int detach_oos_page(struct intel_vgpu *vgpu, | |
| 650 | + struct intel_vgpu_oos_page *oos_page); | |
| 651 | + | |
| 652 | +static void clean_guest_page(struct intel_vgpu *vgpu, | |
| 653 | + struct intel_vgpu_guest_page *p) | |
| 654 | +{ | |
| 655 | + if (p->oos_page) | |
| 656 | + detach_oos_page(vgpu, p->oos_page); | |
| 657 | + | |
| 658 | + intel_vgpu_clean_page_track(vgpu, &p->track); | |
| 659 | +} | |
| 660 | + | |
| 620 | 661 | static inline int init_shadow_page(struct intel_vgpu *vgpu, |
| 621 | − struct intel_vgpu_shadow_page *p, int type) | |
| 662 | + struct intel_vgpu_shadow_page *p, int type, bool hash) | |
| 622 | 663 | { |
| 623 | 664 | struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev; |
| 624 | 665 | dma_addr_t daddr; |
| @@ -634,8 +675,9 @@ static inline int init_shadow_page(struct intel_vgpu *vgpu, · 9 unmodified lines | ||
| 634 | 675 | |
| 635 | 676 | INIT_HLIST_NODE(&p->node); |
| 636 | 677 | |
| 637 | − p->mfn = daddr >> GTT_PAGE_SHIFT; | |
| 638 | − hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn); | |
| 678 | + p->mfn = daddr >> I915_GTT_PAGE_SHIFT; | |
| 679 | + if (hash) | |
| 680 | + hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn); | |
| 639 | 681 | return 0; |
| 640 | 682 | } |
| 641 | 683 | |
| @@ -644,7 +686,7 @@ static inline void clean_shadow_page(struct intel_vgpu *vgpu, · 2 unmodified lines | ||
| 644 | 686 | { |
| 645 | 687 | struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev; |
| 646 | 688 | |
| 647 | − dma_unmap_page(kdev, p->mfn << GTT_PAGE_SHIFT, 4096, | |
| 689 | + dma_unmap_page(kdev, p->mfn << I915_GTT_PAGE_SHIFT, 4096, | |
| 648 | 690 | PCI_DMA_BIDIRECTIONAL); |
| 649 | 691 | |
| 650 | 692 | if (!hlist_unhashed(&p->node)) |
| @@ -664,6 +706,9 @@ static inline struct intel_vgpu_shadow_page *find_shadow_page( · 13 unmodified lines | ||
| 664 | 706 | return NULL; |
| 665 | 707 | } |
| 666 | 708 | |
| 709 | +#define page_track_to_guest_page(ptr) \ | |
| 710 | + container_of(ptr, struct intel_vgpu_guest_page, track) | |
| 711 | + | |
| 667 | 712 | #define guest_page_to_ppgtt_spt(ptr) \ |
| 668 | 713 | container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page) |
| 669 | 714 | |
| @@ -697,7 +742,7 @@ static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt) · 27 unmodified lines | ||
| 697 | 742 | trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type); |
| 698 | 743 | |
| 699 | 744 | clean_shadow_page(spt->vgpu, &spt->shadow_page); |
| 700 | − intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page); | |
| 745 | + clean_guest_page(spt->vgpu, &spt->guest_page); | |
| 701 | 746 | list_del_init(&spt->post_shadow_list); |
| 702 | 747 | |
| 703 | 748 | free_spt(spt); |
| @@ -713,22 +758,24 @@ static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu) · 9 unmodified lines | ||
| 713 | 758 | ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp)); |
| 714 | 759 | } |
| 715 | 760 | |
| 716 | −static int ppgtt_handle_guest_write_page_table_bytes(void *gp, | |
| 761 | +static int ppgtt_handle_guest_write_page_table_bytes( | |
| 762 | + struct intel_vgpu_guest_page *gpt, | |
| 717 | 763 | u64 pa, void *p_data, int bytes); |
| 718 | 764 | |
| 719 | −static int ppgtt_write_protection_handler(void *gp, u64 pa, | |
| 765 | +static int ppgtt_write_protection_handler(void *data, u64 pa, | |
| 720 | 766 | void *p_data, int bytes) |
| 721 | 767 | { |
| 722 | − struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; | |
| 768 | + struct intel_vgpu_page_track *t = data; | |
| 769 | + struct intel_vgpu_guest_page *p = page_track_to_guest_page(t); | |
| 723 | 770 | int ret; |
| 724 | 771 | |
| 725 | 772 | if (bytes != 4 && bytes != 8) |
| 726 | 773 | return -EINVAL; |
| 727 | 774 | |
| 728 | − if (!gpt->writeprotection) | |
| 775 | + if (!t->tracked) | |
| 729 | 776 | return -EINVAL; |
| 730 | 777 | |
| 731 | − ret = ppgtt_handle_guest_write_page_table_bytes(gp, | |
| 778 | + ret = ppgtt_handle_guest_write_page_table_bytes(p, | |
| 732 | 779 | pa, p_data, bytes); |
| 733 | 780 | if (ret) |
| 734 | 781 | return ret; |
| @@ -762,13 +809,13 @@ retry: · 27 unmodified lines | ||
| 762 | 809 | * TODO: guest page type may be different with shadow page type, |
| 763 | 810 | * when we support PSE page in future. |
| 764 | 811 | */ |
| 765 | − ret = init_shadow_page(vgpu, &spt->shadow_page, type); | |
| 812 | + ret = init_shadow_page(vgpu, &spt->shadow_page, type, true); | |
| 766 | 813 | if (ret) { |
| 767 | 814 | gvt_vgpu_err("fail to initialize shadow page for spt\n"); |
| 768 | 815 | goto err; |
| 769 | 816 | } |
| 770 | 817 | |
| 771 | − ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page, | |
| 818 | + ret = init_guest_page(vgpu, &spt->guest_page, | |
| 772 | 819 | gfn, ppgtt_write_protection_handler, NULL); |
| 773 | 820 | if (ret) { |
| 774 | 821 | gvt_vgpu_err("fail to initialize guest page for spt\n"); |
| @@ -798,7 +845,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page( · 23 unmodified lines | ||
| 798 | 845 | ((spt)->vgpu->gvt->device_info.gtt_entry_size_shift) |
| 799 | 846 | |
| 800 | 847 | #define pt_entries(spt) \ |
| 801 | − (GTT_PAGE_SIZE >> pt_entry_size_shift(spt)) | |
| 848 | + (I915_GTT_PAGE_SIZE >> pt_entry_size_shift(spt)) | |
| 802 | 849 | |
| 803 | 850 | #define for_each_present_guest_entry(spt, e, i) \ |
| 804 | 851 | for (i = 0; i < pt_entries(spt); i++) \ |
| @@ -856,7 +903,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) · 51 unmodified lines | ||
| 856 | 903 | int v = atomic_read(&spt->refcount); |
| 857 | 904 | |
| 858 | 905 | trace_spt_change(spt->vgpu->id, "die", spt, |
| 859 | − spt->guest_page.gfn, spt->shadow_page.type); | |
| 906 | + spt->guest_page.track.gfn, spt->shadow_page.type); | |
| 860 | 907 | |
| 861 | 908 | trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1)); |
| 862 | 909 | |
| @@ -878,7 +925,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) · 15 unmodified lines | ||
| 878 | 925 | } |
| 879 | 926 | release: |
| 880 | 927 | trace_spt_change(spt->vgpu->id, "release", spt, |
| 881 | − spt->guest_page.gfn, spt->shadow_page.type); | |
| 928 | + spt->guest_page.track.gfn, spt->shadow_page.type); | |
| 882 | 929 | ppgtt_free_shadow_page(spt); |
| 883 | 930 | return 0; |
| 884 | 931 | fail: |
| @@ -895,6 +942,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( · 10 unmodified lines | ||
| 895 | 942 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
| 896 | 943 | struct intel_vgpu_ppgtt_spt *s = NULL; |
| 897 | 944 | struct intel_vgpu_guest_page *g; |
| 945 | + struct intel_vgpu_page_track *t; | |
| 898 | 946 | int ret; |
| 899 | 947 | |
| 900 | 948 | if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) { |
| @@ -902,8 +950,9 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( · 1 unmodified line | ||
| 902 | 950 | goto fail; |
| 903 | 951 | } |
| 904 | 952 | |
| 905 | − g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); | |
| 906 | − if (g) { | |
| 953 | + t = intel_vgpu_find_tracked_page(vgpu, ops->get_pfn(we)); | |
| 954 | + if (t) { | |
| 955 | + g = page_track_to_guest_page(t); | |
| 907 | 956 | s = guest_page_to_ppgtt_spt(g); |
| 908 | 957 | ppgtt_get_shadow_page(s); |
| 909 | 958 | } else { |
| @@ -915,7 +964,8 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( · 5 unmodified lines | ||
| 915 | 964 | goto fail; |
| 916 | 965 | } |
| 917 | 966 | |
| 918 | − ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page); | |
| 967 | + ret = intel_gvt_hypervisor_enable_page_track(vgpu, | |
| 968 | + &s->guest_page.track); | |
| 919 | 969 | if (ret) |
| 920 | 970 | goto fail; |
| 921 | 971 | |
| @@ -923,7 +973,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( · 1 unmodified line | ||
| 923 | 973 | if (ret) |
| 924 | 974 | goto fail; |
| 925 | 975 | |
| 926 | − trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn, | |
| 976 | + trace_spt_change(vgpu->id, "new", s, s->guest_page.track.gfn, | |
| 927 | 977 | s->shadow_page.type); |
| 928 | 978 | } |
| 929 | 979 | return s; |
| @@ -953,7 +1003,7 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) · 23 unmodified lines | ||
| 953 | 1003 | int ret; |
| 954 | 1004 | |
| 955 | 1005 | trace_spt_change(spt->vgpu->id, "born", spt, |
| 956 | − spt->guest_page.gfn, spt->shadow_page.type); | |
| 1006 | + spt->guest_page.track.gfn, spt->shadow_page.type); | |
| 957 | 1007 | |
| 958 | 1008 | if (gtt_type_is_pte_pt(spt->shadow_page.type)) { |
| 959 | 1009 | for_each_present_guest_entry(spt, &ge, i) { |
| @@ -1078,11 +1128,11 @@ static int sync_oos_page(struct intel_vgpu *vgpu, · 118 unmodified lines | ||
| 1078 | 1128 | old.type = new.type = get_entry_type(spt->guest_page_type); |
| 1079 | 1129 | old.val64 = new.val64 = 0; |
| 1080 | 1130 | |
| 1081 | − for (index = 0; index < (GTT_PAGE_SIZE >> info->gtt_entry_size_shift); | |
| 1082 | − index++) { | |
| 1131 | + for (index = 0; index < (I915_GTT_PAGE_SIZE >> | |
| 1132 | + info->gtt_entry_size_shift); index++) { | |
| 1083 | 1133 | ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu); |
| 1084 | 1134 | ops->get_entry(NULL, &new, index, true, |
| 1085 | − oos_page->guest_page->gfn << PAGE_SHIFT, vgpu); | |
| 1135 | + oos_page->guest_page->track.gfn << PAGE_SHIFT, vgpu); | |
| 1086 | 1136 | |
| 1087 | 1137 | if (old.val64 == new.val64 |
| 1088 | 1138 | && !test_and_clear_bit(index, spt->post_shadow_bitmap)) |
| @@ -1132,8 +1182,9 @@ static int attach_oos_page(struct intel_vgpu *vgpu, · 43 unmodified lines | ||
| 1132 | 1182 | struct intel_gvt *gvt = vgpu->gvt; |
| 1133 | 1183 | int ret; |
| 1134 | 1184 | |
| 1135 | − ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT, | |
| 1136 | − oos_page->mem, GTT_PAGE_SIZE); | |
| 1185 | + ret = intel_gvt_hypervisor_read_gpa(vgpu, | |
| 1186 | + gpt->track.gfn << I915_GTT_PAGE_SHIFT, | |
| 1187 | + oos_page->mem, I915_GTT_PAGE_SIZE); | |
| 1137 | 1188 | if (ret) |
| 1138 | 1189 | return ret; |
| 1139 | 1190 | |
| @@ -1152,7 +1203,7 @@ static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu, · 12 unmodified lines | ||
| 1152 | 1203 | { |
| 1153 | 1204 | int ret; |
| 1154 | 1205 | |
| 1155 | − ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt); | |
| 1206 | + ret = intel_gvt_hypervisor_enable_page_track(vgpu, &gpt->track); | |
| 1156 | 1207 | if (ret) |
| 1157 | 1208 | return ret; |
| 1158 | 1209 | |
| @@ -1200,7 +1251,7 @@ static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu, · 41 unmodified lines | ||
| 1200 | 1251 | gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); |
| 1201 | 1252 | |
| 1202 | 1253 | list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head); |
| 1203 | − return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt); | |
| 1254 | + return intel_gvt_hypervisor_disable_page_track(vgpu, &gpt->track); | |
| 1204 | 1255 | } |
| 1205 | 1256 | |
| 1206 | 1257 | /** |
| @@ -1335,10 +1386,10 @@ int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu) · 128 unmodified lines | ||
| 1335 | 1386 | return 0; |
| 1336 | 1387 | } |
| 1337 | 1388 | |
| 1338 | −static int ppgtt_handle_guest_write_page_table_bytes(void *gp, | |
| 1389 | +static int ppgtt_handle_guest_write_page_table_bytes( | |
| 1390 | + struct intel_vgpu_guest_page *gpt, | |
| 1339 | 1391 | u64 pa, void *p_data, int bytes) |
| 1340 | 1392 | { |
| 1341 | − struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; | |
| 1342 | 1393 | struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); |
| 1343 | 1394 | struct intel_vgpu *vgpu = spt->vgpu; |
| 1344 | 1395 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
| @@ -1415,7 +1466,7 @@ static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm) · 70 unmodified lines | ||
| 1415 | 1466 | mm->shadow_page_table = mem + mm->page_table_entry_size; |
| 1416 | 1467 | } else if (mm->type == INTEL_GVT_MM_GGTT) { |
| 1417 | 1468 | mm->page_table_entry_cnt = |
| 1418 | − (gvt_ggtt_gm_sz(gvt) >> GTT_PAGE_SHIFT); | |
| 1469 | + (gvt_ggtt_gm_sz(gvt) >> I915_GTT_PAGE_SHIFT); | |
| 1419 | 1470 | mm->page_table_entry_size = mm->page_table_entry_cnt * |
| 1420 | 1471 | info->gtt_entry_size; |
| 1421 | 1472 | mem = vzalloc(mm->page_table_entry_size); |
| @@ -1737,8 +1788,8 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma) · 315 unmodified lines | ||
| 1737 | 1788 | gma_ops->gma_to_ggtt_pte_index(gma)); |
| 1738 | 1789 | if (ret) |
| 1739 | 1790 | goto err; |
| 1740 | − gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) | |
| 1741 | − + (gma & ~GTT_PAGE_MASK); | |
| 1791 | + gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT) | |
| 1792 | + + (gma & ~I915_GTT_PAGE_MASK); | |
| 1742 | 1793 | |
| 1743 | 1794 | trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa); |
| 1744 | 1795 | return gpa; |
| @@ -1790,8 +1841,8 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma) · 45 unmodified lines | ||
| 1790 | 1841 | } |
| 1791 | 1842 | } |
| 1792 | 1843 | |
| 1793 | − gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) | |
| 1794 | − + (gma & ~GTT_PAGE_MASK); | |
| 1844 | + gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT) | |
| 1845 | + + (gma & ~I915_GTT_PAGE_MASK); | |
| 1795 | 1846 | |
| 1796 | 1847 | trace_gma_translate(vgpu->id, "ppgtt", 0, |
| 1797 | 1848 | mm->page_table_level, gma, gpa); |
| @@ -1859,7 +1910,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, · 61 unmodified lines | ||
| 1859 | 1910 | if (bytes != 4 && bytes != 8) |
| 1860 | 1911 | return -EINVAL; |
| 1861 | 1912 | |
| 1862 | − gma = g_gtt_index << GTT_PAGE_SHIFT; | |
| 1913 | + gma = g_gtt_index << I915_GTT_PAGE_SHIFT; | |
| 1863 | 1914 | |
| 1864 | 1915 | /* the VM may configure the whole GM space when ballooning is used */ |
| 1865 | 1916 | if (!vgpu_gmadr_is_valid(vgpu, gma)) |
| @@ -1878,11 +1929,11 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, · 12 unmodified lines | ||
| 1878 | 1929 | * update the entry in this situation p2m will fail |
| 1879 | 1930 | * settting the shadow entry to point to a scratch page |
| 1880 | 1931 | */ |
| 1881 | − ops->set_pfn(&m, gvt->gtt.scratch_ggtt_mfn); | |
| 1932 | + ops->set_pfn(&m, gvt->gtt.scratch_mfn); | |
| 1882 | 1933 | } |
| 1883 | 1934 | } else { |
| 1884 | 1935 | m = e; |
| 1885 | − ops->set_pfn(&m, gvt->gtt.scratch_ggtt_mfn); | |
| 1936 | + ops->set_pfn(&m, gvt->gtt.scratch_mfn); | |
| 1886 | 1937 | } |
| 1887 | 1938 | |
| 1888 | 1939 | ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); |
| @@ -1922,7 +1973,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, · 33 unmodified lines | ||
| 1922 | 1973 | { |
| 1923 | 1974 | struct intel_vgpu_gtt *gtt = &vgpu->gtt; |
| 1924 | 1975 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
| 1925 | − int page_entry_num = GTT_PAGE_SIZE >> | |
| 1976 | + int page_entry_num = I915_GTT_PAGE_SIZE >> | |
| 1926 | 1977 | vgpu->gvt->device_info.gtt_entry_size_shift; |
| 1927 | 1978 | void *scratch_pt; |
| 1928 | 1979 | int i; |
| @@ -1946,7 +1997,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, · 17 unmodified lines | ||
| 1946 | 1997 | return -ENOMEM; |
| 1947 | 1998 | } |
| 1948 | 1999 | gtt->scratch_pt[type].page_mfn = |
| 1949 | − (unsigned long)(daddr >> GTT_PAGE_SHIFT); | |
| 2000 | + (unsigned long)(daddr >> I915_GTT_PAGE_SHIFT); | |
| 1950 | 2001 | gtt->scratch_pt[type].page = virt_to_page(scratch_pt); |
| 1951 | 2002 | gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n", |
| 1952 | 2003 | vgpu->id, type, gtt->scratch_pt[type].page_mfn); |
| @@ -1989,7 +2040,7 @@ static int release_scratch_page_tree(struct intel_vgpu *vgpu) · 36 unmodified lines | ||
| 1989 | 2040 | for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) { |
| 1990 | 2041 | if (vgpu->gtt.scratch_pt[i].page != NULL) { |
| 1991 | 2042 | daddr = (dma_addr_t)(vgpu->gtt.scratch_pt[i].page_mfn << |
| 1992 | − GTT_PAGE_SHIFT); | |
| 2043 | + I915_GTT_PAGE_SHIFT); | |
| 1993 | 2044 | dma_unmap_page(dev, daddr, 4096, PCI_DMA_BIDIRECTIONAL); |
| 1994 | 2045 | __free_page(vgpu->gtt.scratch_pt[i].page); |
| 1995 | 2046 | vgpu->gtt.scratch_pt[i].page = NULL; |
| @@ -2032,7 +2083,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) · 36 unmodified lines | ||
| 2032 | 2083 | struct intel_vgpu_gtt *gtt = &vgpu->gtt; |
| 2033 | 2084 | struct intel_vgpu_mm *ggtt_mm; |
| 2034 | 2085 | |
| 2035 | − hash_init(gtt->guest_page_hash_table); | |
| 2086 | + hash_init(gtt->tracked_guest_page_hash_table); | |
| 2036 | 2087 | hash_init(gtt->shadow_page_hash_table); |
| 2037 | 2088 | |
| 2038 | 2089 | INIT_LIST_HEAD(>t->mm_list_head); |
| @@ -2285,15 +2336,16 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt) · 246 unmodified lines | ||
| 2285 | 2336 | __free_page(virt_to_page(page)); |
| 2286 | 2337 | return -ENOMEM; |
| 2287 | 2338 | } |
| 2288 | − gvt->gtt.scratch_ggtt_page = virt_to_page(page); | |
| 2289 | − gvt->gtt.scratch_ggtt_mfn = (unsigned long)(daddr >> GTT_PAGE_SHIFT); | |
| 2339 | + | |
| 2340 | + gvt->gtt.scratch_page = virt_to_page(page); | |
| 2341 | + gvt->gtt.scratch_mfn = (unsigned long)(daddr >> I915_GTT_PAGE_SHIFT); | |
| 2290 | 2342 | |
| 2291 | 2343 | if (enable_out_of_sync) { |
| 2292 | 2344 | ret = setup_spt_oos(gvt); |
| 2293 | 2345 | if (ret) { |
| 2294 | 2346 | gvt_err("fail to initialize SPT oos\n"); |
| 2295 | 2347 | dma_unmap_page(dev, daddr, 4096, PCI_DMA_BIDIRECTIONAL); |
| 2296 | − __free_page(gvt->gtt.scratch_ggtt_page); | |
| 2348 | + __free_page(gvt->gtt.scratch_page); | |
| 2297 | 2349 | return ret; |
| 2298 | 2350 | } |
| 2299 | 2351 | } |
| @@ -2312,12 +2364,12 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt) · 12 unmodified lines | ||
| 2312 | 2364 | void intel_gvt_clean_gtt(struct intel_gvt *gvt) |
| 2313 | 2365 | { |
| 2314 | 2366 | struct device *dev = &gvt->dev_priv->drm.pdev->dev; |
| 2315 | − dma_addr_t daddr = (dma_addr_t)(gvt->gtt.scratch_ggtt_mfn << | |
| 2316 | − GTT_PAGE_SHIFT); | |
| 2367 | + dma_addr_t daddr = (dma_addr_t)(gvt->gtt.scratch_mfn << | |
| 2368 | + I915_GTT_PAGE_SHIFT); | |
| 2317 | 2369 | |
| 2318 | 2370 | dma_unmap_page(dev, daddr, 4096, PCI_DMA_BIDIRECTIONAL); |
| 2319 | 2371 | |
| 2320 | − __free_page(gvt->gtt.scratch_ggtt_page); | |
| 2372 | + __free_page(gvt->gtt.scratch_page); | |
| 2321 | 2373 | |
| 2322 | 2374 | if (enable_out_of_sync) |
| 2323 | 2375 | clean_spt_oos(gvt); |
| @@ -2343,7 +2395,7 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu) · 19 unmodified lines | ||
| 2343 | 2395 | |
| 2344 | 2396 | memset(&e, 0, sizeof(struct intel_gvt_gtt_entry)); |
| 2345 | 2397 | e.type = GTT_TYPE_GGTT_PTE; |
| 2346 | − ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn); | |
| 2398 | + ops->set_pfn(&e, gvt->gtt.scratch_mfn); | |
| 2347 | 2399 | e.val64 |= _PAGE_PRESENT; |
| 2348 | 2400 | |
| 2349 | 2401 | index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT; |
| @@ -2369,8 +2421,6 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu) · 19 unmodified lines | ||
| 2369 | 2421 | */ |
| 2370 | 2422 | void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu) |
| 2371 | 2423 | { |
| 2372 | − int i; | |
| 2373 | − | |
| 2374 | 2424 | ppgtt_free_all_shadow_page(vgpu); |
| 2375 | 2425 | |
| 2376 | 2426 | /* Shadow pages are only created when there is no page |
| @@ -2380,11 +2430,4 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu) · 3 unmodified lines | ||
| 2380 | 2430 | intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); |
| 2381 | 2431 | |
| 2382 | 2432 | intel_vgpu_reset_ggtt(vgpu); |
| 2383 | − | |
| 2384 | − /* clear scratch page for security */ | |
| 2385 | − for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) { | |
| 2386 | − if (vgpu->gtt.scratch_pt[i].page != NULL) | |
| 2387 | − memset(page_address(vgpu->gtt.scratch_pt[i].page), | |
| 2388 | − 0, PAGE_SIZE); | |
| 2389 | − } | |
| 2390 | 2433 | } |
| @@ -34,9 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | #ifndef _GVT_GTT_H_ |
| 35 | 35 | #define _GVT_GTT_H_ |
| 36 | 36 | |
| 37 | −#define GTT_PAGE_SHIFT 12 | |
| 38 | −#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT) | |
| 39 | −#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1)) | |
| 37 | +#define I915_GTT_PAGE_SHIFT 12 | |
| 38 | +#define I915_GTT_PAGE_MASK (~(I915_GTT_PAGE_SIZE - 1)) | |
| 40 | 39 | |
| 41 | 40 | struct intel_vgpu_mm; |
| 42 | 41 | |
| @@ -63,6 +62,7 @@ struct intel_gvt_gtt_pte_ops { · 20 unmodified lines | ||
| 63 | 62 | struct intel_vgpu *vgpu); |
| 64 | 63 | bool (*test_present)(struct intel_gvt_gtt_entry *e); |
| 65 | 64 | void (*clear_present)(struct intel_gvt_gtt_entry *e); |
| 65 | + void (*set_present)(struct intel_gvt_gtt_entry *e); | |
| 66 | 66 | bool (*test_pse)(struct intel_gvt_gtt_entry *e); |
| 67 | 67 | void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); |
| 68 | 68 | unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); |
| @@ -86,8 +86,8 @@ struct intel_gvt_gtt { · 17 unmodified lines | ||
| 86 | 86 | struct list_head oos_page_free_list_head; |
| 87 | 87 | struct list_head mm_lru_list_head; |
| 88 | 88 | |
| 89 | − struct page *scratch_ggtt_page; | |
| 90 | − unsigned long scratch_ggtt_mfn; | |
| 89 | + struct page *scratch_page; | |
| 90 | + unsigned long scratch_mfn; | |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 93 | enum { |
| @@ -193,18 +193,16 @@ struct intel_vgpu_scratch_pt { · 99 unmodified lines | ||
| 193 | 193 | unsigned long page_mfn; |
| 194 | 194 | }; |
| 195 | 195 | |
| 196 | − | |
| 197 | 196 | struct intel_vgpu_gtt { |
| 198 | 197 | struct intel_vgpu_mm *ggtt_mm; |
| 199 | 198 | unsigned long active_ppgtt_mm_bitmap; |
| 200 | 199 | struct list_head mm_list_head; |
| 201 | 200 | DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); |
| 202 | − DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); | |
| 203 | − atomic_t n_write_protected_guest_page; | |
| 201 | + DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); | |
| 202 | + atomic_t n_tracked_guest_page; | |
| 204 | 203 | struct list_head oos_page_list_head; |
| 205 | 204 | struct list_head post_shadow_list_head; |
| 206 | 205 | struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX]; |
| 207 | − | |
| 208 | 206 | }; |
| 209 | 207 | |
| 210 | 208 | extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); |
| @@ -228,12 +226,16 @@ struct intel_vgpu_shadow_page { · 17 unmodified lines | ||
| 228 | 226 | unsigned long mfn; |
| 229 | 227 | }; |
| 230 | 228 | |
| 231 | −struct intel_vgpu_guest_page { | |
| 229 | +struct intel_vgpu_page_track { | |
| 232 | 230 | struct hlist_node node; |
| 233 | − bool writeprotection; | |
| 231 | + bool tracked; | |
| 234 | 232 | unsigned long gfn; |
| 235 | 233 | int (*handler)(void *, u64, void *, int); |
| 236 | 234 | void *data; |
| 235 | +}; | |
| 236 | + | |
| 237 | +struct intel_vgpu_guest_page { | |
| 238 | + struct intel_vgpu_page_track track; | |
| 237 | 239 | unsigned long write_cnt; |
| 238 | 240 | struct intel_vgpu_oos_page *oos_page; |
| 239 | 241 | }; |
| @@ -243,7 +245,7 @@ struct intel_vgpu_oos_page { · 3 unmodified lines | ||
| 243 | 245 | struct list_head list; |
| 244 | 246 | struct list_head vm_list; |
| 245 | 247 | int id; |
| 246 | − unsigned char mem[GTT_PAGE_SIZE]; | |
| 248 | + unsigned char mem[I915_GTT_PAGE_SIZE]; | |
| 247 | 249 | }; |
| 248 | 250 | |
| 249 | 251 | #define GTT_ENTRY_NUM_IN_ONE_PAGE 512 |
| @@ -258,22 +260,16 @@ struct intel_vgpu_ppgtt_spt { · 8 unmodified lines | ||
| 258 | 260 | struct list_head post_shadow_list; |
| 259 | 261 | }; |
| 260 | 262 | |
| 261 | −int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, | |
| 262 | − struct intel_vgpu_guest_page *guest_page, | |
| 263 | +int intel_vgpu_init_page_track(struct intel_vgpu *vgpu, | |
| 264 | + struct intel_vgpu_page_track *t, | |
| 263 | 265 | unsigned long gfn, |
| 264 | 266 | int (*handler)(void *gp, u64, void *, int), |
| 265 | 267 | void *data); |
| 266 | 268 | |
| 267 | −void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, | |
| 268 | − struct intel_vgpu_guest_page *guest_page); | |
| 269 | − | |
| 270 | −int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, | |
| 271 | − struct intel_vgpu_guest_page *guest_page); | |
| 272 | − | |
| 273 | −void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu, | |
| 274 | − struct intel_vgpu_guest_page *guest_page); | |
| 269 | +void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu, | |
| 270 | + struct intel_vgpu_page_track *t); | |
| 275 | 271 | |
| 276 | −struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( | |
| 272 | +struct intel_vgpu_page_track *intel_vgpu_find_tracked_page( | |
| 277 | 273 | struct intel_vgpu *vgpu, unsigned long gfn); |
| 278 | 274 | |
| 279 | 275 | int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #include "i915_drv.h" |
| 38 | 38 | #include "gvt.h" |
| 39 | +#include <linux/vfio.h> | |
| 40 | +#include <linux/mdev.h> | |
| 39 | 41 | |
| 40 | 42 | struct intel_gvt_host intel_gvt_host; |
| 41 | 43 | |
| @@ -44,6 +46,129 @@ static const char * const supported_hypervisors[] = { · 2 unmodified lines | ||
| 44 | 46 | [INTEL_GVT_HYPERVISOR_KVM] = "KVM", |
| 45 | 47 | }; |
| 46 | 48 | |
| 49 | +static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt, | |
| 50 | + const char *name) | |
| 51 | +{ | |
| 52 | + int i; | |
| 53 | + struct intel_vgpu_type *t; | |
| 54 | + const char *driver_name = dev_driver_string( | |
| 55 | + &gvt->dev_priv->drm.pdev->dev); | |
| 56 | + | |
| 57 | + for (i = 0; i < gvt->num_types; i++) { | |
| 58 | + t = &gvt->types[i]; | |
| 59 | + if (!strncmp(t->name, name + strlen(driver_name) + 1, | |
| 60 | + sizeof(t->name))) | |
| 61 | + return t; | |
| 62 | + } | |
| 63 | + | |
| 64 | + return NULL; | |
| 65 | +} | |
| 66 | + | |
| 67 | +static ssize_t available_instances_show(struct kobject *kobj, | |
| 68 | + struct device *dev, char *buf) | |
| 69 | +{ | |
| 70 | + struct intel_vgpu_type *type; | |
| 71 | + unsigned int num = 0; | |
| 72 | + void *gvt = kdev_to_i915(dev)->gvt; | |
| 73 | + | |
| 74 | + type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 75 | + if (!type) | |
| 76 | + num = 0; | |
| 77 | + else | |
| 78 | + num = type->avail_instance; | |
| 79 | + | |
| 80 | + return sprintf(buf, "%u\n", num); | |
| 81 | +} | |
| 82 | + | |
| 83 | +static ssize_t device_api_show(struct kobject *kobj, struct device *dev, | |
| 84 | + char *buf) | |
| 85 | +{ | |
| 86 | + return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING); | |
| 87 | +} | |
| 88 | + | |
| 89 | +static ssize_t description_show(struct kobject *kobj, struct device *dev, | |
| 90 | + char *buf) | |
| 91 | +{ | |
| 92 | + struct intel_vgpu_type *type; | |
| 93 | + void *gvt = kdev_to_i915(dev)->gvt; | |
| 94 | + | |
| 95 | + type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 96 | + if (!type) | |
| 97 | + return 0; | |
| 98 | + | |
| 99 | + return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" | |
| 100 | + "fence: %d\nresolution: %s\n" | |
| 101 | + "weight: %d\n", | |
| 102 | + BYTES_TO_MB(type->low_gm_size), | |
| 103 | + BYTES_TO_MB(type->high_gm_size), | |
| 104 | + type->fence, vgpu_edid_str(type->resolution), | |
| 105 | + type->weight); | |
| 106 | +} | |
| 107 | + | |
| 108 | +static MDEV_TYPE_ATTR_RO(available_instances); | |
| 109 | +static MDEV_TYPE_ATTR_RO(device_api); | |
| 110 | +static MDEV_TYPE_ATTR_RO(description); | |
| 111 | + | |
| 112 | +static struct attribute *gvt_type_attrs[] = { | |
| 113 | + &mdev_type_attr_available_instances.attr, | |
| 114 | + &mdev_type_attr_device_api.attr, | |
| 115 | + &mdev_type_attr_description.attr, | |
| 116 | + NULL, | |
| 117 | +}; | |
| 118 | + | |
| 119 | +static struct attribute_group *gvt_vgpu_type_groups[] = { | |
| 120 | + [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, | |
| 121 | +}; | |
| 122 | + | |
| 123 | +static bool intel_get_gvt_attrs(struct attribute ***type_attrs, | |
| 124 | + struct attribute_group ***intel_vgpu_type_groups) | |
| 125 | +{ | |
| 126 | + *type_attrs = gvt_type_attrs; | |
| 127 | + *intel_vgpu_type_groups = gvt_vgpu_type_groups; | |
| 128 | + return true; | |
| 129 | +} | |
| 130 | + | |
| 131 | +static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt) | |
| 132 | +{ | |
| 133 | + int i, j; | |
| 134 | + struct intel_vgpu_type *type; | |
| 135 | + struct attribute_group *group; | |
| 136 | + | |
| 137 | + for (i = 0; i < gvt->num_types; i++) { | |
| 138 | + type = &gvt->types[i]; | |
| 139 | + | |
| 140 | + group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); | |
| 141 | + if (WARN_ON(!group)) | |
| 142 | + goto unwind; | |
| 143 | + | |
| 144 | + group->name = type->name; | |
| 145 | + group->attrs = gvt_type_attrs; | |
| 146 | + gvt_vgpu_type_groups[i] = group; | |
| 147 | + } | |
| 148 | + | |
| 149 | + return true; | |
| 150 | + | |
| 151 | +unwind: | |
| 152 | + for (j = 0; j < i; j++) { | |
| 153 | + group = gvt_vgpu_type_groups[j]; | |
| 154 | + kfree(group); | |
| 155 | + } | |
| 156 | + | |
| 157 | + return false; | |
| 158 | +} | |
| 159 | + | |
| 160 | +static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt) | |
| 161 | +{ | |
| 162 | + int i; | |
| 163 | + struct attribute_group *group; | |
| 164 | + | |
| 165 | + for (i = 0; i < gvt->num_types; i++) { | |
| 166 | + group = gvt_vgpu_type_groups[i]; | |
| 167 | + gvt_vgpu_type_groups[i] = NULL; | |
| 168 | + kfree(group); | |
| 169 | + } | |
| 170 | +} | |
| 171 | + | |
| 47 | 172 | static const struct intel_gvt_ops intel_gvt_ops = { |
| 48 | 173 | .emulate_cfg_read = intel_vgpu_emulate_cfg_read, |
| 49 | 174 | .emulate_cfg_write = intel_vgpu_emulate_cfg_write, |
| @@ -54,6 +179,8 @@ static const struct intel_gvt_ops intel_gvt_ops = { · 4 unmodified lines | ||
| 54 | 179 | .vgpu_reset = intel_gvt_reset_vgpu, |
| 55 | 180 | .vgpu_activate = intel_gvt_activate_vgpu, |
| 56 | 181 | .vgpu_deactivate = intel_gvt_deactivate_vgpu, |
| 182 | + .gvt_find_vgpu_type = intel_gvt_find_vgpu_type, | |
| 183 | + .get_gvt_attrs = intel_get_gvt_attrs, | |
| 57 | 184 | }; |
| 58 | 185 | |
| 59 | 186 | /** |
| @@ -191,17 +318,18 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) · 131 unmodified lines | ||
| 191 | 318 | if (WARN_ON(!gvt)) |
| 192 | 319 | return; |
| 193 | 320 | |
| 321 | + intel_gvt_debugfs_clean(gvt); | |
| 194 | 322 | clean_service_thread(gvt); |
| 195 | 323 | intel_gvt_clean_cmd_parser(gvt); |
| 196 | 324 | intel_gvt_clean_sched_policy(gvt); |
| 197 | 325 | intel_gvt_clean_workload_scheduler(gvt); |
| 198 | − intel_gvt_clean_opregion(gvt); | |
| 199 | 326 | intel_gvt_clean_gtt(gvt); |
| 200 | 327 | intel_gvt_clean_irq(gvt); |
| 201 | 328 | intel_gvt_clean_mmio_info(gvt); |
| 202 | 329 | intel_gvt_free_firmware(gvt); |
| 203 | 330 | |
| 204 | 331 | intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt); |
| 332 | + intel_gvt_cleanup_vgpu_type_groups(gvt); | |
| 205 | 333 | intel_gvt_clean_vgpu_types(gvt); |
| 206 | 334 | |
| 207 | 335 | idr_destroy(&gvt->vgpu_idr); |
| @@ -268,13 +396,9 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) · 60 unmodified lines | ||
| 268 | 396 | if (ret) |
| 269 | 397 | goto out_clean_irq; |
| 270 | 398 | |
| 271 | − ret = intel_gvt_init_opregion(gvt); | |
| 272 | − if (ret) | |
| 273 | − goto out_clean_gtt; | |
| 274 | − | |
| 275 | 399 | ret = intel_gvt_init_workload_scheduler(gvt); |
| 276 | 400 | if (ret) |
| 277 | − goto out_clean_opregion; | |
| 401 | + goto out_clean_gtt; | |
| 278 | 402 | |
| 279 | 403 | ret = intel_gvt_init_sched_policy(gvt); |
| 280 | 404 | if (ret) |
| @@ -292,6 +416,12 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 292 | 416 | if (ret) |
| 293 | 417 | goto out_clean_thread; |
| 294 | 418 | |
| 419 | + ret = intel_gvt_init_vgpu_type_groups(gvt); | |
| 420 | + if (ret == false) { | |
| 421 | + gvt_err("failed to init vgpu type groups: %d\n", ret); | |
| 422 | + goto out_clean_types; | |
| 423 | + } | |
| 424 | + | |
| 295 | 425 | ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt, |
| 296 | 426 | &intel_gvt_ops); |
| 297 | 427 | if (ret) { |
| @@ -307,6 +437,10 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 307 | 437 | } |
| 308 | 438 | gvt->idle_vgpu = vgpu; |
| 309 | 439 | |
| 440 | + ret = intel_gvt_debugfs_init(gvt); | |
| 441 | + if (ret) | |
| 442 | + gvt_err("debugfs registeration failed, go on.\n"); | |
| 443 | + | |
| 310 | 444 | gvt_dbg_core("gvt device initialization is done\n"); |
| 311 | 445 | dev_priv->gvt = gvt; |
| 312 | 446 | return 0; |
| @@ -321,8 +455,6 @@ out_clean_sched_policy: · 8 unmodified lines | ||
| 321 | 455 | intel_gvt_clean_sched_policy(gvt); |
| 322 | 456 | out_clean_workload_scheduler: |
| 323 | 457 | intel_gvt_clean_workload_scheduler(gvt); |
| 324 | −out_clean_opregion: | |
| 325 | − intel_gvt_clean_opregion(gvt); | |
| 326 | 458 | out_clean_gtt: |
| 327 | 459 | intel_gvt_clean_gtt(gvt); |
| 328 | 460 | out_clean_irq: |
| @@ -125,7 +125,6 @@ struct intel_vgpu_irq { · 124 unmodified lines | ||
| 125 | 125 | struct intel_vgpu_opregion { |
| 126 | 126 | void *va; |
| 127 | 127 | u32 gfn[INTEL_GVT_OPREGION_PAGES]; |
| 128 | − struct page *pages[INTEL_GVT_OPREGION_PAGES]; | |
| 129 | 128 | }; |
| 130 | 129 | |
| 131 | 130 | #define vgpu_opregion(vgpu) (&(vgpu->opregion)) |
| @@ -142,6 +141,33 @@ struct vgpu_sched_ctl { · 10 unmodified lines | ||
| 142 | 141 | int weight; |
| 143 | 142 | }; |
| 144 | 143 | |
| 144 | +enum { | |
| 145 | + INTEL_VGPU_EXECLIST_SUBMISSION = 1, | |
| 146 | + INTEL_VGPU_GUC_SUBMISSION, | |
| 147 | +}; | |
| 148 | + | |
| 149 | +struct intel_vgpu_submission_ops { | |
| 150 | + const char *name; | |
| 151 | + int (*init)(struct intel_vgpu *vgpu); | |
| 152 | + void (*clean)(struct intel_vgpu *vgpu); | |
| 153 | + void (*reset)(struct intel_vgpu *vgpu, unsigned long engine_mask); | |
| 154 | +}; | |
| 155 | + | |
| 156 | +struct intel_vgpu_submission { | |
| 157 | + struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; | |
| 158 | + struct list_head workload_q_head[I915_NUM_ENGINES]; | |
| 159 | + struct kmem_cache *workloads; | |
| 160 | + atomic_t running_workload_num; | |
| 161 | + struct i915_gem_context *shadow_ctx; | |
| 162 | + DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES); | |
| 163 | + DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); | |
| 164 | + void *ring_scan_buffer[I915_NUM_ENGINES]; | |
| 165 | + int ring_scan_buffer_size[I915_NUM_ENGINES]; | |
| 166 | + const struct intel_vgpu_submission_ops *ops; | |
| 167 | + int virtual_submission_interface; | |
| 168 | + bool active; | |
| 169 | +}; | |
| 170 | + | |
| 145 | 171 | struct intel_vgpu { |
| 146 | 172 | struct intel_gvt *gvt; |
| 147 | 173 | int id; |
| @@ -161,16 +187,10 @@ struct intel_vgpu { · 13 unmodified lines | ||
| 161 | 187 | struct intel_vgpu_gtt gtt; |
| 162 | 188 | struct intel_vgpu_opregion opregion; |
| 163 | 189 | struct intel_vgpu_display display; |
| 164 | − struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; | |
| 165 | − struct list_head workload_q_head[I915_NUM_ENGINES]; | |
| 166 | − struct kmem_cache *workloads; | |
| 167 | − atomic_t running_workload_num; | |
| 168 | − /* 1/2K for each reserve ring buffer */ | |
| 169 | − void *reserve_ring_buffer_va[I915_NUM_ENGINES]; | |
| 170 | − int reserve_ring_buffer_size[I915_NUM_ENGINES]; | |
| 171 | − DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); | |
| 172 | − struct i915_gem_context *shadow_ctx; | |
| 173 | − DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES); | |
| 190 | + struct intel_vgpu_submission submission; | |
| 191 | + u32 hws_pga[I915_NUM_ENGINES]; | |
| 192 | + | |
| 193 | + struct dentry *debugfs; | |
| 174 | 194 | |
| 175 | 195 | #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) |
| 176 | 196 | struct { |
| @@ -190,6 +210,10 @@ struct intel_vgpu { · 13 unmodified lines | ||
| 190 | 210 | #endif |
| 191 | 211 | }; |
| 192 | 212 | |
| 213 | +/* validating GM healthy status*/ | |
| 214 | +#define vgpu_is_vm_unhealthy(ret_val) \ | |
| 215 | + (((ret_val) == -EBADRQC) || ((ret_val) == -EFAULT)) | |
| 216 | + | |
| 193 | 217 | struct intel_gvt_gm { |
| 194 | 218 | unsigned long vgpu_allocated_low_gm_size; |
| 195 | 219 | unsigned long vgpu_allocated_high_gm_size; |
| @@ -231,7 +255,7 @@ struct intel_gvt_mmio { · 35 unmodified lines | ||
| 231 | 255 | unsigned int num_mmio_block; |
| 232 | 256 | |
| 233 | 257 | DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS); |
| 234 | − unsigned int num_tracked_mmio; | |
| 258 | + unsigned long num_tracked_mmio; | |
| 235 | 259 | }; |
| 236 | 260 | |
| 237 | 261 | struct intel_gvt_firmware { |
| @@ -240,11 +264,6 @@ struct intel_gvt_firmware { · 2 unmodified lines | ||
| 240 | 264 | bool firmware_loaded; |
| 241 | 265 | }; |
| 242 | 266 | |
| 243 | −struct intel_gvt_opregion { | |
| 244 | − void *opregion_va; | |
| 245 | − u32 opregion_pa; | |
| 246 | −}; | |
| 247 | − | |
| 248 | 267 | #define NR_MAX_INTEL_VGPU_TYPES 20 |
| 249 | 268 | struct intel_vgpu_type { |
| 250 | 269 | char name[16]; |
| @@ -268,7 +287,6 @@ struct intel_gvt { · 17 unmodified lines | ||
| 268 | 287 | struct intel_gvt_firmware firmware; |
| 269 | 288 | struct intel_gvt_irq irq; |
| 270 | 289 | struct intel_gvt_gtt gtt; |
| 271 | − struct intel_gvt_opregion opregion; | |
| 272 | 290 | struct intel_gvt_workload_scheduler scheduler; |
| 273 | 291 | struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES]; |
| 274 | 292 | DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); |
| @@ -279,6 +297,8 @@ struct intel_gvt { · 4 unmodified lines | ||
| 279 | 297 | struct task_struct *service_thread; |
| 280 | 298 | wait_queue_head_t service_thread_wq; |
| 281 | 299 | unsigned long service_request; |
| 300 | + | |
| 301 | + struct dentry *debugfs_root; | |
| 282 | 302 | }; |
| 283 | 303 | |
| 284 | 304 | static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915) |
| @@ -484,9 +504,6 @@ static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar) · 199 unmodified lines | ||
| 484 | 504 | PCI_BASE_ADDRESS_MEM_MASK; |
| 485 | 505 | } |
| 486 | 506 | |
| 487 | −void intel_gvt_clean_opregion(struct intel_gvt *gvt); | |
| 488 | −int intel_gvt_init_opregion(struct intel_gvt *gvt); | |
| 489 | − | |
| 490 | 507 | void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu); |
| 491 | 508 | int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa); |
| 492 | 509 | |
| @@ -494,6 +511,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci); · 1 unmodified line | ||
| 494 | 511 | void populate_pvinfo_page(struct intel_vgpu *vgpu); |
| 495 | 512 | |
| 496 | 513 | int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload); |
| 514 | +void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason); | |
| 497 | 515 | |
| 498 | 516 | struct intel_gvt_ops { |
| 499 | 517 | int (*emulate_cfg_read)(struct intel_vgpu *, unsigned int, void *, |
| @@ -510,12 +528,17 @@ struct intel_gvt_ops { · 10 unmodified lines | ||
| 510 | 528 | void (*vgpu_reset)(struct intel_vgpu *); |
| 511 | 529 | void (*vgpu_activate)(struct intel_vgpu *); |
| 512 | 530 | void (*vgpu_deactivate)(struct intel_vgpu *); |
| 531 | + struct intel_vgpu_type *(*gvt_find_vgpu_type)(struct intel_gvt *gvt, | |
| 532 | + const char *name); | |
| 533 | + bool (*get_gvt_attrs)(struct attribute ***type_attrs, | |
| 534 | + struct attribute_group ***intel_vgpu_type_groups); | |
| 513 | 535 | }; |
| 514 | 536 | |
| 515 | 537 | |
| 516 | 538 | enum { |
| 517 | 539 | GVT_FAILSAFE_UNSUPPORTED_GUEST, |
| 518 | 540 | GVT_FAILSAFE_INSUFFICIENT_RESOURCE, |
| 541 | + GVT_FAILSAFE_GUEST_ERR, | |
| 519 | 542 | }; |
| 520 | 543 | |
| 521 | 544 | static inline void mmio_hw_access_pre(struct drm_i915_private *dev_priv) |
| @@ -591,6 +614,12 @@ static inline bool intel_gvt_mmio_has_mode_mask( · 69 unmodified lines | ||
| 591 | 614 | return gvt->mmio.mmio_attribute[offset >> 2] & F_MODE_MASK; |
| 592 | 615 | } |
| 593 | 616 | |
| 617 | +int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu); | |
| 618 | +void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu); | |
| 619 | +int intel_gvt_debugfs_init(struct intel_gvt *gvt); | |
| 620 | +void intel_gvt_debugfs_clean(struct intel_gvt *gvt); | |
| 621 | + | |
| 622 | + | |
| 594 | 623 | #include "trace.h" |
| 595 | 624 | #include "mpt.h" |
| 596 | 625 | |
| @@ -137,17 +137,26 @@ static int new_mmio_info(struct intel_gvt *gvt, · 136 unmodified lines | ||
| 137 | 137 | return 0; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | −static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) | |
| 140 | +/** | |
| 141 | + * intel_gvt_render_mmio_to_ring_id - convert a mmio offset into ring id | |
| 142 | + * @gvt: a GVT device | |
| 143 | + * @offset: register offset | |
| 144 | + * | |
| 145 | + * Returns: | |
| 146 | + * Ring ID on success, negative error code if failed. | |
| 147 | + */ | |
| 148 | +int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt, | |
| 149 | + unsigned int offset) | |
| 141 | 150 | { |
| 142 | 151 | enum intel_engine_id id; |
| 143 | 152 | struct intel_engine_cs *engine; |
| 144 | 153 | |
| 145 | − reg &= ~GENMASK(11, 0); | |
| 154 | + offset &= ~GENMASK(11, 0); | |
| 146 | 155 | for_each_engine(engine, gvt->dev_priv, id) { |
| 147 | − if (engine->mmio_base == reg) | |
| 156 | + if (engine->mmio_base == offset) | |
| 148 | 157 | return id; |
| 149 | 158 | } |
| 150 | − return -1; | |
| 159 | + return -ENODEV; | |
| 151 | 160 | } |
| 152 | 161 | |
| 153 | 162 | #define offset_to_fence_num(offset) \ |
| @@ -157,7 +166,7 @@ static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) · 3 unmodified lines | ||
| 157 | 166 | (num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) |
| 158 | 167 | |
| 159 | 168 | |
| 160 | −static void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason) | |
| 169 | +void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason) | |
| 161 | 170 | { |
| 162 | 171 | switch (reason) { |
| 163 | 172 | case GVT_FAILSAFE_UNSUPPORTED_GUEST: |
| @@ -165,6 +174,8 @@ static void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason) · 1 unmodified line | ||
| 165 | 174 | break; |
| 166 | 175 | case GVT_FAILSAFE_INSUFFICIENT_RESOURCE: |
| 167 | 176 | pr_err("Graphics resource is not enough for the guest\n"); |
| 177 | + case GVT_FAILSAFE_GUEST_ERR: | |
| 178 | + pr_err("GVT Internal error for the guest\n"); | |
| 168 | 179 | default: |
| 169 | 180 | break; |
| 170 | 181 | } |
| @@ -1369,6 +1380,34 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset, · 1198 unmodified lines | ||
| 1369 | 1380 | return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes); |
| 1370 | 1381 | } |
| 1371 | 1382 | |
| 1383 | +static int hws_pga_write(struct intel_vgpu *vgpu, unsigned int offset, | |
| 1384 | + void *p_data, unsigned int bytes) | |
| 1385 | +{ | |
| 1386 | + u32 value = *(u32 *)p_data; | |
| 1387 | + int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); | |
| 1388 | + | |
| 1389 | + if (!intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) { | |
| 1390 | + gvt_vgpu_err("VM(%d) write invalid HWSP address, reg:0x%x, value:0x%x\n", | |
| 1391 | + vgpu->id, offset, value); | |
| 1392 | + return -EINVAL; | |
| 1393 | + } | |
| 1394 | + /* | |
| 1395 | + * Need to emulate all the HWSP register write to ensure host can | |
| 1396 | + * update the VM CSB status correctly. Here listed registers can | |
| 1397 | + * support BDW, SKL or other platforms with same HWSP registers. | |
| 1398 | + */ | |
| 1399 | + if (unlikely(ring_id < 0 || ring_id > I915_NUM_ENGINES)) { | |
| 1400 | + gvt_vgpu_err("VM(%d) access unknown hardware status page register:0x%x\n", | |
| 1401 | + vgpu->id, offset); | |
| 1402 | + return -EINVAL; | |
| 1403 | + } | |
| 1404 | + vgpu->hws_pga[ring_id] = value; | |
| 1405 | + gvt_dbg_mmio("VM(%d) write: 0x%x to HWSP: 0x%x\n", | |
| 1406 | + vgpu->id, value, offset); | |
| 1407 | + | |
| 1408 | + return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes); | |
| 1409 | +} | |
| 1410 | + | |
| 1372 | 1411 | static int skl_power_well_ctl_write(struct intel_vgpu *vgpu, |
| 1373 | 1412 | unsigned int offset, void *p_data, unsigned int bytes) |
| 1374 | 1413 | { |
| @@ -1398,18 +1437,36 @@ static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, · 23 unmodified lines | ||
| 1398 | 1437 | static int mmio_read_from_hw(struct intel_vgpu *vgpu, |
| 1399 | 1438 | unsigned int offset, void *p_data, unsigned int bytes) |
| 1400 | 1439 | { |
| 1401 | − struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 1440 | + struct intel_gvt *gvt = vgpu->gvt; | |
| 1441 | + struct drm_i915_private *dev_priv = gvt->dev_priv; | |
| 1442 | + int ring_id; | |
| 1443 | + u32 ring_base; | |
| 1444 | + | |
| 1445 | + ring_id = intel_gvt_render_mmio_to_ring_id(gvt, offset); | |
| 1446 | + /** | |
| 1447 | + * Read HW reg in following case | |
| 1448 | + * a. the offset isn't a ring mmio | |
| 1449 | + * b. the offset's ring is running on hw. | |
| 1450 | + * c. the offset is ring time stamp mmio | |
| 1451 | + */ | |
| 1452 | + if (ring_id >= 0) | |
| 1453 | + ring_base = dev_priv->engine[ring_id]->mmio_base; | |
| 1454 | + | |
| 1455 | + if (ring_id < 0 || vgpu == gvt->scheduler.engine_owner[ring_id] || | |
| 1456 | + offset == i915_mmio_reg_offset(RING_TIMESTAMP(ring_base)) || | |
| 1457 | + offset == i915_mmio_reg_offset(RING_TIMESTAMP_UDW(ring_base))) { | |
| 1458 | + mmio_hw_access_pre(dev_priv); | |
| 1459 | + vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); | |
| 1460 | + mmio_hw_access_post(dev_priv); | |
| 1461 | + } | |
| 1402 | 1462 | |
| 1403 | − mmio_hw_access_pre(dev_priv); | |
| 1404 | − vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); | |
| 1405 | − mmio_hw_access_post(dev_priv); | |
| 1406 | 1463 | return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); |
| 1407 | 1464 | } |
| 1408 | 1465 | |
| 1409 | 1466 | static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, |
| 1410 | 1467 | void *p_data, unsigned int bytes) |
| 1411 | 1468 | { |
| 1412 | − int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | |
| 1469 | + int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); | |
| 1413 | 1470 | struct intel_vgpu_execlist *execlist; |
| 1414 | 1471 | u32 data = *(u32 *)p_data; |
| 1415 | 1472 | int ret = 0; |
| @@ -1417,9 +1474,9 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, · 1 unmodified line | ||
| 1417 | 1474 | if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1)) |
| 1418 | 1475 | return -EINVAL; |
| 1419 | 1476 | |
| 1420 | − execlist = &vgpu->execlist[ring_id]; | |
| 1477 | + execlist = &vgpu->submission.execlist[ring_id]; | |
| 1421 | 1478 | |
| 1422 | − execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; | |
| 1479 | + execlist->elsp_dwords.data[3 - execlist->elsp_dwords.index] = data; | |
| 1423 | 1480 | if (execlist->elsp_dwords.index == 3) { |
| 1424 | 1481 | ret = intel_vgpu_submit_execlist(vgpu, ring_id); |
| 1425 | 1482 | if(ret) |
| @@ -1435,9 +1492,11 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, · 9 unmodified lines | ||
| 1435 | 1492 | static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, |
| 1436 | 1493 | void *p_data, unsigned int bytes) |
| 1437 | 1494 | { |
| 1495 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1438 | 1496 | u32 data = *(u32 *)p_data; |
| 1439 | − int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | |
| 1497 | + int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); | |
| 1440 | 1498 | bool enable_execlist; |
| 1499 | + int ret; | |
| 1441 | 1500 | |
| 1442 | 1501 | write_vreg(vgpu, offset, p_data, bytes); |
| 1443 | 1502 | |
| @@ -1459,8 +1518,18 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, · 15 unmodified lines | ||
| 1459 | 1518 | (enable_execlist ? "enabling" : "disabling"), |
| 1460 | 1519 | ring_id); |
| 1461 | 1520 | |
| 1462 | − if (enable_execlist) | |
| 1463 | − intel_vgpu_start_schedule(vgpu); | |
| 1521 | + if (!enable_execlist) | |
| 1522 | + return 0; | |
| 1523 | + | |
| 1524 | + if (s->active) | |
| 1525 | + return 0; | |
| 1526 | + | |
| 1527 | + ret = intel_vgpu_select_submission_ops(vgpu, | |
| 1528 | + INTEL_VGPU_EXECLIST_SUBMISSION); | |
| 1529 | + if (ret) | |
| 1530 | + return ret; | |
| 1531 | + | |
| 1532 | + intel_vgpu_start_schedule(vgpu); | |
| 1464 | 1533 | } |
| 1465 | 1534 | return 0; |
| 1466 | 1535 | } |
| @@ -1492,7 +1561,7 @@ static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu, · 25 unmodified lines | ||
| 1492 | 1561 | default: |
| 1493 | 1562 | return -EINVAL; |
| 1494 | 1563 | } |
| 1495 | − set_bit(id, (void *)vgpu->tlb_handle_pending); | |
| 1564 | + set_bit(id, (void *)vgpu->submission.tlb_handle_pending); | |
| 1496 | 1565 | |
| 1497 | 1566 | return 0; |
| 1498 | 1567 | } |
| @@ -2478,7 +2547,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) · 979 unmodified lines | ||
| 2478 | 2547 | MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); |
| 2479 | 2548 | #undef RING_REG |
| 2480 | 2549 | |
| 2481 | − MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); | |
| 2550 | + MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, hws_pga_write); | |
| 2482 | 2551 | |
| 2483 | 2552 | MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); |
| 2484 | 2553 | |
| @@ -2879,14 +2948,46 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt) · 394 unmodified lines | ||
| 2879 | 2948 | gvt->mmio.mmio_block = mmio_blocks; |
| 2880 | 2949 | gvt->mmio.num_mmio_block = ARRAY_SIZE(mmio_blocks); |
| 2881 | 2950 | |
| 2882 | − gvt_dbg_mmio("traced %u virtual mmio registers\n", | |
| 2883 | − gvt->mmio.num_tracked_mmio); | |
| 2884 | 2951 | return 0; |
| 2885 | 2952 | err: |
| 2886 | 2953 | intel_gvt_clean_mmio_info(gvt); |
| 2887 | 2954 | return ret; |
| 2888 | 2955 | } |
| 2889 | 2956 | |
| 2957 | +/** | |
| 2958 | + * intel_gvt_for_each_tracked_mmio - iterate each tracked mmio | |
| 2959 | + * @gvt: a GVT device | |
| 2960 | + * @handler: the handler | |
| 2961 | + * @data: private data given to handler | |
| 2962 | + * | |
| 2963 | + * Returns: | |
| 2964 | + * Zero on success, negative error code if failed. | |
| 2965 | + */ | |
| 2966 | +int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt, | |
| 2967 | + int (*handler)(struct intel_gvt *gvt, u32 offset, void *data), | |
| 2968 | + void *data) | |
| 2969 | +{ | |
| 2970 | + struct gvt_mmio_block *block = gvt->mmio.mmio_block; | |
| 2971 | + struct intel_gvt_mmio_info *e; | |
| 2972 | + int i, j, ret; | |
| 2973 | + | |
| 2974 | + hash_for_each(gvt->mmio.mmio_info_table, i, e, node) { | |
| 2975 | + ret = handler(gvt, e->offset, data); | |
| 2976 | + if (ret) | |
| 2977 | + return ret; | |
| 2978 | + } | |
| 2979 | + | |
| 2980 | + for (i = 0; i < gvt->mmio.num_mmio_block; i++, block++) { | |
| 2981 | + for (j = 0; j < block->size; j += 4) { | |
| 2982 | + ret = handler(gvt, | |
| 2983 | + INTEL_GVT_MMIO_OFFSET(block->offset) + j, | |
| 2984 | + data); | |
| 2985 | + if (ret) | |
| 2986 | + return ret; | |
| 2987 | + } | |
| 2988 | + } | |
| 2989 | + return 0; | |
| 2990 | +} | |
| 2890 | 2991 | |
| 2891 | 2992 | /** |
| 2892 | 2993 | * intel_vgpu_default_mmio_read - default MMIO read handler |
| @@ -248,120 +248,6 @@ static void gvt_cache_destroy(struct intel_vgpu *vgpu) · 247 unmodified lines | ||
| 248 | 248 | } |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | −static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt, | |
| 252 | − const char *name) | |
| 253 | −{ | |
| 254 | − int i; | |
| 255 | − struct intel_vgpu_type *t; | |
| 256 | − const char *driver_name = dev_driver_string( | |
| 257 | − &gvt->dev_priv->drm.pdev->dev); | |
| 258 | − | |
| 259 | − for (i = 0; i < gvt->num_types; i++) { | |
| 260 | − t = &gvt->types[i]; | |
| 261 | − if (!strncmp(t->name, name + strlen(driver_name) + 1, | |
| 262 | − sizeof(t->name))) | |
| 263 | − return t; | |
| 264 | − } | |
| 265 | − | |
| 266 | − return NULL; | |
| 267 | −} | |
| 268 | − | |
| 269 | −static ssize_t available_instances_show(struct kobject *kobj, | |
| 270 | − struct device *dev, char *buf) | |
| 271 | −{ | |
| 272 | − struct intel_vgpu_type *type; | |
| 273 | − unsigned int num = 0; | |
| 274 | − void *gvt = kdev_to_i915(dev)->gvt; | |
| 275 | − | |
| 276 | − type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 277 | − if (!type) | |
| 278 | − num = 0; | |
| 279 | − else | |
| 280 | − num = type->avail_instance; | |
| 281 | − | |
| 282 | − return sprintf(buf, "%u\n", num); | |
| 283 | −} | |
| 284 | − | |
| 285 | −static ssize_t device_api_show(struct kobject *kobj, struct device *dev, | |
| 286 | − char *buf) | |
| 287 | −{ | |
| 288 | − return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING); | |
| 289 | −} | |
| 290 | − | |
| 291 | −static ssize_t description_show(struct kobject *kobj, struct device *dev, | |
| 292 | − char *buf) | |
| 293 | −{ | |
| 294 | − struct intel_vgpu_type *type; | |
| 295 | − void *gvt = kdev_to_i915(dev)->gvt; | |
| 296 | − | |
| 297 | − type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 298 | − if (!type) | |
| 299 | − return 0; | |
| 300 | − | |
| 301 | − return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" | |
| 302 | − "fence: %d\nresolution: %s\n" | |
| 303 | − "weight: %d\n", | |
| 304 | − BYTES_TO_MB(type->low_gm_size), | |
| 305 | − BYTES_TO_MB(type->high_gm_size), | |
| 306 | − type->fence, vgpu_edid_str(type->resolution), | |
| 307 | − type->weight); | |
| 308 | −} | |
| 309 | − | |
| 310 | −static MDEV_TYPE_ATTR_RO(available_instances); | |
| 311 | −static MDEV_TYPE_ATTR_RO(device_api); | |
| 312 | −static MDEV_TYPE_ATTR_RO(description); | |
| 313 | − | |
| 314 | −static struct attribute *type_attrs[] = { | |
| 315 | − &mdev_type_attr_available_instances.attr, | |
| 316 | − &mdev_type_attr_device_api.attr, | |
| 317 | − &mdev_type_attr_description.attr, | |
| 318 | − NULL, | |
| 319 | −}; | |
| 320 | − | |
| 321 | −static struct attribute_group *intel_vgpu_type_groups[] = { | |
| 322 | − [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, | |
| 323 | −}; | |
| 324 | − | |
| 325 | −static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt) | |
| 326 | −{ | |
| 327 | − int i, j; | |
| 328 | − struct intel_vgpu_type *type; | |
| 329 | − struct attribute_group *group; | |
| 330 | − | |
| 331 | − for (i = 0; i < gvt->num_types; i++) { | |
| 332 | − type = &gvt->types[i]; | |
| 333 | − | |
| 334 | − group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); | |
| 335 | − if (WARN_ON(!group)) | |
| 336 | − goto unwind; | |
| 337 | − | |
| 338 | − group->name = type->name; | |
| 339 | − group->attrs = type_attrs; | |
| 340 | − intel_vgpu_type_groups[i] = group; | |
| 341 | − } | |
| 342 | − | |
| 343 | − return true; | |
| 344 | − | |
| 345 | −unwind: | |
| 346 | − for (j = 0; j < i; j++) { | |
| 347 | − group = intel_vgpu_type_groups[j]; | |
| 348 | − kfree(group); | |
| 349 | − } | |
| 350 | − | |
| 351 | − return false; | |
| 352 | −} | |
| 353 | − | |
| 354 | −static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt) | |
| 355 | −{ | |
| 356 | − int i; | |
| 357 | − struct attribute_group *group; | |
| 358 | − | |
| 359 | − for (i = 0; i < gvt->num_types; i++) { | |
| 360 | − group = intel_vgpu_type_groups[i]; | |
| 361 | − kfree(group); | |
| 362 | − } | |
| 363 | −} | |
| 364 | − | |
| 365 | 251 | static void kvmgt_protect_table_init(struct kvmgt_guest_info *info) |
| 366 | 252 | { |
| 367 | 253 | hash_init(info->ptable); |
| @@ -441,7 +327,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev) · 73 unmodified lines | ||
| 441 | 327 | pdev = mdev_parent_dev(mdev); |
| 442 | 328 | gvt = kdev_to_i915(pdev)->gvt; |
| 443 | 329 | |
| 444 | − type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 330 | + type = intel_gvt_ops->gvt_find_vgpu_type(gvt, kobject_name(kobj)); | |
| 445 | 331 | if (!type) { |
| 446 | 332 | gvt_vgpu_err("failed to find type %s to create\n", |
| 447 | 333 | kobject_name(kobj)); |
| @@ -1188,7 +1074,7 @@ hw_id_show(struct device *dev, struct device_attribute *attr, · 740 unmodified lines | ||
| 1188 | 1074 | struct intel_vgpu *vgpu = (struct intel_vgpu *) |
| 1189 | 1075 | mdev_get_drvdata(mdev); |
| 1190 | 1076 | return sprintf(buf, "%u\n", |
| 1191 | − vgpu->shadow_ctx->hw_id); | |
| 1077 | + vgpu->submission.shadow_ctx->hw_id); | |
| 1192 | 1078 | } |
| 1193 | 1079 | return sprintf(buf, "\n"); |
| 1194 | 1080 | } |
| @@ -1212,8 +1098,7 @@ static const struct attribute_group *intel_vgpu_groups[] = { · 17 unmodified lines | ||
| 1212 | 1098 | NULL, |
| 1213 | 1099 | }; |
| 1214 | 1100 | |
| 1215 | −static const struct mdev_parent_ops intel_vgpu_ops = { | |
| 1216 | − .supported_type_groups = intel_vgpu_type_groups, | |
| 1101 | +static struct mdev_parent_ops intel_vgpu_ops = { | |
| 1217 | 1102 | .mdev_attr_groups = intel_vgpu_groups, |
| 1218 | 1103 | .create = intel_vgpu_create, |
| 1219 | 1104 | .remove = intel_vgpu_remove, |
| @@ -1229,17 +1114,20 @@ static const struct mdev_parent_ops intel_vgpu_ops = { · 9 unmodified lines | ||
| 1229 | 1114 | |
| 1230 | 1115 | static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops) |
| 1231 | 1116 | { |
| 1232 | − if (!intel_gvt_init_vgpu_type_groups(gvt)) | |
| 1233 | − return -EFAULT; | |
| 1117 | + struct attribute **kvm_type_attrs; | |
| 1118 | + struct attribute_group **kvm_vgpu_type_groups; | |
| 1234 | 1119 | |
| 1235 | 1120 | intel_gvt_ops = ops; |
| 1121 | + if (!intel_gvt_ops->get_gvt_attrs(&kvm_type_attrs, | |
| 1122 | + &kvm_vgpu_type_groups)) | |
| 1123 | + return -EFAULT; | |
| 1124 | + intel_vgpu_ops.supported_type_groups = kvm_vgpu_type_groups; | |
| 1236 | 1125 | |
| 1237 | 1126 | return mdev_register_device(dev, &intel_vgpu_ops); |
| 1238 | 1127 | } |
| 1239 | 1128 | |
| 1240 | 1129 | static void kvmgt_host_exit(struct device *dev, void *gvt) |
| 1241 | 1130 | { |
| 1242 | − intel_gvt_cleanup_vgpu_type_groups(gvt); | |
| 1243 | 1131 | mdev_unregister_device(dev); |
| 1244 | 1132 | } |
| 1245 | 1133 | |
| @@ -117,18 +117,18 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, · 116 unmodified lines | ||
| 117 | 117 | else |
| 118 | 118 | memcpy(pt, p_data, bytes); |
| 119 | 119 | |
| 120 | − } else if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { | |
| 121 | − struct intel_vgpu_guest_page *gp; | |
| 120 | + } else if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) { | |
| 121 | + struct intel_vgpu_page_track *t; | |
| 122 | 122 | |
| 123 | 123 | /* Since we enter the failsafe mode early during guest boot, |
| 124 | 124 | * guest may not have chance to set up its ppgtt table, so |
| 125 | 125 | * there should not be any wp pages for guest. Keep the wp |
| 126 | 126 | * related code here in case we need to handle it in furture. |
| 127 | 127 | */ |
| 128 | − gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); | |
| 129 | − if (gp) { | |
| 128 | + t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT); | |
| 129 | + if (t) { | |
| 130 | 130 | /* remove write protection to prevent furture traps */ |
| 131 | − intel_vgpu_clean_guest_page(vgpu, gp); | |
| 131 | + intel_vgpu_clean_page_track(vgpu, t); | |
| 132 | 132 | if (read) |
| 133 | 133 | intel_gvt_hypervisor_read_gpa(vgpu, pa, |
| 134 | 134 | p_data, bytes); |
| @@ -170,17 +170,17 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa, · 35 unmodified lines | ||
| 170 | 170 | return ret; |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | − if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { | |
| 174 | − struct intel_vgpu_guest_page *gp; | |
| 173 | + if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) { | |
| 174 | + struct intel_vgpu_page_track *t; | |
| 175 | 175 | |
| 176 | − gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); | |
| 177 | − if (gp) { | |
| 176 | + t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT); | |
| 177 | + if (t) { | |
| 178 | 178 | ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, |
| 179 | 179 | p_data, bytes); |
| 180 | 180 | if (ret) { |
| 181 | 181 | gvt_vgpu_err("guest page read error %d, " |
| 182 | 182 | "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", |
| 183 | − ret, gp->gfn, pa, *(u32 *)p_data, | |
| 183 | + ret, t->gfn, pa, *(u32 *)p_data, | |
| 184 | 184 | bytes); |
| 185 | 185 | } |
| 186 | 186 | mutex_unlock(&gvt->lock); |
| @@ -267,17 +267,17 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa, · 80 unmodified lines | ||
| 267 | 267 | return ret; |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | − if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { | |
| 271 | − struct intel_vgpu_guest_page *gp; | |
| 270 | + if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) { | |
| 271 | + struct intel_vgpu_page_track *t; | |
| 272 | 272 | |
| 273 | − gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); | |
| 274 | − if (gp) { | |
| 275 | − ret = gp->handler(gp, pa, p_data, bytes); | |
| 273 | + t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT); | |
| 274 | + if (t) { | |
| 275 | + ret = t->handler(t, pa, p_data, bytes); | |
| 276 | 276 | if (ret) { |
| 277 | 277 | gvt_err("guest page write error %d, " |
| 278 | 278 | "gfn 0x%lx, pa 0x%llx, " |
| 279 | 279 | "var 0x%x, len %d\n", |
| 280 | − ret, gp->gfn, pa, | |
| 280 | + ret, t->gfn, pa, | |
| 281 | 281 | *(u32 *)p_data, bytes); |
| 282 | 282 | } |
| 283 | 283 | mutex_unlock(&gvt->lock); |
| @@ -65,11 +65,17 @@ struct intel_gvt_mmio_info { · 64 unmodified lines | ||
| 65 | 65 | struct hlist_node node; |
| 66 | 66 | }; |
| 67 | 67 | |
| 68 | +int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt, | |
| 69 | + unsigned int reg); | |
| 68 | 70 | unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt); |
| 69 | 71 | bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); |
| 70 | 72 | |
| 71 | 73 | int intel_gvt_setup_mmio_info(struct intel_gvt *gvt); |
| 72 | 74 | void intel_gvt_clean_mmio_info(struct intel_gvt *gvt); |
| 75 | +int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt, | |
| 76 | + int (*handler)(struct intel_gvt *gvt, u32 offset, void *data), | |
| 77 | + void *data); | |
| 78 | + | |
| 73 | 79 | |
| 74 | 80 | #define INTEL_GVT_MMIO_OFFSET(reg) ({ \ |
| 75 | 81 | typeof(reg) __reg = reg; \ |
| @@ -154,51 +154,53 @@ static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) · 153 unmodified lines | ||
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | /** |
| 157 | − * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected | |
| 157 | + * intel_gvt_hypervisor_enable - set a guest page to write-protected | |
| 158 | 158 | * @vgpu: a vGPU |
| 159 | − * @p: intel_vgpu_guest_page | |
| 159 | + * @t: page track data structure | |
| 160 | 160 | * |
| 161 | 161 | * Returns: |
| 162 | 162 | * Zero on success, negative error code if failed. |
| 163 | 163 | */ |
| 164 | −static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu, | |
| 165 | − struct intel_vgpu_guest_page *p) | |
| 164 | +static inline int intel_gvt_hypervisor_enable_page_track( | |
| 165 | + struct intel_vgpu *vgpu, | |
| 166 | + struct intel_vgpu_page_track *t) | |
| 166 | 167 | { |
| 167 | 168 | int ret; |
| 168 | 169 | |
| 169 | − if (p->writeprotection) | |
| 170 | + if (t->tracked) | |
| 170 | 171 | return 0; |
| 171 | 172 | |
| 172 | − ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn); | |
| 173 | + ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, t->gfn); | |
| 173 | 174 | if (ret) |
| 174 | 175 | return ret; |
| 175 | − p->writeprotection = true; | |
| 176 | − atomic_inc(&vgpu->gtt.n_write_protected_guest_page); | |
| 176 | + t->tracked = true; | |
| 177 | + atomic_inc(&vgpu->gtt.n_tracked_guest_page); | |
| 177 | 178 | return 0; |
| 178 | 179 | } |
| 179 | 180 | |
| 180 | 181 | /** |
| 181 | − * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a | |
| 182 | + * intel_gvt_hypervisor_disable_page_track - remove the write-protection of a | |
| 182 | 183 | * guest page |
| 183 | 184 | * @vgpu: a vGPU |
| 184 | − * @p: intel_vgpu_guest_page | |
| 185 | + * @t: page track data structure | |
| 185 | 186 | * |
| 186 | 187 | * Returns: |
| 187 | 188 | * Zero on success, negative error code if failed. |
| 188 | 189 | */ |
| 189 | −static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu, | |
| 190 | − struct intel_vgpu_guest_page *p) | |
| 190 | +static inline int intel_gvt_hypervisor_disable_page_track( | |
| 191 | + struct intel_vgpu *vgpu, | |
| 192 | + struct intel_vgpu_page_track *t) | |
| 191 | 193 | { |
| 192 | 194 | int ret; |
| 193 | 195 | |
| 194 | − if (!p->writeprotection) | |
| 196 | + if (!t->tracked) | |
| 195 | 197 | return 0; |
| 196 | 198 | |
| 197 | − ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn); | |
| 199 | + ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, t->gfn); | |
| 198 | 200 | if (ret) |
| 199 | 201 | return ret; |
| 200 | − p->writeprotection = false; | |
| 201 | − atomic_dec(&vgpu->gtt.n_write_protected_guest_page); | |
| 202 | + t->tracked = false; | |
| 203 | + atomic_dec(&vgpu->gtt.n_tracked_guest_page); | |
| 202 | 204 | return 0; |
| 203 | 205 | } |
| 204 | 206 | |
| @@ -25,36 +25,247 @@ · 24 unmodified lines | ||
| 25 | 25 | #include "i915_drv.h" |
| 26 | 26 | #include "gvt.h" |
| 27 | 27 | |
| 28 | −static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) | |
| 28 | +/* | |
| 29 | + * Note: Only for GVT-g virtual VBT generation, other usage must | |
| 30 | + * not do like this. | |
| 31 | + */ | |
| 32 | +#define _INTEL_BIOS_PRIVATE | |
| 33 | +#include "intel_vbt_defs.h" | |
| 34 | + | |
| 35 | +#define OPREGION_SIGNATURE "IntelGraphicsMem" | |
| 36 | +#define MBOX_VBT (1<<3) | |
| 37 | + | |
| 38 | +/* device handle */ | |
| 39 | +#define DEVICE_TYPE_CRT 0x01 | |
| 40 | +#define DEVICE_TYPE_EFP1 0x04 | |
| 41 | +#define DEVICE_TYPE_EFP2 0x40 | |
| 42 | +#define DEVICE_TYPE_EFP3 0x20 | |
| 43 | +#define DEVICE_TYPE_EFP4 0x10 | |
| 44 | + | |
| 45 | +#define DEV_SIZE 38 | |
| 46 | + | |
| 47 | +struct opregion_header { | |
| 48 | + u8 signature[16]; | |
| 49 | + u32 size; | |
| 50 | + u32 opregion_ver; | |
| 51 | + u8 bios_ver[32]; | |
| 52 | + u8 vbios_ver[16]; | |
| 53 | + u8 driver_ver[16]; | |
| 54 | + u32 mboxes; | |
| 55 | + u32 driver_model; | |
| 56 | + u32 pcon; | |
| 57 | + u8 dver[32]; | |
| 58 | + u8 rsvd[124]; | |
| 59 | +} __packed; | |
| 60 | + | |
| 61 | +struct bdb_data_header { | |
| 62 | + u8 id; | |
| 63 | + u16 size; /* data size */ | |
| 64 | +} __packed; | |
| 65 | + | |
| 66 | +struct efp_child_device_config { | |
| 67 | + u16 handle; | |
| 68 | + u16 device_type; | |
| 69 | + u16 device_class; | |
| 70 | + u8 i2c_speed; | |
| 71 | + u8 dp_onboard_redriver; /* 158 */ | |
| 72 | + u8 dp_ondock_redriver; /* 158 */ | |
| 73 | + u8 hdmi_level_shifter_value:4; /* 169 */ | |
| 74 | + u8 hdmi_max_data_rate:4; /* 204 */ | |
| 75 | + u16 dtd_buf_ptr; /* 161 */ | |
| 76 | + u8 edidless_efp:1; /* 161 */ | |
| 77 | + u8 compression_enable:1; /* 198 */ | |
| 78 | + u8 compression_method:1; /* 198 */ | |
| 79 | + u8 ganged_edp:1; /* 202 */ | |
| 80 | + u8 skip0:4; | |
| 81 | + u8 compression_structure_index:4; /* 198 */ | |
| 82 | + u8 skip1:4; | |
| 83 | + u8 slave_port; /* 202 */ | |
| 84 | + u8 skip2; | |
| 85 | + u8 dvo_port; | |
| 86 | + u8 i2c_pin; /* for add-in card */ | |
| 87 | + u8 slave_addr; /* for add-in card */ | |
| 88 | + u8 ddc_pin; | |
| 89 | + u16 edid_ptr; | |
| 90 | + u8 dvo_config; | |
| 91 | + u8 efp_docked_port:1; /* 158 */ | |
| 92 | + u8 lane_reversal:1; /* 184 */ | |
| 93 | + u8 onboard_lspcon:1; /* 192 */ | |
| 94 | + u8 iboost_enable:1; /* 196 */ | |
| 95 | + u8 hpd_invert:1; /* BXT 196 */ | |
| 96 | + u8 slip3:3; | |
| 97 | + u8 hdmi_compat:1; | |
| 98 | + u8 dp_compat:1; | |
| 99 | + u8 tmds_compat:1; | |
| 100 | + u8 skip4:5; | |
| 101 | + u8 aux_channel; | |
| 102 | + u8 dongle_detect; | |
| 103 | + u8 pipe_cap:2; | |
| 104 | + u8 sdvo_stall:1; /* 158 */ | |
| 105 | + u8 hpd_status:2; | |
| 106 | + u8 integrated_encoder:1; | |
| 107 | + u8 skip5:2; | |
| 108 | + u8 dvo_wiring; | |
| 109 | + u8 mipi_bridge_type; /* 171 */ | |
| 110 | + u16 device_class_ext; | |
| 111 | + u8 dvo_function; | |
| 112 | + u8 dp_usb_type_c:1; /* 195 */ | |
| 113 | + u8 skip6:7; | |
| 114 | + u8 dp_usb_type_c_2x_gpio_index; /* 195 */ | |
| 115 | + u16 dp_usb_type_c_2x_gpio_pin; /* 195 */ | |
| 116 | + u8 iboost_dp:4; /* 196 */ | |
| 117 | + u8 iboost_hdmi:4; /* 196 */ | |
| 118 | +} __packed; | |
| 119 | + | |
| 120 | +struct vbt { | |
| 121 | + /* header->bdb_offset point to bdb_header offset */ | |
| 122 | + struct vbt_header header; | |
| 123 | + struct bdb_header bdb_header; | |
| 124 | + | |
| 125 | + struct bdb_data_header general_features_header; | |
| 126 | + struct bdb_general_features general_features; | |
| 127 | + | |
| 128 | + struct bdb_data_header general_definitions_header; | |
| 129 | + struct bdb_general_definitions general_definitions; | |
| 130 | + | |
| 131 | + struct efp_child_device_config child0; | |
| 132 | + struct efp_child_device_config child1; | |
| 133 | + struct efp_child_device_config child2; | |
| 134 | + struct efp_child_device_config child3; | |
| 135 | + | |
| 136 | + struct bdb_data_header driver_features_header; | |
| 137 | + struct bdb_driver_features driver_features; | |
| 138 | +}; | |
| 139 | + | |
| 140 | +static void virt_vbt_generation(struct vbt *v) | |
| 29 | 141 | { |
| 30 | − u8 *buf; | |
| 31 | − int i; | |
| 142 | + int num_child; | |
| 143 | + | |
| 144 | + memset(v, 0, sizeof(struct vbt)); | |
| 145 | + | |
| 146 | + v->header.signature[0] = '$'; | |
| 147 | + v->header.signature[1] = 'V'; | |
| 148 | + v->header.signature[2] = 'B'; | |
| 149 | + v->header.signature[3] = 'T'; | |
| 150 | + | |
| 151 | + /* there's features depending on version! */ | |
| 152 | + v->header.version = 155; | |
| 153 | + v->header.header_size = sizeof(v->header); | |
| 154 | + v->header.vbt_size = sizeof(struct vbt) - sizeof(v->header); | |
| 155 | + v->header.bdb_offset = offsetof(struct vbt, bdb_header); | |
| 156 | + | |
| 157 | + strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK"); | |
| 158 | + v->bdb_header.version = 186; /* child_dev_size = 38 */ | |
| 159 | + v->bdb_header.header_size = sizeof(v->bdb_header); | |
| 160 | + | |
| 161 | + v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header) | |
| 162 | + - sizeof(struct bdb_header); | |
| 163 | + | |
| 164 | + /* general features */ | |
| 165 | + v->general_features_header.id = BDB_GENERAL_FEATURES; | |
| 166 | + v->general_features_header.size = sizeof(struct bdb_general_features); | |
| 167 | + v->general_features.int_crt_support = 0; | |
| 168 | + v->general_features.int_tv_support = 0; | |
| 169 | + | |
| 170 | + /* child device */ | |
| 171 | + num_child = 4; /* each port has one child */ | |
| 172 | + v->general_definitions_header.id = BDB_GENERAL_DEFINITIONS; | |
| 173 | + /* size will include child devices */ | |
| 174 | + v->general_definitions_header.size = | |
| 175 | + sizeof(struct bdb_general_definitions) + num_child * DEV_SIZE; | |
| 176 | + v->general_definitions.child_dev_size = DEV_SIZE; | |
| 177 | + | |
| 178 | + /* portA */ | |
| 179 | + v->child0.handle = DEVICE_TYPE_EFP1; | |
| 180 | + v->child0.device_type = DEVICE_TYPE_DP; | |
| 181 | + v->child0.dvo_port = DVO_PORT_DPA; | |
| 182 | + v->child0.aux_channel = DP_AUX_A; | |
| 183 | + v->child0.dp_compat = true; | |
| 184 | + v->child0.integrated_encoder = true; | |
| 185 | + | |
| 186 | + /* portB */ | |
| 187 | + v->child1.handle = DEVICE_TYPE_EFP2; | |
| 188 | + v->child1.device_type = DEVICE_TYPE_DP; | |
| 189 | + v->child1.dvo_port = DVO_PORT_DPB; | |
| 190 | + v->child1.aux_channel = DP_AUX_B; | |
| 191 | + v->child1.dp_compat = true; | |
| 192 | + v->child1.integrated_encoder = true; | |
| 193 | + | |
| 194 | + /* portC */ | |
| 195 | + v->child2.handle = DEVICE_TYPE_EFP3; | |
| 196 | + v->child2.device_type = DEVICE_TYPE_DP; | |
| 197 | + v->child2.dvo_port = DVO_PORT_DPC; | |
| 198 | + v->child2.aux_channel = DP_AUX_C; | |
| 199 | + v->child2.dp_compat = true; | |
| 200 | + v->child2.integrated_encoder = true; | |
| 201 | + | |
| 202 | + /* portD */ | |
| 203 | + v->child3.handle = DEVICE_TYPE_EFP4; | |
| 204 | + v->child3.device_type = DEVICE_TYPE_DP; | |
| 205 | + v->child3.dvo_port = DVO_PORT_DPD; | |
| 206 | + v->child3.aux_channel = DP_AUX_D; | |
| 207 | + v->child3.dp_compat = true; | |
| 208 | + v->child3.integrated_encoder = true; | |
| 209 | + | |
| 210 | + /* driver features */ | |
| 211 | + v->driver_features_header.id = BDB_DRIVER_FEATURES; | |
| 212 | + v->driver_features_header.size = sizeof(struct bdb_driver_features); | |
| 213 | + v->driver_features.lvds_config = BDB_DRIVER_FEATURE_NO_LVDS; | |
| 214 | +} | |
| 32 | 215 | |
| 33 | − if (WARN((vgpu_opregion(vgpu)->va), | |
| 34 | − "vgpu%d: opregion has been initialized already.\n", | |
| 35 | − vgpu->id)) | |
| 36 | − return -EINVAL; | |
| 216 | +static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu) | |
| 217 | +{ | |
| 218 | + u8 *buf; | |
| 219 | + struct opregion_header *header; | |
| 220 | + struct vbt v; | |
| 37 | 221 | |
| 222 | + gvt_dbg_core("init vgpu%d opregion\n", vgpu->id); | |
| 38 | 223 | vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL | |
| 39 | 224 | __GFP_ZERO, |
| 40 | 225 | get_order(INTEL_GVT_OPREGION_SIZE)); |
| 41 | − | |
| 42 | − if (!vgpu_opregion(vgpu)->va) | |
| 226 | + if (!vgpu_opregion(vgpu)->va) { | |
| 227 | + gvt_err("fail to get memory for vgpu virt opregion\n"); | |
| 43 | 228 | return -ENOMEM; |
| 229 | + } | |
| 44 | 230 | |
| 45 | − memcpy(vgpu_opregion(vgpu)->va, vgpu->gvt->opregion.opregion_va, | |
| 46 | − INTEL_GVT_OPREGION_SIZE); | |
| 47 | − | |
| 48 | − for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) | |
| 49 | − vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; | |
| 231 | + /* emulated opregion with VBT mailbox only */ | |
| 232 | + buf = (u8 *)vgpu_opregion(vgpu)->va; | |
| 233 | + header = (struct opregion_header *)buf; | |
| 234 | + memcpy(header->signature, OPREGION_SIGNATURE, | |
| 235 | + sizeof(OPREGION_SIGNATURE)); | |
| 236 | + header->size = 0x8; | |
| 237 | + header->opregion_ver = 0x02000000; | |
| 238 | + header->mboxes = MBOX_VBT; | |
| 50 | 239 | |
| 51 | 240 | /* for unknown reason, the value in LID field is incorrect |
| 52 | 241 | * which block the windows guest, so workaround it by force |
| 53 | 242 | * setting it to "OPEN" |
| 54 | 243 | */ |
| 55 | − buf = (u8 *)vgpu_opregion(vgpu)->va; | |
| 56 | 244 | buf[INTEL_GVT_OPREGION_CLID] = 0x3; |
| 57 | 245 | |
| 246 | + /* emulated vbt from virt vbt generation */ | |
| 247 | + virt_vbt_generation(&v); | |
| 248 | + memcpy(buf + INTEL_GVT_OPREGION_VBT_OFFSET, &v, sizeof(struct vbt)); | |
| 249 | + | |
| 250 | + return 0; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) | |
| 254 | +{ | |
| 255 | + int i, ret; | |
| 256 | + | |
| 257 | + if (WARN((vgpu_opregion(vgpu)->va), | |
| 258 | + "vgpu%d: opregion has been initialized already.\n", | |
| 259 | + vgpu->id)) | |
| 260 | + return -EINVAL; | |
| 261 | + | |
| 262 | + ret = alloc_and_init_virt_opregion(vgpu); | |
| 263 | + if (ret < 0) | |
| 264 | + return ret; | |
| 265 | + | |
| 266 | + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) | |
| 267 | + vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; | |
| 268 | + | |
| 58 | 269 | return 0; |
| 59 | 270 | } |
| 60 | 271 | |
| @@ -132,40 +343,6 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa) · 71 unmodified lines | ||
| 132 | 343 | return 0; |
| 133 | 344 | } |
| 134 | 345 | |
| 135 | −/** | |
| 136 | − * intel_gvt_clean_opregion - clean host opergion related stuffs | |
| 137 | − * @gvt: a GVT device | |
| 138 | − * | |
| 139 | − */ | |
| 140 | −void intel_gvt_clean_opregion(struct intel_gvt *gvt) | |
| 141 | −{ | |
| 142 | − memunmap(gvt->opregion.opregion_va); | |
| 143 | − gvt->opregion.opregion_va = NULL; | |
| 144 | −} | |
| 145 | − | |
| 146 | −/** | |
| 147 | − * intel_gvt_init_opregion - initialize host opergion related stuffs | |
| 148 | − * @gvt: a GVT device | |
| 149 | − * | |
| 150 | − * Returns: | |
| 151 | − * Zero on success, negative error code if failed. | |
| 152 | − */ | |
| 153 | −int intel_gvt_init_opregion(struct intel_gvt *gvt) | |
| 154 | −{ | |
| 155 | − gvt_dbg_core("init host opregion\n"); | |
| 156 | − | |
| 157 | − pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION, | |
| 158 | − &gvt->opregion.opregion_pa); | |
| 159 | − | |
| 160 | − gvt->opregion.opregion_va = memremap(gvt->opregion.opregion_pa, | |
| 161 | − INTEL_GVT_OPREGION_SIZE, MEMREMAP_WB); | |
| 162 | − if (!gvt->opregion.opregion_va) { | |
| 163 | − gvt_err("fail to map host opregion\n"); | |
| 164 | − return -EFAULT; | |
| 165 | − } | |
| 166 | − return 0; | |
| 167 | −} | |
| 168 | − | |
| 169 | 346 | #define GVT_OPREGION_FUNC(scic) \ |
| 170 | 347 | ({ \ |
| 171 | 348 | u32 __ret; \ |
| @@ -51,6 +51,9 @@ · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | #define INTEL_GVT_OPREGION_PAGES 2 |
| 53 | 53 | #define INTEL_GVT_OPREGION_SIZE (INTEL_GVT_OPREGION_PAGES * PAGE_SIZE) |
| 54 | +#define INTEL_GVT_OPREGION_VBT_OFFSET 0x400 | |
| 55 | +#define INTEL_GVT_OPREGION_VBT_SIZE \ | |
| 56 | + (INTEL_GVT_OPREGION_SIZE - INTEL_GVT_OPREGION_VBT_OFFSET) | |
| 54 | 57 | |
| 55 | 58 | #define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B) |
| 56 | 59 | |
| @@ -71,6 +74,7 @@ · 14 unmodified lines | ||
| 71 | 74 | #define RB_HEAD_OFF_MASK ((1U << 21) - (1U << 2)) |
| 72 | 75 | #define RB_TAIL_OFF_MASK ((1U << 21) - (1U << 3)) |
| 73 | 76 | #define RB_TAIL_SIZE_MASK ((1U << 21) - (1U << 12)) |
| 74 | −#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE) | |
| 77 | +#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + \ | |
| 78 | + I915_GTT_PAGE_SIZE) | |
| 75 | 79 | |
| 76 | 80 | #endif |
| @@ -147,6 +147,7 @@ static u32 gen9_render_mocs_L3[32]; · 146 unmodified lines | ||
| 147 | 147 | static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) |
| 148 | 148 | { |
| 149 | 149 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; |
| 150 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 150 | 151 | enum forcewake_domains fw; |
| 151 | 152 | i915_reg_t reg; |
| 152 | 153 | u32 regs[] = { |
| @@ -160,7 +161,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) · 7 unmodified lines | ||
| 160 | 161 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) |
| 161 | 162 | return; |
| 162 | 163 | |
| 163 | − if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending)) | |
| 164 | + if (!test_and_clear_bit(ring_id, (void *)s->tlb_handle_pending)) | |
| 164 | 165 | return; |
| 165 | 166 | |
| 166 | 167 | reg = _MMIO(regs[ring_id]); |
| @@ -208,7 +209,7 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id) · 41 unmodified lines | ||
| 208 | 209 | offset.reg = regs[ring_id]; |
| 209 | 210 | for (i = 0; i < 64; i++) { |
| 210 | 211 | gen9_render_mocs[ring_id][i] = I915_READ_FW(offset); |
| 211 | − I915_WRITE(offset, vgpu_vreg(vgpu, offset)); | |
| 212 | + I915_WRITE_FW(offset, vgpu_vreg(vgpu, offset)); | |
| 212 | 213 | offset.reg += 4; |
| 213 | 214 | } |
| 214 | 215 | |
| @@ -261,14 +262,15 @@ static void restore_mocs(struct intel_vgpu *vgpu, int ring_id) · 46 unmodified lines | ||
| 261 | 262 | static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id) |
| 262 | 263 | { |
| 263 | 264 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; |
| 264 | − struct render_mmio *mmio; | |
| 265 | − u32 v; | |
| 266 | − int i, array_size; | |
| 267 | − u32 *reg_state = vgpu->shadow_ctx->engine[ring_id].lrc_reg_state; | |
| 265 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 266 | + u32 *reg_state = s->shadow_ctx->engine[ring_id].lrc_reg_state; | |
| 268 | 267 | u32 ctx_ctrl = reg_state[CTX_CONTEXT_CONTROL_VAL]; |
| 269 | 268 | u32 inhibit_mask = |
| 270 | 269 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); |
| 271 | 270 | i915_reg_t last_reg = _MMIO(0); |
| 271 | + struct render_mmio *mmio; | |
| 272 | + u32 v; | |
| 273 | + int i, array_size; | |
| 272 | 274 | |
| 273 | 275 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) |
| 274 | 276 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) { |
| @@ -57,7 +57,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) · 56 unmodified lines | ||
| 57 | 57 | struct intel_vgpu *vgpu = workload->vgpu; |
| 58 | 58 | struct intel_gvt *gvt = vgpu->gvt; |
| 59 | 59 | int ring_id = workload->ring_id; |
| 60 | − struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | |
| 60 | + struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; | |
| 61 | 61 | struct drm_i915_gem_object *ctx_obj = |
| 62 | 62 | shadow_ctx->engine[ring_id].state->obj; |
| 63 | 63 | struct execlist_ring_context *shadow_ring_context; |
| @@ -81,16 +81,16 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) · 17 unmodified lines | ||
| 81 | 81 | while (i < context_page_num) { |
| 82 | 82 | context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, |
| 83 | 83 | (u32)((workload->ctx_desc.lrca + i) << |
| 84 | − GTT_PAGE_SHIFT)); | |
| 84 | + I915_GTT_PAGE_SHIFT)); | |
| 85 | 85 | if (context_gpa == INTEL_GVT_INVALID_ADDR) { |
| 86 | 86 | gvt_vgpu_err("Invalid guest context descriptor\n"); |
| 87 | − return -EINVAL; | |
| 87 | + return -EFAULT; | |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); |
| 91 | 91 | dst = kmap(page); |
| 92 | 92 | intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst, |
| 93 | − GTT_PAGE_SIZE); | |
| 93 | + I915_GTT_PAGE_SIZE); | |
| 94 | 94 | kunmap(page); |
| 95 | 95 | i++; |
| 96 | 96 | } |
| @@ -120,7 +120,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) · 23 unmodified lines | ||
| 120 | 120 | sizeof(*shadow_ring_context), |
| 121 | 121 | (void *)shadow_ring_context + |
| 122 | 122 | sizeof(*shadow_ring_context), |
| 123 | − GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | |
| 123 | + I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | |
| 124 | 124 | |
| 125 | 125 | kunmap(page); |
| 126 | 126 | return 0; |
| @@ -131,6 +131,20 @@ static inline bool is_gvt_request(struct drm_i915_gem_request *req) · 4 unmodified lines | ||
| 131 | 131 | return i915_gem_context_force_single_submission(req->ctx); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | +static void save_ring_hw_state(struct intel_vgpu *vgpu, int ring_id) | |
| 135 | +{ | |
| 136 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 137 | + u32 ring_base = dev_priv->engine[ring_id]->mmio_base; | |
| 138 | + i915_reg_t reg; | |
| 139 | + | |
| 140 | + reg = RING_INSTDONE(ring_base); | |
| 141 | + vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | |
| 142 | + reg = RING_ACTHD(ring_base); | |
| 143 | + vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | |
| 144 | + reg = RING_ACTHD_UDW(ring_base); | |
| 145 | + vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | |
| 146 | +} | |
| 147 | + | |
| 134 | 148 | static int shadow_context_status_change(struct notifier_block *nb, |
| 135 | 149 | unsigned long action, void *data) |
| 136 | 150 | { |
| @@ -176,6 +190,7 @@ static int shadow_context_status_change(struct notifier_block *nb, · 39 unmodified lines | ||
| 176 | 190 | break; |
| 177 | 191 | case INTEL_CONTEXT_SCHEDULE_OUT: |
| 178 | 192 | case INTEL_CONTEXT_SCHEDULE_PREEMPTED: |
| 193 | + save_ring_hw_state(workload->vgpu, ring_id); | |
| 179 | 194 | atomic_set(&workload->shadow_ctx_active, 0); |
| 180 | 195 | break; |
| 181 | 196 | default: |
| @@ -250,11 +265,12 @@ void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) · 68 unmodified lines | ||
| 250 | 265 | */ |
| 251 | 266 | int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) |
| 252 | 267 | { |
| 268 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 269 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 270 | + struct i915_gem_context *shadow_ctx = s->shadow_ctx; | |
| 271 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 253 | 272 | int ring_id = workload->ring_id; |
| 254 | − struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | |
| 255 | − struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; | |
| 256 | 273 | struct intel_engine_cs *engine = dev_priv->engine[ring_id]; |
| 257 | − struct intel_vgpu *vgpu = workload->vgpu; | |
| 258 | 274 | struct intel_ring *ring; |
| 259 | 275 | int ret; |
| 260 | 276 | |
| @@ -267,7 +283,7 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) · 6 unmodified lines | ||
| 267 | 283 | shadow_ctx->desc_template |= workload->ctx_desc.addressing_mode << |
| 268 | 284 | GEN8_CTX_ADDRESSING_MODE_SHIFT; |
| 269 | 285 | |
| 270 | − if (!test_and_set_bit(ring_id, vgpu->shadow_ctx_desc_updated)) | |
| 286 | + if (!test_and_set_bit(ring_id, s->shadow_ctx_desc_updated)) | |
| 271 | 287 | shadow_context_descriptor_update(shadow_ctx, |
| 272 | 288 | dev_priv->engine[ring_id]); |
| 273 | 289 | |
| @@ -310,14 +326,15 @@ err_scan: · 36 unmodified lines | ||
| 310 | 326 | return ret; |
| 311 | 327 | } |
| 312 | 328 | |
| 313 | −int intel_gvt_generate_request(struct intel_vgpu_workload *workload) | |
| 329 | +static int intel_gvt_generate_request(struct intel_vgpu_workload *workload) | |
| 314 | 330 | { |
| 315 | 331 | int ring_id = workload->ring_id; |
| 316 | 332 | struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; |
| 317 | 333 | struct intel_engine_cs *engine = dev_priv->engine[ring_id]; |
| 318 | 334 | struct drm_i915_gem_request *rq; |
| 319 | 335 | struct intel_vgpu *vgpu = workload->vgpu; |
| 320 | − struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx; | |
| 336 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 337 | + struct i915_gem_context *shadow_ctx = s->shadow_ctx; | |
| 321 | 338 | int ret; |
| 322 | 339 | |
| 323 | 340 | rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); |
| @@ -341,11 +358,203 @@ err_unpin: · 17 unmodified lines | ||
| 341 | 358 | return ret; |
| 342 | 359 | } |
| 343 | 360 | |
| 361 | +static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload); | |
| 362 | + | |
| 363 | +static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |
| 364 | +{ | |
| 365 | + struct intel_gvt *gvt = workload->vgpu->gvt; | |
| 366 | + const int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd; | |
| 367 | + struct intel_vgpu_shadow_bb *bb; | |
| 368 | + int ret; | |
| 369 | + | |
| 370 | + list_for_each_entry(bb, &workload->shadow_bb, list) { | |
| 371 | + bb->vma = i915_gem_object_ggtt_pin(bb->obj, NULL, 0, 0, 0); | |
| 372 | + if (IS_ERR(bb->vma)) { | |
| 373 | + ret = PTR_ERR(bb->vma); | |
| 374 | + goto err; | |
| 375 | + } | |
| 376 | + | |
| 377 | + /* relocate shadow batch buffer */ | |
| 378 | + bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); | |
| 379 | + if (gmadr_bytes == 8) | |
| 380 | + bb->bb_start_cmd_va[2] = 0; | |
| 381 | + | |
| 382 | + /* No one is going to touch shadow bb from now on. */ | |
| 383 | + if (bb->clflush & CLFLUSH_AFTER) { | |
| 384 | + drm_clflush_virt_range(bb->va, bb->obj->base.size); | |
| 385 | + bb->clflush &= ~CLFLUSH_AFTER; | |
| 386 | + } | |
| 387 | + | |
| 388 | + ret = i915_gem_object_set_to_gtt_domain(bb->obj, false); | |
| 389 | + if (ret) | |
| 390 | + goto err; | |
| 391 | + | |
| 392 | + i915_gem_obj_finish_shmem_access(bb->obj); | |
| 393 | + bb->accessing = false; | |
| 394 | + | |
| 395 | + i915_vma_move_to_active(bb->vma, workload->req, 0); | |
| 396 | + } | |
| 397 | + return 0; | |
| 398 | +err: | |
| 399 | + release_shadow_batch_buffer(workload); | |
| 400 | + return ret; | |
| 401 | +} | |
| 402 | + | |
| 403 | +static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |
| 404 | +{ | |
| 405 | + struct intel_vgpu_workload *workload = container_of(wa_ctx, | |
| 406 | + struct intel_vgpu_workload, | |
| 407 | + wa_ctx); | |
| 408 | + int ring_id = workload->ring_id; | |
| 409 | + struct intel_vgpu_submission *s = &workload->vgpu->submission; | |
| 410 | + struct i915_gem_context *shadow_ctx = s->shadow_ctx; | |
| 411 | + struct drm_i915_gem_object *ctx_obj = | |
| 412 | + shadow_ctx->engine[ring_id].state->obj; | |
| 413 | + struct execlist_ring_context *shadow_ring_context; | |
| 414 | + struct page *page; | |
| 415 | + | |
| 416 | + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | |
| 417 | + shadow_ring_context = kmap_atomic(page); | |
| 418 | + | |
| 419 | + shadow_ring_context->bb_per_ctx_ptr.val = | |
| 420 | + (shadow_ring_context->bb_per_ctx_ptr.val & | |
| 421 | + (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma; | |
| 422 | + shadow_ring_context->rcs_indirect_ctx.val = | |
| 423 | + (shadow_ring_context->rcs_indirect_ctx.val & | |
| 424 | + (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; | |
| 425 | + | |
| 426 | + kunmap_atomic(shadow_ring_context); | |
| 427 | + return 0; | |
| 428 | +} | |
| 429 | + | |
| 430 | +static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |
| 431 | +{ | |
| 432 | + struct i915_vma *vma; | |
| 433 | + unsigned char *per_ctx_va = | |
| 434 | + (unsigned char *)wa_ctx->indirect_ctx.shadow_va + | |
| 435 | + wa_ctx->indirect_ctx.size; | |
| 436 | + | |
| 437 | + if (wa_ctx->indirect_ctx.size == 0) | |
| 438 | + return 0; | |
| 439 | + | |
| 440 | + vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, | |
| 441 | + 0, CACHELINE_BYTES, 0); | |
| 442 | + if (IS_ERR(vma)) | |
| 443 | + return PTR_ERR(vma); | |
| 444 | + | |
| 445 | + /* FIXME: we are not tracking our pinned VMA leaving it | |
| 446 | + * up to the core to fix up the stray pin_count upon | |
| 447 | + * free. | |
| 448 | + */ | |
| 449 | + | |
| 450 | + wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma); | |
| 451 | + | |
| 452 | + wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1); | |
| 453 | + memset(per_ctx_va, 0, CACHELINE_BYTES); | |
| 454 | + | |
| 455 | + update_wa_ctx_2_shadow_ctx(wa_ctx); | |
| 456 | + return 0; | |
| 457 | +} | |
| 458 | + | |
| 459 | +static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |
| 460 | +{ | |
| 461 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 462 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 463 | + struct intel_vgpu_shadow_bb *bb, *pos; | |
| 464 | + | |
| 465 | + if (list_empty(&workload->shadow_bb)) | |
| 466 | + return; | |
| 467 | + | |
| 468 | + bb = list_first_entry(&workload->shadow_bb, | |
| 469 | + struct intel_vgpu_shadow_bb, list); | |
| 470 | + | |
| 471 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 472 | + | |
| 473 | + list_for_each_entry_safe(bb, pos, &workload->shadow_bb, list) { | |
| 474 | + if (bb->obj) { | |
| 475 | + if (bb->accessing) | |
| 476 | + i915_gem_obj_finish_shmem_access(bb->obj); | |
| 477 | + | |
| 478 | + if (bb->va && !IS_ERR(bb->va)) | |
| 479 | + i915_gem_object_unpin_map(bb->obj); | |
| 480 | + | |
| 481 | + if (bb->vma && !IS_ERR(bb->vma)) { | |
| 482 | + i915_vma_unpin(bb->vma); | |
| 483 | + i915_vma_close(bb->vma); | |
| 484 | + } | |
| 485 | + __i915_gem_object_release_unless_active(bb->obj); | |
| 486 | + } | |
| 487 | + list_del(&bb->list); | |
| 488 | + kfree(bb); | |
| 489 | + } | |
| 490 | + | |
| 491 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 492 | +} | |
| 493 | + | |
| 494 | +static int prepare_workload(struct intel_vgpu_workload *workload) | |
| 495 | +{ | |
| 496 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 497 | + int ret = 0; | |
| 498 | + | |
| 499 | + ret = intel_vgpu_pin_mm(workload->shadow_mm); | |
| 500 | + if (ret) { | |
| 501 | + gvt_vgpu_err("fail to vgpu pin mm\n"); | |
| 502 | + return ret; | |
| 503 | + } | |
| 504 | + | |
| 505 | + ret = intel_vgpu_sync_oos_pages(workload->vgpu); | |
| 506 | + if (ret) { | |
| 507 | + gvt_vgpu_err("fail to vgpu sync oos pages\n"); | |
| 508 | + goto err_unpin_mm; | |
| 509 | + } | |
| 510 | + | |
| 511 | + ret = intel_vgpu_flush_post_shadow(workload->vgpu); | |
| 512 | + if (ret) { | |
| 513 | + gvt_vgpu_err("fail to flush post shadow\n"); | |
| 514 | + goto err_unpin_mm; | |
| 515 | + } | |
| 516 | + | |
| 517 | + ret = intel_gvt_generate_request(workload); | |
| 518 | + if (ret) { | |
| 519 | + gvt_vgpu_err("fail to generate request\n"); | |
| 520 | + goto err_unpin_mm; | |
| 521 | + } | |
| 522 | + | |
| 523 | + ret = prepare_shadow_batch_buffer(workload); | |
| 524 | + if (ret) { | |
| 525 | + gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n"); | |
| 526 | + goto err_unpin_mm; | |
| 527 | + } | |
| 528 | + | |
| 529 | + ret = prepare_shadow_wa_ctx(&workload->wa_ctx); | |
| 530 | + if (ret) { | |
| 531 | + gvt_vgpu_err("fail to prepare_shadow_wa_ctx\n"); | |
| 532 | + goto err_shadow_batch; | |
| 533 | + } | |
| 534 | + | |
| 535 | + if (workload->prepare) { | |
| 536 | + ret = workload->prepare(workload); | |
| 537 | + if (ret) | |
| 538 | + goto err_shadow_wa_ctx; | |
| 539 | + } | |
| 540 | + | |
| 541 | + return 0; | |
| 542 | +err_shadow_wa_ctx: | |
| 543 | + release_shadow_wa_ctx(&workload->wa_ctx); | |
| 544 | +err_shadow_batch: | |
| 545 | + release_shadow_batch_buffer(workload); | |
| 546 | +err_unpin_mm: | |
| 547 | + intel_vgpu_unpin_mm(workload->shadow_mm); | |
| 548 | + return ret; | |
| 549 | +} | |
| 550 | + | |
| 344 | 551 | static int dispatch_workload(struct intel_vgpu_workload *workload) |
| 345 | 552 | { |
| 553 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 554 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 555 | + struct i915_gem_context *shadow_ctx = s->shadow_ctx; | |
| 556 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 346 | 557 | int ring_id = workload->ring_id; |
| 347 | − struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | |
| 348 | − struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; | |
| 349 | 558 | struct intel_engine_cs *engine = dev_priv->engine[ring_id]; |
| 350 | 559 | int ret = 0; |
| 351 | 560 | |
| @@ -358,12 +567,10 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) · 6 unmodified lines | ||
| 358 | 567 | if (ret) |
| 359 | 568 | goto out; |
| 360 | 569 | |
| 361 | − if (workload->prepare) { | |
| 362 | − ret = workload->prepare(workload); | |
| 363 | − if (ret) { | |
| 364 | − engine->context_unpin(engine, shadow_ctx); | |
| 365 | − goto out; | |
| 366 | − } | |
| 570 | + ret = prepare_workload(workload); | |
| 571 | + if (ret) { | |
| 572 | + engine->context_unpin(engine, shadow_ctx); | |
| 573 | + goto out; | |
| 367 | 574 | } |
| 368 | 575 | |
| 369 | 576 | out: |
| @@ -431,7 +638,7 @@ static struct intel_vgpu_workload *pick_next_workload( · 61 unmodified lines | ||
| 431 | 638 | |
| 432 | 639 | gvt_dbg_sched("ring id %d pick new workload %p\n", ring_id, workload); |
| 433 | 640 | |
| 434 | − atomic_inc(&workload->vgpu->running_workload_num); | |
| 641 | + atomic_inc(&workload->vgpu->submission.running_workload_num); | |
| 435 | 642 | out: |
| 436 | 643 | mutex_unlock(&gvt->lock); |
| 437 | 644 | return workload; |
| @@ -441,8 +648,9 @@ static void update_guest_context(struct intel_vgpu_workload *workload) · 3 unmodified lines | ||
| 441 | 648 | { |
| 442 | 649 | struct intel_vgpu *vgpu = workload->vgpu; |
| 443 | 650 | struct intel_gvt *gvt = vgpu->gvt; |
| 651 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 652 | + struct i915_gem_context *shadow_ctx = s->shadow_ctx; | |
| 444 | 653 | int ring_id = workload->ring_id; |
| 445 | − struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | |
| 446 | 654 | struct drm_i915_gem_object *ctx_obj = |
| 447 | 655 | shadow_ctx->engine[ring_id].state->obj; |
| 448 | 656 | struct execlist_ring_context *shadow_ring_context; |
| @@ -466,7 +674,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) · 17 unmodified lines | ||
| 466 | 674 | while (i < context_page_num) { |
| 467 | 675 | context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, |
| 468 | 676 | (u32)((workload->ctx_desc.lrca + i) << |
| 469 | − GTT_PAGE_SHIFT)); | |
| 677 | + I915_GTT_PAGE_SHIFT)); | |
| 470 | 678 | if (context_gpa == INTEL_GVT_INVALID_ADDR) { |
| 471 | 679 | gvt_vgpu_err("invalid guest context descriptor\n"); |
| 472 | 680 | return; |
| @@ -475,7 +683,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) · 2 unmodified lines | ||
| 475 | 683 | page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); |
| 476 | 684 | src = kmap(page); |
| 477 | 685 | intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src, |
| 478 | − GTT_PAGE_SIZE); | |
| 686 | + I915_GTT_PAGE_SIZE); | |
| 479 | 687 | kunmap(page); |
| 480 | 688 | i++; |
| 481 | 689 | } |
| @@ -500,23 +708,41 @@ static void update_guest_context(struct intel_vgpu_workload *workload) · 18 unmodified lines | ||
| 500 | 708 | sizeof(*shadow_ring_context), |
| 501 | 709 | (void *)shadow_ring_context + |
| 502 | 710 | sizeof(*shadow_ring_context), |
| 503 | − GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | |
| 711 | + I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | |
| 504 | 712 | |
| 505 | 713 | kunmap(page); |
| 506 | 714 | } |
| 507 | 715 | |
| 716 | +static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) | |
| 717 | +{ | |
| 718 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 719 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 720 | + struct intel_engine_cs *engine; | |
| 721 | + struct intel_vgpu_workload *pos, *n; | |
| 722 | + unsigned int tmp; | |
| 723 | + | |
| 724 | + /* free the unsubmited workloads in the queues. */ | |
| 725 | + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { | |
| 726 | + list_for_each_entry_safe(pos, n, | |
| 727 | + &s->workload_q_head[engine->id], list) { | |
| 728 | + list_del_init(&pos->list); | |
| 729 | + intel_vgpu_destroy_workload(pos); | |
| 730 | + } | |
| 731 | + clear_bit(engine->id, s->shadow_ctx_desc_updated); | |
| 732 | + } | |
| 733 | +} | |
| 734 | + | |
| 508 | 735 | static void complete_current_workload(struct intel_gvt *gvt, int ring_id) |
| 509 | 736 | { |
| 510 | 737 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; |
| 511 | − struct intel_vgpu_workload *workload; | |
| 512 | − struct intel_vgpu *vgpu; | |
| 738 | + struct intel_vgpu_workload *workload = | |
| 739 | + scheduler->current_workload[ring_id]; | |
| 740 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 741 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 513 | 742 | int event; |
| 514 | 743 | |
| 515 | 744 | mutex_lock(&gvt->lock); |
| 516 | 745 | |
| 517 | − workload = scheduler->current_workload[ring_id]; | |
| 518 | − vgpu = workload->vgpu; | |
| 519 | − | |
| 520 | 746 | /* For the workload w/ request, needs to wait for the context |
| 521 | 747 | * switch to make sure request is completed. |
| 522 | 748 | * For the workload w/o request, directly complete the workload. |
| @@ -553,7 +779,7 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) · 30 unmodified lines | ||
| 553 | 779 | } |
| 554 | 780 | mutex_lock(&dev_priv->drm.struct_mutex); |
| 555 | 781 | /* unpin shadow ctx as the shadow_ctx update is done */ |
| 556 | − engine->context_unpin(engine, workload->vgpu->shadow_ctx); | |
| 782 | + engine->context_unpin(engine, s->shadow_ctx); | |
| 557 | 783 | mutex_unlock(&dev_priv->drm.struct_mutex); |
| 558 | 784 | } |
| 559 | 785 | |
| @@ -563,9 +789,32 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) · 3 unmodified lines | ||
| 563 | 789 | scheduler->current_workload[ring_id] = NULL; |
| 564 | 790 | |
| 565 | 791 | list_del_init(&workload->list); |
| 792 | + | |
| 793 | + if (!workload->status) { | |
| 794 | + release_shadow_batch_buffer(workload); | |
| 795 | + release_shadow_wa_ctx(&workload->wa_ctx); | |
| 796 | + } | |
| 797 | + | |
| 798 | + if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) { | |
| 799 | + /* if workload->status is not successful means HW GPU | |
| 800 | + * has occurred GPU hang or something wrong with i915/GVT, | |
| 801 | + * and GVT won't inject context switch interrupt to guest. | |
| 802 | + * So this error is a vGPU hang actually to the guest. | |
| 803 | + * According to this we should emunlate a vGPU hang. If | |
| 804 | + * there are pending workloads which are already submitted | |
| 805 | + * from guest, we should clean them up like HW GPU does. | |
| 806 | + * | |
| 807 | + * if it is in middle of engine resetting, the pending | |
| 808 | + * workloads won't be submitted to HW GPU and will be | |
| 809 | + * cleaned up during the resetting process later, so doing | |
| 810 | + * the workload clean up here doesn't have any impact. | |
| 811 | + **/ | |
| 812 | + clean_workloads(vgpu, ENGINE_MASK(ring_id)); | |
| 813 | + } | |
| 814 | + | |
| 566 | 815 | workload->complete(workload); |
| 567 | 816 | |
| 568 | − atomic_dec(&vgpu->running_workload_num); | |
| 817 | + atomic_dec(&s->running_workload_num); | |
| 569 | 818 | wake_up(&scheduler->workload_complete_wq); |
| 570 | 819 | |
| 571 | 820 | if (gvt->scheduler.need_reschedule) |
| @@ -648,20 +897,23 @@ complete: · 76 unmodified lines | ||
| 648 | 897 | FORCEWAKE_ALL); |
| 649 | 898 | |
| 650 | 899 | intel_runtime_pm_put(gvt->dev_priv); |
| 900 | + if (ret && (vgpu_is_vm_unhealthy(ret))) | |
| 901 | + enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR); | |
| 651 | 902 | } |
| 652 | 903 | return 0; |
| 653 | 904 | } |
| 654 | 905 | |
| 655 | 906 | void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) |
| 656 | 907 | { |
| 908 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 657 | 909 | struct intel_gvt *gvt = vgpu->gvt; |
| 658 | 910 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; |
| 659 | 911 | |
| 660 | − if (atomic_read(&vgpu->running_workload_num)) { | |
| 912 | + if (atomic_read(&s->running_workload_num)) { | |
| 661 | 913 | gvt_dbg_sched("wait vgpu idle\n"); |
| 662 | 914 | |
| 663 | 915 | wait_event(scheduler->workload_complete_wq, |
| 664 | − !atomic_read(&vgpu->running_workload_num)); | |
| 916 | + !atomic_read(&s->running_workload_num)); | |
| 665 | 917 | } |
| 666 | 918 | } |
| 667 | 919 | |
| @@ -726,23 +978,354 @@ err: · 58 unmodified lines | ||
| 726 | 978 | return ret; |
| 727 | 979 | } |
| 728 | 980 | |
| 729 | −void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu) | |
| 981 | +/** | |
| 982 | + * intel_vgpu_clean_submission - free submission-related resource for vGPU | |
| 983 | + * @vgpu: a vGPU | |
| 984 | + * | |
| 985 | + * This function is called when a vGPU is being destroyed. | |
| 986 | + * | |
| 987 | + */ | |
| 988 | +void intel_vgpu_clean_submission(struct intel_vgpu *vgpu) | |
| 989 | +{ | |
| 990 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 991 | + | |
| 992 | + intel_vgpu_select_submission_ops(vgpu, 0); | |
| 993 | + i915_gem_context_put(s->shadow_ctx); | |
| 994 | + kmem_cache_destroy(s->workloads); | |
| 995 | +} | |
| 996 | + | |
| 997 | + | |
| 998 | +/** | |
| 999 | + * intel_vgpu_reset_submission - reset submission-related resource for vGPU | |
| 1000 | + * @vgpu: a vGPU | |
| 1001 | + * @engine_mask: engines expected to be reset | |
| 1002 | + * | |
| 1003 | + * This function is called when a vGPU is being destroyed. | |
| 1004 | + * | |
| 1005 | + */ | |
| 1006 | +void intel_vgpu_reset_submission(struct intel_vgpu *vgpu, | |
| 1007 | + unsigned long engine_mask) | |
| 730 | 1008 | { |
| 731 | − i915_gem_context_put(vgpu->shadow_ctx); | |
| 1009 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1010 | + | |
| 1011 | + if (!s->active) | |
| 1012 | + return; | |
| 1013 | + | |
| 1014 | + clean_workloads(vgpu, engine_mask); | |
| 1015 | + s->ops->reset(vgpu, engine_mask); | |
| 732 | 1016 | } |
| 733 | 1017 | |
| 734 | −int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) | |
| 1018 | +/** | |
| 1019 | + * intel_vgpu_setup_submission - setup submission-related resource for vGPU | |
| 1020 | + * @vgpu: a vGPU | |
| 1021 | + * | |
| 1022 | + * This function is called when a vGPU is being created. | |
| 1023 | + * | |
| 1024 | + * Returns: | |
| 1025 | + * Zero on success, negative error code if failed. | |
| 1026 | + * | |
| 1027 | + */ | |
| 1028 | +int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) | |
| 735 | 1029 | { |
| 736 | − atomic_set(&vgpu->running_workload_num, 0); | |
| 1030 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1031 | + enum intel_engine_id i; | |
| 1032 | + struct intel_engine_cs *engine; | |
| 1033 | + int ret; | |
| 737 | 1034 | |
| 738 | − vgpu->shadow_ctx = i915_gem_context_create_gvt( | |
| 1035 | + s->shadow_ctx = i915_gem_context_create_gvt( | |
| 739 | 1036 | &vgpu->gvt->dev_priv->drm); |
| 740 | − if (IS_ERR(vgpu->shadow_ctx)) | |
| 741 | − return PTR_ERR(vgpu->shadow_ctx); | |
| 1037 | + if (IS_ERR(s->shadow_ctx)) | |
| 1038 | + return PTR_ERR(s->shadow_ctx); | |
| 1039 | + | |
| 1040 | + bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); | |
| 1041 | + | |
| 1042 | + s->workloads = kmem_cache_create("gvt-g_vgpu_workload", | |
| 1043 | + sizeof(struct intel_vgpu_workload), 0, | |
| 1044 | + SLAB_HWCACHE_ALIGN, | |
| 1045 | + NULL); | |
| 1046 | + | |
| 1047 | + if (!s->workloads) { | |
| 1048 | + ret = -ENOMEM; | |
| 1049 | + goto out_shadow_ctx; | |
| 1050 | + } | |
| 1051 | + | |
| 1052 | + for_each_engine(engine, vgpu->gvt->dev_priv, i) | |
| 1053 | + INIT_LIST_HEAD(&s->workload_q_head[i]); | |
| 1054 | + | |
| 1055 | + atomic_set(&s->running_workload_num, 0); | |
| 1056 | + bitmap_zero(s->tlb_handle_pending, I915_NUM_ENGINES); | |
| 1057 | + | |
| 1058 | + return 0; | |
| 1059 | + | |
| 1060 | +out_shadow_ctx: | |
| 1061 | + i915_gem_context_put(s->shadow_ctx); | |
| 1062 | + return ret; | |
| 1063 | +} | |
| 1064 | + | |
| 1065 | +/** | |
| 1066 | + * intel_vgpu_select_submission_ops - select virtual submission interface | |
| 1067 | + * @vgpu: a vGPU | |
| 1068 | + * @interface: expected vGPU virtual submission interface | |
| 1069 | + * | |
| 1070 | + * This function is called when guest configures submission interface. | |
| 1071 | + * | |
| 1072 | + * Returns: | |
| 1073 | + * Zero on success, negative error code if failed. | |
| 1074 | + * | |
| 1075 | + */ | |
| 1076 | +int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, | |
| 1077 | + unsigned int interface) | |
| 1078 | +{ | |
| 1079 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1080 | + const struct intel_vgpu_submission_ops *ops[] = { | |
| 1081 | + [INTEL_VGPU_EXECLIST_SUBMISSION] = | |
| 1082 | + &intel_vgpu_execlist_submission_ops, | |
| 1083 | + }; | |
| 1084 | + int ret; | |
| 1085 | + | |
| 1086 | + if (WARN_ON(interface >= ARRAY_SIZE(ops))) | |
| 1087 | + return -EINVAL; | |
| 1088 | + | |
| 1089 | + if (s->active) { | |
| 1090 | + s->ops->clean(vgpu); | |
| 1091 | + s->active = false; | |
| 1092 | + gvt_dbg_core("vgpu%d: de-select ops [ %s ] \n", | |
| 1093 | + vgpu->id, s->ops->name); | |
| 1094 | + } | |
| 1095 | + | |
| 1096 | + if (interface == 0) { | |
| 1097 | + s->ops = NULL; | |
| 1098 | + s->virtual_submission_interface = 0; | |
| 1099 | + gvt_dbg_core("vgpu%d: no submission ops\n", vgpu->id); | |
| 1100 | + return 0; | |
| 1101 | + } | |
| 1102 | + | |
| 1103 | + ret = ops[interface]->init(vgpu); | |
| 1104 | + if (ret) | |
| 1105 | + return ret; | |
| 1106 | + | |
| 1107 | + s->ops = ops[interface]; | |
| 1108 | + s->virtual_submission_interface = interface; | |
| 1109 | + s->active = true; | |
| 1110 | + | |
| 1111 | + gvt_dbg_core("vgpu%d: activate ops [ %s ]\n", | |
| 1112 | + vgpu->id, s->ops->name); | |
| 1113 | + | |
| 1114 | + return 0; | |
| 1115 | +} | |
| 1116 | + | |
| 1117 | +/** | |
| 1118 | + * intel_vgpu_destroy_workload - destroy a vGPU workload | |
| 1119 | + * @vgpu: a vGPU | |
| 1120 | + * | |
| 1121 | + * This function is called when destroy a vGPU workload. | |
| 1122 | + * | |
| 1123 | + */ | |
| 1124 | +void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload) | |
| 1125 | +{ | |
| 1126 | + struct intel_vgpu_submission *s = &workload->vgpu->submission; | |
| 1127 | + | |
| 1128 | + if (workload->shadow_mm) | |
| 1129 | + intel_gvt_mm_unreference(workload->shadow_mm); | |
| 1130 | + | |
| 1131 | + kmem_cache_free(s->workloads, workload); | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +static struct intel_vgpu_workload * | |
| 1135 | +alloc_workload(struct intel_vgpu *vgpu) | |
| 1136 | +{ | |
| 1137 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1138 | + struct intel_vgpu_workload *workload; | |
| 742 | 1139 | |
| 743 | − vgpu->shadow_ctx->engine[RCS].initialised = true; | |
| 1140 | + workload = kmem_cache_zalloc(s->workloads, GFP_KERNEL); | |
| 1141 | + if (!workload) | |
| 1142 | + return ERR_PTR(-ENOMEM); | |
| 744 | 1143 | |
| 745 | − bitmap_zero(vgpu->shadow_ctx_desc_updated, I915_NUM_ENGINES); | |
| 1144 | + INIT_LIST_HEAD(&workload->list); | |
| 1145 | + INIT_LIST_HEAD(&workload->shadow_bb); | |
| 746 | 1146 | |
| 1147 | + init_waitqueue_head(&workload->shadow_ctx_status_wq); | |
| 1148 | + atomic_set(&workload->shadow_ctx_active, 0); | |
| 1149 | + | |
| 1150 | + workload->status = -EINPROGRESS; | |
| 1151 | + workload->shadowed = false; | |
| 1152 | + workload->vgpu = vgpu; | |
| 1153 | + | |
| 1154 | + return workload; | |
| 1155 | +} | |
| 1156 | + | |
| 1157 | +#define RING_CTX_OFF(x) \ | |
| 1158 | + offsetof(struct execlist_ring_context, x) | |
| 1159 | + | |
| 1160 | +static void read_guest_pdps(struct intel_vgpu *vgpu, | |
| 1161 | + u64 ring_context_gpa, u32 pdp[8]) | |
| 1162 | +{ | |
| 1163 | + u64 gpa; | |
| 1164 | + int i; | |
| 1165 | + | |
| 1166 | + gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val); | |
| 1167 | + | |
| 1168 | + for (i = 0; i < 8; i++) | |
| 1169 | + intel_gvt_hypervisor_read_gpa(vgpu, | |
| 1170 | + gpa + i * 8, &pdp[7 - i], 4); | |
| 1171 | +} | |
| 1172 | + | |
| 1173 | +static int prepare_mm(struct intel_vgpu_workload *workload) | |
| 1174 | +{ | |
| 1175 | + struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; | |
| 1176 | + struct intel_vgpu_mm *mm; | |
| 1177 | + struct intel_vgpu *vgpu = workload->vgpu; | |
| 1178 | + int page_table_level; | |
| 1179 | + u32 pdp[8]; | |
| 1180 | + | |
| 1181 | + if (desc->addressing_mode == 1) { /* legacy 32-bit */ | |
| 1182 | + page_table_level = 3; | |
| 1183 | + } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ | |
| 1184 | + page_table_level = 4; | |
| 1185 | + } else { | |
| 1186 | + gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n"); | |
| 1187 | + return -EINVAL; | |
| 1188 | + } | |
| 1189 | + | |
| 1190 | + read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); | |
| 1191 | + | |
| 1192 | + mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); | |
| 1193 | + if (mm) { | |
| 1194 | + intel_gvt_mm_reference(mm); | |
| 1195 | + } else { | |
| 1196 | + | |
| 1197 | + mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, | |
| 1198 | + pdp, page_table_level, 0); | |
| 1199 | + if (IS_ERR(mm)) { | |
| 1200 | + gvt_vgpu_err("fail to create mm object.\n"); | |
| 1201 | + return PTR_ERR(mm); | |
| 1202 | + } | |
| 1203 | + } | |
| 1204 | + workload->shadow_mm = mm; | |
| 747 | 1205 | return 0; |
| 748 | 1206 | } |
| 1207 | + | |
| 1208 | +#define same_context(a, b) (((a)->context_id == (b)->context_id) && \ | |
| 1209 | + ((a)->lrca == (b)->lrca)) | |
| 1210 | + | |
| 1211 | +#define get_last_workload(q) \ | |
| 1212 | + (list_empty(q) ? NULL : container_of(q->prev, \ | |
| 1213 | + struct intel_vgpu_workload, list)) | |
| 1214 | +/** | |
| 1215 | + * intel_vgpu_create_workload - create a vGPU workload | |
| 1216 | + * @vgpu: a vGPU | |
| 1217 | + * @desc: a guest context descriptor | |
| 1218 | + * | |
| 1219 | + * This function is called when creating a vGPU workload. | |
| 1220 | + * | |
| 1221 | + * Returns: | |
| 1222 | + * struct intel_vgpu_workload * on success, negative error code in | |
| 1223 | + * pointer if failed. | |
| 1224 | + * | |
| 1225 | + */ | |
| 1226 | +struct intel_vgpu_workload * | |
| 1227 | +intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id, | |
| 1228 | + struct execlist_ctx_descriptor_format *desc) | |
| 1229 | +{ | |
| 1230 | + struct intel_vgpu_submission *s = &vgpu->submission; | |
| 1231 | + struct list_head *q = workload_q_head(vgpu, ring_id); | |
| 1232 | + struct intel_vgpu_workload *last_workload = get_last_workload(q); | |
| 1233 | + struct intel_vgpu_workload *workload = NULL; | |
| 1234 | + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | |
| 1235 | + u64 ring_context_gpa; | |
| 1236 | + u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx; | |
| 1237 | + int ret; | |
| 1238 | + | |
| 1239 | + ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | |
| 1240 | + (u32)((desc->lrca + 1) << I915_GTT_PAGE_SHIFT)); | |
| 1241 | + if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { | |
| 1242 | + gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca); | |
| 1243 | + return ERR_PTR(-EINVAL); | |
| 1244 | + } | |
| 1245 | + | |
| 1246 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1247 | + RING_CTX_OFF(ring_header.val), &head, 4); | |
| 1248 | + | |
| 1249 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1250 | + RING_CTX_OFF(ring_tail.val), &tail, 4); | |
| 1251 | + | |
| 1252 | + head &= RB_HEAD_OFF_MASK; | |
| 1253 | + tail &= RB_TAIL_OFF_MASK; | |
| 1254 | + | |
| 1255 | + if (last_workload && same_context(&last_workload->ctx_desc, desc)) { | |
| 1256 | + gvt_dbg_el("ring id %d cur workload == last\n", ring_id); | |
| 1257 | + gvt_dbg_el("ctx head %x real head %lx\n", head, | |
| 1258 | + last_workload->rb_tail); | |
| 1259 | + /* | |
| 1260 | + * cannot use guest context head pointer here, | |
| 1261 | + * as it might not be updated at this time | |
| 1262 | + */ | |
| 1263 | + head = last_workload->rb_tail; | |
| 1264 | + } | |
| 1265 | + | |
| 1266 | + gvt_dbg_el("ring id %d begin a new workload\n", ring_id); | |
| 1267 | + | |
| 1268 | + /* record some ring buffer register values for scan and shadow */ | |
| 1269 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1270 | + RING_CTX_OFF(rb_start.val), &start, 4); | |
| 1271 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1272 | + RING_CTX_OFF(rb_ctrl.val), &ctl, 4); | |
| 1273 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1274 | + RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); | |
| 1275 | + | |
| 1276 | + workload = alloc_workload(vgpu); | |
| 1277 | + if (IS_ERR(workload)) | |
| 1278 | + return workload; | |
| 1279 | + | |
| 1280 | + workload->ring_id = ring_id; | |
| 1281 | + workload->ctx_desc = *desc; | |
| 1282 | + workload->ring_context_gpa = ring_context_gpa; | |
| 1283 | + workload->rb_head = head; | |
| 1284 | + workload->rb_tail = tail; | |
| 1285 | + workload->rb_start = start; | |
| 1286 | + workload->rb_ctl = ctl; | |
| 1287 | + | |
| 1288 | + if (ring_id == RCS) { | |
| 1289 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1290 | + RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4); | |
| 1291 | + intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | |
| 1292 | + RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4); | |
| 1293 | + | |
| 1294 | + workload->wa_ctx.indirect_ctx.guest_gma = | |
| 1295 | + indirect_ctx & INDIRECT_CTX_ADDR_MASK; | |
| 1296 | + workload->wa_ctx.indirect_ctx.size = | |
| 1297 | + (indirect_ctx & INDIRECT_CTX_SIZE_MASK) * | |
| 1298 | + CACHELINE_BYTES; | |
| 1299 | + workload->wa_ctx.per_ctx.guest_gma = | |
| 1300 | + per_ctx & PER_CTX_ADDR_MASK; | |
| 1301 | + workload->wa_ctx.per_ctx.valid = per_ctx & 1; | |
| 1302 | + } | |
| 1303 | + | |
| 1304 | + gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n", | |
| 1305 | + workload, ring_id, head, tail, start, ctl); | |
| 1306 | + | |
| 1307 | + ret = prepare_mm(workload); | |
| 1308 | + if (ret) { | |
| 1309 | + kmem_cache_free(s->workloads, workload); | |
| 1310 | + return ERR_PTR(ret); | |
| 1311 | + } | |
| 1312 | + | |
| 1313 | + /* Only scan and shadow the first workload in the queue | |
| 1314 | + * as there is only one pre-allocated buf-obj for shadow. | |
| 1315 | + */ | |
| 1316 | + if (list_empty(workload_q_head(vgpu, ring_id))) { | |
| 1317 | + intel_runtime_pm_get(dev_priv); | |
| 1318 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 1319 | + ret = intel_gvt_scan_and_shadow_workload(workload); | |
| 1320 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 1321 | + intel_runtime_pm_put(dev_priv); | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + if (ret && (vgpu_is_vm_unhealthy(ret))) { | |
| 1325 | + enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR); | |
| 1326 | + intel_vgpu_destroy_workload(workload); | |
| 1327 | + return ERR_PTR(ret); | |
| 1328 | + } | |
| 1329 | + | |
| 1330 | + return workload; | |
| 1331 | +} | |
| @@ -112,17 +112,18 @@ struct intel_vgpu_workload { · 111 unmodified lines | ||
| 112 | 112 | struct intel_shadow_wa_ctx wa_ctx; |
| 113 | 113 | }; |
| 114 | 114 | |
| 115 | −/* Intel shadow batch buffer is a i915 gem object */ | |
| 116 | −struct intel_shadow_bb_entry { | |
| 115 | +struct intel_vgpu_shadow_bb { | |
| 117 | 116 | struct list_head list; |
| 118 | 117 | struct drm_i915_gem_object *obj; |
| 118 | + struct i915_vma *vma; | |
| 119 | 119 | void *va; |
| 120 | − unsigned long len; | |
| 121 | 120 | u32 *bb_start_cmd_va; |
| 121 | + unsigned int clflush; | |
| 122 | + bool accessing; | |
| 122 | 123 | }; |
| 123 | 124 | |
| 124 | 125 | #define workload_q_head(vgpu, ring_id) \ |
| 125 | − (&(vgpu->workload_q_head[ring_id])) | |
| 126 | + (&(vgpu->submission.workload_q_head[ring_id])) | |
| 126 | 127 | |
| 127 | 128 | #define queue_workload(workload) do { \ |
| 128 | 129 | list_add_tail(&workload->list, \ |
| @@ -137,12 +138,23 @@ void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt); · 8 unmodified lines | ||
| 137 | 138 | |
| 138 | 139 | void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu); |
| 139 | 140 | |
| 140 | −int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); | |
| 141 | +int intel_vgpu_setup_submission(struct intel_vgpu *vgpu); | |
| 141 | 142 | |
| 142 | −void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); | |
| 143 | +void intel_vgpu_reset_submission(struct intel_vgpu *vgpu, | |
| 144 | + unsigned long engine_mask); | |
| 143 | 145 | |
| 144 | −void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); | |
| 146 | +void intel_vgpu_clean_submission(struct intel_vgpu *vgpu); | |
| 145 | 147 | |
| 146 | −int intel_gvt_generate_request(struct intel_vgpu_workload *workload); | |
| 148 | +int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, | |
| 149 | + unsigned int interface); | |
| 150 | + | |
| 151 | +extern const struct intel_vgpu_submission_ops | |
| 152 | +intel_vgpu_execlist_submission_ops; | |
| 153 | + | |
| 154 | +struct intel_vgpu_workload * | |
| 155 | +intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id, | |
| 156 | + struct execlist_ctx_descriptor_format *desc); | |
| 157 | + | |
| 158 | +void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload); | |
| 147 | 159 | |
| 148 | 160 | #endif |
| @@ -43,7 +43,10 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu) · 42 unmodified lines | ||
| 43 | 43 | vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0; |
| 44 | 44 | vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0; |
| 45 | 45 | vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id; |
| 46 | + | |
| 46 | 47 | vgpu_vreg(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT; |
| 48 | + vgpu_vreg(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION; | |
| 49 | + | |
| 47 | 50 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = |
| 48 | 51 | vgpu_aperture_gmadr_base(vgpu); |
| 49 | 52 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = |
| @@ -226,7 +229,7 @@ void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu) · 176 unmodified lines | ||
| 226 | 229 | |
| 227 | 230 | vgpu->active = false; |
| 228 | 231 | |
| 229 | − if (atomic_read(&vgpu->running_workload_num)) { | |
| 232 | + if (atomic_read(&vgpu->submission.running_workload_num)) { | |
| 230 | 233 | mutex_unlock(&gvt->lock); |
| 231 | 234 | intel_gvt_wait_vgpu_idle(vgpu); |
| 232 | 235 | mutex_lock(&gvt->lock); |
| @@ -252,10 +255,10 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) · 19 unmodified lines | ||
| 252 | 255 | |
| 253 | 256 | WARN(vgpu->active, "vGPU is still active!\n"); |
| 254 | 257 | |
| 258 | + intel_gvt_debugfs_remove_vgpu(vgpu); | |
| 255 | 259 | idr_remove(&gvt->vgpu_idr, vgpu->id); |
| 256 | 260 | intel_vgpu_clean_sched_policy(vgpu); |
| 257 | − intel_vgpu_clean_gvt_context(vgpu); | |
| 258 | − intel_vgpu_clean_execlist(vgpu); | |
| 261 | + intel_vgpu_clean_submission(vgpu); | |
| 259 | 262 | intel_vgpu_clean_display(vgpu); |
| 260 | 263 | intel_vgpu_clean_opregion(vgpu); |
| 261 | 264 | intel_vgpu_clean_gtt(vgpu); |
| @@ -293,7 +296,7 @@ struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt) · 31 unmodified lines | ||
| 293 | 296 | vgpu->gvt = gvt; |
| 294 | 297 | |
| 295 | 298 | for (i = 0; i < I915_NUM_ENGINES; i++) |
| 296 | − INIT_LIST_HEAD(&vgpu->workload_q_head[i]); | |
| 299 | + INIT_LIST_HEAD(&vgpu->submission.workload_q_head[i]); | |
| 297 | 300 | |
| 298 | 301 | ret = intel_vgpu_init_sched_policy(vgpu); |
| 299 | 302 | if (ret) |
| @@ -346,7 +349,6 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, · 46 unmodified lines | ||
| 346 | 349 | vgpu->handle = param->handle; |
| 347 | 350 | vgpu->gvt = gvt; |
| 348 | 351 | vgpu->sched_ctl.weight = param->weight; |
| 349 | − bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); | |
| 350 | 352 | |
| 351 | 353 | intel_vgpu_init_cfg_space(vgpu, param->primary); |
| 352 | 354 | |
| @@ -372,26 +374,26 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, · 19 unmodified lines | ||
| 372 | 374 | if (ret) |
| 373 | 375 | goto out_clean_gtt; |
| 374 | 376 | |
| 375 | − ret = intel_vgpu_init_execlist(vgpu); | |
| 377 | + ret = intel_vgpu_setup_submission(vgpu); | |
| 376 | 378 | if (ret) |
| 377 | 379 | goto out_clean_display; |
| 378 | 380 | |
| 379 | − ret = intel_vgpu_init_gvt_context(vgpu); | |
| 381 | + ret = intel_vgpu_init_sched_policy(vgpu); | |
| 380 | 382 | if (ret) |
| 381 | − goto out_clean_execlist; | |
| 383 | + goto out_clean_submission; | |
| 382 | 384 | |
| 383 | − ret = intel_vgpu_init_sched_policy(vgpu); | |
| 385 | + ret = intel_gvt_debugfs_add_vgpu(vgpu); | |
| 384 | 386 | if (ret) |
| 385 | − goto out_clean_shadow_ctx; | |
| 387 | + goto out_clean_sched_policy; | |
| 386 | 388 | |
| 387 | 389 | mutex_unlock(&gvt->lock); |
| 388 | 390 | |
| 389 | 391 | return vgpu; |
| 390 | 392 | |
| 391 | −out_clean_shadow_ctx: | |
| 392 | − intel_vgpu_clean_gvt_context(vgpu); | |
| 393 | −out_clean_execlist: | |
| 394 | − intel_vgpu_clean_execlist(vgpu); | |
| 393 | +out_clean_sched_policy: | |
| 394 | + intel_vgpu_clean_sched_policy(vgpu); | |
| 395 | +out_clean_submission: | |
| 396 | + intel_vgpu_clean_submission(vgpu); | |
| 395 | 397 | out_clean_display: |
| 396 | 398 | intel_vgpu_clean_display(vgpu); |
| 397 | 399 | out_clean_gtt: |
| @@ -500,10 +502,10 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, · 102 unmodified lines | ||
| 500 | 502 | mutex_lock(&gvt->lock); |
| 501 | 503 | } |
| 502 | 504 | |
| 503 | − intel_vgpu_reset_execlist(vgpu, resetting_eng); | |
| 504 | − | |
| 505 | + intel_vgpu_reset_submission(vgpu, resetting_eng); | |
| 505 | 506 | /* full GPU reset or device model level reset */ |
| 506 | 507 | if (engine_mask == ALL_ENGINES || dmlr) { |
| 508 | + intel_vgpu_select_submission_ops(vgpu, 0); | |
| 507 | 509 | |
| 508 | 510 | /*fence will not be reset during virtual reset */ |
| 509 | 511 | if (dmlr) { |
| @@ -798,22 +798,15 @@ struct cmd_node { · 797 unmodified lines | ||
| 798 | 798 | */ |
| 799 | 799 | static inline u32 cmd_header_key(u32 x) |
| 800 | 800 | { |
| 801 | − u32 shift; | |
| 802 | − | |
| 803 | 801 | switch (x >> INSTR_CLIENT_SHIFT) { |
| 804 | 802 | default: |
| 805 | 803 | case INSTR_MI_CLIENT: |
| 806 | − shift = STD_MI_OPCODE_SHIFT; | |
| 807 | − break; | |
| 804 | + return x >> STD_MI_OPCODE_SHIFT; | |
| 808 | 805 | case INSTR_RC_CLIENT: |
| 809 | − shift = STD_3D_OPCODE_SHIFT; | |
| 810 | − break; | |
| 806 | + return x >> STD_3D_OPCODE_SHIFT; | |
| 811 | 807 | case INSTR_BC_CLIENT: |
| 812 | − shift = STD_2D_OPCODE_SHIFT; | |
| 813 | − break; | |
| 808 | + return x >> STD_2D_OPCODE_SHIFT; | |
| 814 | 809 | } |
| 815 | − | |
| 816 | − return x >> shift; | |
| 817 | 810 | } |
| 818 | 811 | |
| 819 | 812 | static int init_hash_table(struct intel_engine_cs *engine, |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/sort.h> |
| 31 | 31 | #include <linux/sched/mm.h> |
| 32 | 32 | #include "intel_drv.h" |
| 33 | −#include "i915_guc_submission.h" | |
| 33 | +#include "intel_guc_submission.h" | |
| 34 | 34 | |
| 35 | 35 | static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) |
| 36 | 36 | { |
| @@ -1974,7 +1974,6 @@ static int i915_context_status(struct seq_file *m, void *unused) · 1937 unmodified lines | ||
| 1974 | 1974 | struct intel_context *ce = &ctx->engine[engine->id]; |
| 1975 | 1975 | |
| 1976 | 1976 | seq_printf(m, "%s: ", engine->name); |
| 1977 | − seq_putc(m, ce->initialised ? 'I' : 'i'); | |
| 1978 | 1977 | if (ce->state) |
| 1979 | 1978 | describe_obj(m, ce->state->obj); |
| 1980 | 1979 | if (ce->ring) |
| @@ -2434,7 +2433,7 @@ static void i915_guc_log_info(struct seq_file *m, · 453 unmodified lines | ||
| 2434 | 2433 | |
| 2435 | 2434 | static void i915_guc_client_info(struct seq_file *m, |
| 2436 | 2435 | struct drm_i915_private *dev_priv, |
| 2437 | − struct i915_guc_client *client) | |
| 2436 | + struct intel_guc_client *client) | |
| 2438 | 2437 | { |
| 2439 | 2438 | struct intel_engine_cs *engine; |
| 2440 | 2439 | enum intel_engine_id id; |
| @@ -2484,6 +2483,8 @@ static int i915_guc_info(struct seq_file *m, void *data) · 43 unmodified lines | ||
| 2484 | 2483 | |
| 2485 | 2484 | seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); |
| 2486 | 2485 | i915_guc_client_info(m, dev_priv, guc->execbuf_client); |
| 2486 | + seq_printf(m, "\nGuC preempt client @ %p:\n", guc->preempt_client); | |
| 2487 | + i915_guc_client_info(m, dev_priv, guc->preempt_client); | |
| 2487 | 2488 | |
| 2488 | 2489 | i915_guc_log_info(m, dev_priv); |
| 2489 | 2490 | |
| @@ -2497,7 +2498,7 @@ static int i915_guc_stage_pool(struct seq_file *m, void *data) · 7 unmodified lines | ||
| 2497 | 2498 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 2498 | 2499 | const struct intel_guc *guc = &dev_priv->guc; |
| 2499 | 2500 | struct guc_stage_desc *desc = guc->stage_desc_pool_vaddr; |
| 2500 | − struct i915_guc_client *client = guc->execbuf_client; | |
| 2501 | + struct intel_guc_client *client = guc->execbuf_client; | |
| 2501 | 2502 | unsigned int tmp; |
| 2502 | 2503 | int index; |
| 2503 | 2504 | |
| @@ -2734,39 +2735,76 @@ static int i915_sink_crc(struct seq_file *m, void *data) · 230 unmodified lines | ||
| 2734 | 2735 | struct intel_connector *connector; |
| 2735 | 2736 | struct drm_connector_list_iter conn_iter; |
| 2736 | 2737 | struct intel_dp *intel_dp = NULL; |
| 2738 | + struct drm_modeset_acquire_ctx ctx; | |
| 2737 | 2739 | int ret; |
| 2738 | 2740 | u8 crc[6]; |
| 2739 | 2741 | |
| 2740 | − drm_modeset_lock_all(dev); | |
| 2742 | + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); | |
| 2743 | + | |
| 2741 | 2744 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 2745 | + | |
| 2742 | 2746 | for_each_intel_connector_iter(connector, &conn_iter) { |
| 2743 | 2747 | struct drm_crtc *crtc; |
| 2748 | + struct drm_connector_state *state; | |
| 2749 | + struct intel_crtc_state *crtc_state; | |
| 2744 | 2750 | |
| 2745 | − if (!connector->base.state->best_encoder) | |
| 2751 | + if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) | |
| 2746 | 2752 | continue; |
| 2747 | 2753 | |
| 2748 | − crtc = connector->base.state->crtc; | |
| 2749 | − if (!crtc->state->active) | |
| 2754 | +retry: | |
| 2755 | + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); | |
| 2756 | + if (ret) | |
| 2757 | + goto err; | |
| 2758 | + | |
| 2759 | + state = connector->base.state; | |
| 2760 | + if (!state->best_encoder) | |
| 2750 | 2761 | continue; |
| 2751 | 2762 | |
| 2752 | − if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) | |
| 2763 | + crtc = state->crtc; | |
| 2764 | + ret = drm_modeset_lock(&crtc->mutex, &ctx); | |
| 2765 | + if (ret) | |
| 2766 | + goto err; | |
| 2767 | + | |
| 2768 | + crtc_state = to_intel_crtc_state(crtc->state); | |
| 2769 | + if (!crtc_state->base.active) | |
| 2753 | 2770 | continue; |
| 2754 | 2771 | |
| 2755 | − intel_dp = enc_to_intel_dp(connector->base.state->best_encoder); | |
| 2772 | + /* | |
| 2773 | + * We need to wait for all crtc updates to complete, to make | |
| 2774 | + * sure any pending modesets and plane updates are completed. | |
| 2775 | + */ | |
| 2776 | + if (crtc_state->base.commit) { | |
| 2777 | + ret = wait_for_completion_interruptible(&crtc_state->base.commit->hw_done); | |
| 2756 | 2778 | |
| 2757 | − ret = intel_dp_sink_crc(intel_dp, crc); | |
| 2779 | + if (ret) | |
| 2780 | + goto err; | |
| 2781 | + } | |
| 2782 | + | |
| 2783 | + intel_dp = enc_to_intel_dp(state->best_encoder); | |
| 2784 | + | |
| 2785 | + ret = intel_dp_sink_crc(intel_dp, crtc_state, crc); | |
| 2758 | 2786 | if (ret) |
| 2759 | − goto out; | |
| 2787 | + goto err; | |
| 2760 | 2788 | |
| 2761 | 2789 | seq_printf(m, "%02x%02x%02x%02x%02x%02x\n", |
| 2762 | 2790 | crc[0], crc[1], crc[2], |
| 2763 | 2791 | crc[3], crc[4], crc[5]); |
| 2764 | 2792 | goto out; |
| 2793 | + | |
| 2794 | +err: | |
| 2795 | + if (ret == -EDEADLK) { | |
| 2796 | + ret = drm_modeset_backoff(&ctx); | |
| 2797 | + if (!ret) | |
| 2798 | + goto retry; | |
| 2799 | + } | |
| 2800 | + goto out; | |
| 2765 | 2801 | } |
| 2766 | 2802 | ret = -ENODEV; |
| 2767 | 2803 | out: |
| 2768 | 2804 | drm_connector_list_iter_end(&conn_iter); |
| 2769 | − drm_modeset_unlock_all(dev); | |
| 2805 | + drm_modeset_drop_locks(&ctx); | |
| 2806 | + drm_modeset_acquire_fini(&ctx); | |
| 2807 | + | |
| 2770 | 2808 | return ret; |
| 2771 | 2809 | } |
| 2772 | 2810 | |
| @@ -3049,7 +3087,7 @@ static void intel_connector_info(struct seq_file *m, · 276 unmodified lines | ||
| 3049 | 3087 | break; |
| 3050 | 3088 | case DRM_MODE_CONNECTOR_HDMIA: |
| 3051 | 3089 | if (intel_encoder->type == INTEL_OUTPUT_HDMI || |
| 3052 | − intel_encoder->type == INTEL_OUTPUT_UNKNOWN) | |
| 3090 | + intel_encoder->type == INTEL_OUTPUT_DDI) | |
| 3053 | 3091 | intel_hdmi_info(m, intel_connector); |
| 3054 | 3092 | break; |
| 3055 | 3093 | default: |
| @@ -3244,6 +3282,8 @@ static int i915_engine_info(struct seq_file *m, void *unused) · 188 unmodified lines | ||
| 3244 | 3282 | yesno(dev_priv->gt.awake)); |
| 3245 | 3283 | seq_printf(m, "Global active requests: %d\n", |
| 3246 | 3284 | dev_priv->gt.active_requests); |
| 3285 | + seq_printf(m, "CS timestamp frequency: %u kHz\n", | |
| 3286 | + dev_priv->info.cs_timestamp_frequency_khz); | |
| 3247 | 3287 | |
| 3248 | 3288 | p = drm_seq_file_printer(m); |
| 3249 | 3289 | for_each_engine(engine, dev_priv, id) |
| @@ -3601,7 +3641,7 @@ static int i915_dp_mst_info(struct seq_file *m, void *unused) · 351 unmodified lines | ||
| 3601 | 3641 | continue; |
| 3602 | 3642 | |
| 3603 | 3643 | seq_printf(m, "MST Source Port %c\n", |
| 3604 | − port_name(intel_dig_port->port)); | |
| 3644 | + port_name(intel_dig_port->base.port)); | |
| 3605 | 3645 | drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr); |
| 3606 | 3646 | } |
| 3607 | 3647 | drm_connector_list_iter_end(&conn_iter); |
| @@ -4448,6 +4488,61 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, · 840 unmodified lines | ||
| 4448 | 4488 | } |
| 4449 | 4489 | } |
| 4450 | 4490 | |
| 4491 | +static void gen10_sseu_device_status(struct drm_i915_private *dev_priv, | |
| 4492 | + struct sseu_dev_info *sseu) | |
| 4493 | +{ | |
| 4494 | + const struct intel_device_info *info = INTEL_INFO(dev_priv); | |
| 4495 | + int s_max = 6, ss_max = 4; | |
| 4496 | + int s, ss; | |
| 4497 | + u32 s_reg[s_max], eu_reg[2 * s_max], eu_mask[2]; | |
| 4498 | + | |
| 4499 | + for (s = 0; s < s_max; s++) { | |
| 4500 | + /* | |
| 4501 | + * FIXME: Valid SS Mask respects the spec and read | |
| 4502 | + * only valid bits for those registers, excluding reserverd | |
| 4503 | + * although this seems wrong because it would leave many | |
| 4504 | + * subslices without ACK. | |
| 4505 | + */ | |
| 4506 | + s_reg[s] = I915_READ(GEN10_SLICE_PGCTL_ACK(s)) & | |
| 4507 | + GEN10_PGCTL_VALID_SS_MASK(s); | |
| 4508 | + eu_reg[2 * s] = I915_READ(GEN10_SS01_EU_PGCTL_ACK(s)); | |
| 4509 | + eu_reg[2 * s + 1] = I915_READ(GEN10_SS23_EU_PGCTL_ACK(s)); | |
| 4510 | + } | |
| 4511 | + | |
| 4512 | + eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | | |
| 4513 | + GEN9_PGCTL_SSA_EU19_ACK | | |
| 4514 | + GEN9_PGCTL_SSA_EU210_ACK | | |
| 4515 | + GEN9_PGCTL_SSA_EU311_ACK; | |
| 4516 | + eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK | | |
| 4517 | + GEN9_PGCTL_SSB_EU19_ACK | | |
| 4518 | + GEN9_PGCTL_SSB_EU210_ACK | | |
| 4519 | + GEN9_PGCTL_SSB_EU311_ACK; | |
| 4520 | + | |
| 4521 | + for (s = 0; s < s_max; s++) { | |
| 4522 | + if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) | |
| 4523 | + /* skip disabled slice */ | |
| 4524 | + continue; | |
| 4525 | + | |
| 4526 | + sseu->slice_mask |= BIT(s); | |
| 4527 | + sseu->subslice_mask = info->sseu.subslice_mask; | |
| 4528 | + | |
| 4529 | + for (ss = 0; ss < ss_max; ss++) { | |
| 4530 | + unsigned int eu_cnt; | |
| 4531 | + | |
| 4532 | + if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) | |
| 4533 | + /* skip disabled subslice */ | |
| 4534 | + continue; | |
| 4535 | + | |
| 4536 | + eu_cnt = 2 * hweight32(eu_reg[2 * s + ss / 2] & | |
| 4537 | + eu_mask[ss % 2]); | |
| 4538 | + sseu->eu_total += eu_cnt; | |
| 4539 | + sseu->eu_per_subslice = max_t(unsigned int, | |
| 4540 | + sseu->eu_per_subslice, | |
| 4541 | + eu_cnt); | |
| 4542 | + } | |
| 4543 | + } | |
| 4544 | +} | |
| 4545 | + | |
| 4451 | 4546 | static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, |
| 4452 | 4547 | struct sseu_dev_info *sseu) |
| 4453 | 4548 | { |
| @@ -4483,7 +4578,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, · 29 unmodified lines | ||
| 4483 | 4578 | |
| 4484 | 4579 | sseu->slice_mask |= BIT(s); |
| 4485 | 4580 | |
| 4486 | − if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) | |
| 4581 | + if (IS_GEN9_BC(dev_priv)) | |
| 4487 | 4582 | sseu->subslice_mask = |
| 4488 | 4583 | INTEL_INFO(dev_priv)->sseu.subslice_mask; |
| 4489 | 4584 | |
| @@ -4589,8 +4684,10 @@ static int i915_sseu_status(struct seq_file *m, void *unused) · 99 unmodified lines | ||
| 4589 | 4684 | cherryview_sseu_device_status(dev_priv, &sseu); |
| 4590 | 4685 | } else if (IS_BROADWELL(dev_priv)) { |
| 4591 | 4686 | broadwell_sseu_device_status(dev_priv, &sseu); |
| 4592 | − } else if (INTEL_GEN(dev_priv) >= 9) { | |
| 4687 | + } else if (IS_GEN9(dev_priv)) { | |
| 4593 | 4688 | gen9_sseu_device_status(dev_priv, &sseu); |
| 4689 | + } else if (INTEL_GEN(dev_priv) >= 10) { | |
| 4690 | + gen10_sseu_device_status(dev_priv, &sseu); | |
| 4594 | 4691 | } |
| 4595 | 4692 | |
| 4596 | 4693 | intel_runtime_pm_put(dev_priv); |
| @@ -372,9 +372,8 @@ static int i915_getparam(struct drm_device *dev, void *data, · 371 unmodified lines | ||
| 372 | 372 | value |= I915_SCHEDULER_CAP_ENABLED; |
| 373 | 373 | value |= I915_SCHEDULER_CAP_PRIORITY; |
| 374 | 374 | |
| 375 | − if (INTEL_INFO(dev_priv)->has_logical_ring_preemption && | |
| 376 | − i915_modparams.enable_execlists && | |
| 377 | − !i915_modparams.enable_guc_submission) | |
| 375 | + if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) && | |
| 376 | + i915_modparams.enable_execlists) | |
| 378 | 377 | value |= I915_SCHEDULER_CAP_PREEMPTION; |
| 379 | 378 | } |
| 380 | 379 | break; |
| @@ -407,6 +406,9 @@ static int i915_getparam(struct drm_device *dev, void *data, · 26 unmodified lines | ||
| 407 | 406 | */ |
| 408 | 407 | value = 1; |
| 409 | 408 | break; |
| 409 | + case I915_PARAM_HAS_CONTEXT_ISOLATION: | |
| 410 | + value = intel_engines_has_context_isolation(dev_priv); | |
| 411 | + break; | |
| 410 | 412 | case I915_PARAM_SLICE_MASK: |
| 411 | 413 | value = INTEL_INFO(dev_priv)->sseu.slice_mask; |
| 412 | 414 | if (!value) |
| @@ -417,6 +419,9 @@ static int i915_getparam(struct drm_device *dev, void *data, · 4 unmodified lines | ||
| 417 | 419 | if (!value) |
| 418 | 420 | return -ENODEV; |
| 419 | 421 | break; |
| 422 | + case I915_PARAM_CS_TIMESTAMP_FREQUENCY: | |
| 423 | + value = 1000 * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz; | |
| 424 | + break; | |
| 420 | 425 | default: |
| 421 | 426 | DRM_DEBUG("Unknown parameter %d\n", param->param); |
| 422 | 427 | return -EINVAL; |
| @@ -677,7 +682,7 @@ static int i915_load_modeset_init(struct drm_device *dev) · 254 unmodified lines | ||
| 677 | 682 | if (ret) |
| 678 | 683 | goto cleanup_uc; |
| 679 | 684 | |
| 680 | − intel_modeset_gem_init(dev); | |
| 685 | + intel_setup_overlay(dev_priv); | |
| 681 | 686 | |
| 682 | 687 | if (INTEL_INFO(dev_priv)->num_pipes == 0) |
| 683 | 688 | return 0; |
| @@ -838,6 +843,11 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) · 154 unmodified lines | ||
| 838 | 843 | * We don't keep the workarounds for pre-production hardware, so we expect our |
| 839 | 844 | * driver to fail on these machines in one way or another. A little warning on |
| 840 | 845 | * dmesg may help both the user and the bug triagers. |
| 846 | + * | |
| 847 | + * Our policy for removing pre-production workarounds is to keep the | |
| 848 | + * current gen workarounds as a guide to the bring-up of the next gen | |
| 849 | + * (workarounds have a habit of persisting!). Anything older than that | |
| 850 | + * should be removed along with the complications they introduce. | |
| 841 | 851 | */ |
| 842 | 852 | static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) |
| 843 | 853 | { |
| @@ -892,7 +902,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, · 48 unmodified lines | ||
| 892 | 902 | mutex_init(&dev_priv->backlight_lock); |
| 893 | 903 | spin_lock_init(&dev_priv->uncore.lock); |
| 894 | 904 | |
| 895 | − spin_lock_init(&dev_priv->mm.object_stat_lock); | |
| 896 | 905 | mutex_init(&dev_priv->sb_lock); |
| 897 | 906 | mutex_init(&dev_priv->modeset_restore_lock); |
| 898 | 907 | mutex_init(&dev_priv->av_mutex); |
| @@ -1682,8 +1691,6 @@ static int i915_drm_resume(struct drm_device *dev) · 783 unmodified lines | ||
| 1682 | 1691 | |
| 1683 | 1692 | intel_csr_ucode_resume(dev_priv); |
| 1684 | 1693 | |
| 1685 | − i915_gem_resume(dev_priv); | |
| 1686 | − | |
| 1687 | 1694 | i915_restore_state(dev_priv); |
| 1688 | 1695 | intel_pps_unlock_regs_wa(dev_priv); |
| 1689 | 1696 | intel_opregion_setup(dev_priv); |
| @@ -1704,14 +1711,7 @@ static int i915_drm_resume(struct drm_device *dev) · 14 unmodified lines | ||
| 1704 | 1711 | |
| 1705 | 1712 | drm_mode_config_reset(dev); |
| 1706 | 1713 | |
| 1707 | − mutex_lock(&dev->struct_mutex); | |
| 1708 | − if (i915_gem_init_hw(dev_priv)) { | |
| 1709 | − DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); | |
| 1710 | − i915_gem_set_wedged(dev_priv); | |
| 1711 | − } | |
| 1712 | − mutex_unlock(&dev->struct_mutex); | |
| 1713 | − | |
| 1714 | − intel_guc_resume(dev_priv); | |
| 1714 | + i915_gem_resume(dev_priv); | |
| 1715 | 1715 | |
| 1716 | 1716 | intel_modeset_init_hw(dev); |
| 1717 | 1717 | intel_init_clock_gating(dev_priv); |
| @@ -1745,8 +1745,6 @@ static int i915_drm_resume(struct drm_device *dev) · 27 unmodified lines | ||
| 1745 | 1745 | |
| 1746 | 1746 | intel_opregion_notify_adapter(dev_priv, PCI_D0); |
| 1747 | 1747 | |
| 1748 | − intel_autoenable_gt_powersave(dev_priv); | |
| 1749 | − | |
| 1750 | 1748 | enable_rpm_wakeref_asserts(dev_priv); |
| 1751 | 1749 | |
| 1752 | 1750 | return 0; |
| @@ -1952,6 +1950,12 @@ error: · 199 unmodified lines | ||
| 1952 | 1950 | goto finish; |
| 1953 | 1951 | } |
| 1954 | 1952 | |
| 1953 | +static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv, | |
| 1954 | + struct intel_engine_cs *engine) | |
| 1955 | +{ | |
| 1956 | + return intel_gpu_reset(dev_priv, intel_engine_flag(engine)); | |
| 1957 | +} | |
| 1958 | + | |
| 1955 | 1959 | /** |
| 1956 | 1960 | * i915_reset_engine - reset GPU engine to recover from a hang |
| 1957 | 1961 | * @engine: engine to reset |
| @@ -1986,10 +1990,14 @@ int i915_reset_engine(struct intel_engine_cs *engine, unsigned int flags) · 28 unmodified lines | ||
| 1986 | 1990 | goto out; |
| 1987 | 1991 | } |
| 1988 | 1992 | |
| 1989 | − ret = intel_gpu_reset(engine->i915, intel_engine_flag(engine)); | |
| 1993 | + if (!engine->i915->guc.execbuf_client) | |
| 1994 | + ret = intel_gt_reset_engine(engine->i915, engine); | |
| 1995 | + else | |
| 1996 | + ret = intel_guc_reset_engine(&engine->i915->guc, engine); | |
| 1990 | 1997 | if (ret) { |
| 1991 | 1998 | /* If we fail here, we expect to fallback to a global reset */ |
| 1992 | − DRM_DEBUG_DRIVER("Failed to reset %s, ret=%d\n", | |
| 1999 | + DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n", | |
| 2000 | + engine->i915->guc.execbuf_client ? "GuC " : "", | |
| 1993 | 2001 | engine->name, ret); |
| 1994 | 2002 | goto out; |
| 1995 | 2003 | } |
| @@ -2524,6 +2532,8 @@ static int intel_runtime_suspend(struct device *kdev) · 528 unmodified lines | ||
| 2524 | 2532 | |
| 2525 | 2533 | intel_runtime_pm_disable_interrupts(dev_priv); |
| 2526 | 2534 | |
| 2535 | + intel_uncore_suspend(dev_priv); | |
| 2536 | + | |
| 2527 | 2537 | ret = 0; |
| 2528 | 2538 | if (IS_GEN9_LP(dev_priv)) { |
| 2529 | 2539 | bxt_display_core_uninit(dev_priv); |
| @@ -2536,6 +2546,8 @@ static int intel_runtime_suspend(struct device *kdev) · 6 unmodified lines | ||
| 2536 | 2546 | |
| 2537 | 2547 | if (ret) { |
| 2538 | 2548 | DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret); |
| 2549 | + intel_uncore_runtime_resume(dev_priv); | |
| 2550 | + | |
| 2539 | 2551 | intel_runtime_pm_enable_interrupts(dev_priv); |
| 2540 | 2552 | |
| 2541 | 2553 | enable_rpm_wakeref_asserts(dev_priv); |
| @@ -2543,8 +2555,6 @@ static int intel_runtime_suspend(struct device *kdev) · 1 unmodified line | ||
| 2543 | 2555 | return ret; |
| 2544 | 2556 | } |
| 2545 | 2557 | |
| 2546 | − intel_uncore_suspend(dev_priv); | |
| 2547 | − | |
| 2548 | 2558 | enable_rpm_wakeref_asserts(dev_priv); |
| 2549 | 2559 | WARN_ON_ONCE(atomic_read(&dev_priv->runtime_pm.wakeref_count)); |
| 2550 | 2560 | |
| @@ -67,7 +67,6 @@ · 66 unmodified lines | ||
| 67 | 67 | #include "i915_gem_fence_reg.h" |
| 68 | 68 | #include "i915_gem_object.h" |
| 69 | 69 | #include "i915_gem_gtt.h" |
| 70 | −#include "i915_gem_render_state.h" | |
| 71 | 70 | #include "i915_gem_request.h" |
| 72 | 71 | #include "i915_gem_timeline.h" |
| 73 | 72 | |
| @@ -80,8 +79,8 @@ · 6 unmodified lines | ||
| 80 | 79 | |
| 81 | 80 | #define DRIVER_NAME "i915" |
| 82 | 81 | #define DRIVER_DESC "Intel Graphics" |
| 83 | −#define DRIVER_DATE "20171023" | |
| 84 | −#define DRIVER_TIMESTAMP 1508748913 | |
| 82 | +#define DRIVER_DATE "20171117" | |
| 83 | +#define DRIVER_TIMESTAMP 1510958822 | |
| 85 | 84 | |
| 86 | 85 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and |
| 87 | 86 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions |
| @@ -726,10 +725,12 @@ struct drm_i915_display_funcs { · 638 unmodified lines | ||
| 726 | 725 | void (*crtc_disable)(struct intel_crtc_state *old_crtc_state, |
| 727 | 726 | struct drm_atomic_state *old_state); |
| 728 | 727 | void (*update_crtcs)(struct drm_atomic_state *state); |
| 729 | − void (*audio_codec_enable)(struct drm_connector *connector, | |
| 730 | − struct intel_encoder *encoder, | |
| 731 | − const struct drm_display_mode *adjusted_mode); | |
| 732 | − void (*audio_codec_disable)(struct intel_encoder *encoder); | |
| 728 | + void (*audio_codec_enable)(struct intel_encoder *encoder, | |
| 729 | + const struct intel_crtc_state *crtc_state, | |
| 730 | + const struct drm_connector_state *conn_state); | |
| 731 | + void (*audio_codec_disable)(struct intel_encoder *encoder, | |
| 732 | + const struct intel_crtc_state *old_crtc_state, | |
| 733 | + const struct drm_connector_state *old_conn_state); | |
| 733 | 734 | void (*fdi_link_train)(struct intel_crtc *crtc, |
| 734 | 735 | const struct intel_crtc_state *crtc_state); |
| 735 | 736 | void (*init_clock_gating)(struct drm_i915_private *dev_priv); |
| @@ -884,6 +885,8 @@ struct intel_device_info { · 148 unmodified lines | ||
| 884 | 885 | /* Slice/subslice/EU info */ |
| 885 | 886 | struct sseu_dev_info sseu; |
| 886 | 887 | |
| 888 | + u32 cs_timestamp_frequency_khz; | |
| 889 | + | |
| 887 | 890 | struct color_luts { |
| 888 | 891 | u16 degamma_lut_size; |
| 889 | 892 | u16 gamma_lut_size; |
| @@ -911,6 +914,12 @@ struct i915_gpu_state { · 21 unmodified lines | ||
| 911 | 914 | struct intel_device_info device_info; |
| 912 | 915 | struct i915_params params; |
| 913 | 916 | |
| 917 | + struct i915_error_uc { | |
| 918 | + struct intel_uc_fw guc_fw; | |
| 919 | + struct intel_uc_fw huc_fw; | |
| 920 | + struct drm_i915_error_object *guc_log; | |
| 921 | + } uc; | |
| 922 | + | |
| 914 | 923 | /* Generic register state */ |
| 915 | 924 | u32 eir; |
| 916 | 925 | u32 pgtbl_er; |
| @@ -934,7 +943,6 @@ struct i915_gpu_state { · 17 unmodified lines | ||
| 934 | 943 | struct intel_overlay_error_state *overlay; |
| 935 | 944 | struct intel_display_error_state *display; |
| 936 | 945 | struct drm_i915_error_object *semaphore; |
| 937 | − struct drm_i915_error_object *guc_log; | |
| 938 | 946 | |
| 939 | 947 | struct drm_i915_error_engine { |
| 940 | 948 | int engine_id; |
| @@ -1386,7 +1394,6 @@ struct intel_gen6_power_mgmt { · 445 unmodified lines | ||
| 1386 | 1394 | struct intel_rps rps; |
| 1387 | 1395 | struct intel_rc6 rc6; |
| 1388 | 1396 | struct intel_llc_pstate llc_pstate; |
| 1389 | − struct delayed_work autoenable_work; | |
| 1390 | 1397 | }; |
| 1391 | 1398 | |
| 1392 | 1399 | /* defined intel_pm.c */ |
| @@ -1698,6 +1705,8 @@ enum modeset_restore { · 305 unmodified lines | ||
| 1698 | 1705 | #define DDC_PIN_D 0x06 |
| 1699 | 1706 | |
| 1700 | 1707 | struct ddi_vbt_port_info { |
| 1708 | + int max_tmds_clock; | |
| 1709 | + | |
| 1701 | 1710 | /* |
| 1702 | 1711 | * This is an index in the HDMI/DVI DDI buffer translation table. |
| 1703 | 1712 | * The special value HDMI_LEVEL_SHIFT_UNKNOWN means the VBT didn't |
| @@ -2228,6 +2237,7 @@ struct i915_oa_ops { · 524 unmodified lines | ||
| 2228 | 2237 | |
| 2229 | 2238 | struct intel_cdclk_state { |
| 2230 | 2239 | unsigned int cdclk, vco, ref; |
| 2240 | + u8 voltage_level; | |
| 2231 | 2241 | }; |
| 2232 | 2242 | |
| 2233 | 2243 | struct drm_i915_private { |
| @@ -2339,6 +2349,7 @@ struct drm_i915_private { · 105 unmodified lines | ||
| 2339 | 2349 | unsigned int max_dotclk_freq; |
| 2340 | 2350 | unsigned int rawclk_freq; |
| 2341 | 2351 | unsigned int hpll_freq; |
| 2352 | + unsigned int fdi_pll_freq; | |
| 2342 | 2353 | unsigned int czclk_freq; |
| 2343 | 2354 | |
| 2344 | 2355 | struct { |
| @@ -2415,6 +2426,8 @@ struct drm_i915_private { · 70 unmodified lines | ||
| 2415 | 2426 | unsigned int active_crtcs; |
| 2416 | 2427 | /* minimum acceptable cdclk for each pipe */ |
| 2417 | 2428 | int min_cdclk[I915_MAX_PIPES]; |
| 2429 | + /* minimum acceptable voltage level for each pipe */ | |
| 2430 | + u8 min_voltage_level[I915_MAX_PIPES]; | |
| 2418 | 2431 | |
| 2419 | 2432 | int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; |
| 2420 | 2433 | |
| @@ -3046,6 +3059,8 @@ intel_info(const struct drm_i915_private *dev_priv) · 625 unmodified lines | ||
| 3046 | 3059 | (INTEL_DEVID(dev_priv) & 0x00F0) == 0x00A0) |
| 3047 | 3060 | #define IS_CFL_GT2(dev_priv) (IS_COFFEELAKE(dev_priv) && \ |
| 3048 | 3061 | (dev_priv)->info.gt == 2) |
| 3062 | +#define IS_CFL_GT3(dev_priv) (IS_COFFEELAKE(dev_priv) && \ | |
| 3063 | + (dev_priv)->info.gt == 3) | |
| 3049 | 3064 | |
| 3050 | 3065 | #define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support) |
| 3051 | 3066 | |
| @@ -3137,6 +3152,8 @@ intel_info(const struct drm_i915_private *dev_priv) · 85 unmodified lines | ||
| 3137 | 3152 | |
| 3138 | 3153 | #define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \ |
| 3139 | 3154 | ((dev_priv)->info.has_logical_ring_contexts) |
| 3155 | +#define HAS_LOGICAL_RING_PREEMPTION(dev_priv) \ | |
| 3156 | + ((dev_priv)->info.has_logical_ring_preemption) | |
| 3140 | 3157 | #define USES_PPGTT(dev_priv) (i915_modparams.enable_ppgtt) |
| 3141 | 3158 | #define USES_FULL_PPGTT(dev_priv) (i915_modparams.enable_ppgtt >= 2) |
| 3142 | 3159 | #define USES_FULL_48BIT_PPGTT(dev_priv) (i915_modparams.enable_ppgtt == 3) |
| @@ -3315,7 +3332,9 @@ extern int i915_reset_engine(struct intel_engine_cs *engine, · 172 unmodified lines | ||
| 3315 | 3332 | unsigned int flags); |
| 3316 | 3333 | |
| 3317 | 3334 | extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv); |
| 3318 | −extern int intel_guc_reset(struct drm_i915_private *dev_priv); | |
| 3335 | +extern int intel_reset_guc(struct drm_i915_private *dev_priv); | |
| 3336 | +extern int intel_guc_reset_engine(struct intel_guc *guc, | |
| 3337 | + struct intel_engine_cs *engine); | |
| 3319 | 3338 | extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); |
| 3320 | 3339 | extern void intel_hangcheck_init(struct drm_i915_private *dev_priv); |
| 3321 | 3340 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); |
| @@ -4107,7 +4126,6 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv); · 785 unmodified lines | ||
| 4107 | 4126 | /* modesetting */ |
| 4108 | 4127 | extern void intel_modeset_init_hw(struct drm_device *dev); |
| 4109 | 4128 | extern int intel_modeset_init(struct drm_device *dev); |
| 4110 | −extern void intel_modeset_gem_init(struct drm_device *dev); | |
| 4111 | 4129 | extern void intel_modeset_cleanup(struct drm_device *dev); |
| 4112 | 4130 | extern int intel_connector_register(struct drm_connector *); |
| 4113 | 4131 | extern void intel_connector_unregister(struct drm_connector *); |
| @@ -4174,8 +4192,7 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, · 60 unmodified lines | ||
| 4174 | 4192 | enum dpio_phy phy); |
| 4175 | 4193 | bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, |
| 4176 | 4194 | enum dpio_phy phy); |
| 4177 | −uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, | |
| 4178 | − uint8_t lane_count); | |
| 4195 | +uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(uint8_t lane_count); | |
| 4179 | 4196 | void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, |
| 4180 | 4197 | uint8_t lane_lat_optim_mask); |
| 4181 | 4198 | uint8_t bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder); |
| @@ -4184,18 +4201,25 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, · 2 unmodified lines | ||
| 4184 | 4201 | u32 deemph_reg_value, u32 margin_reg_value, |
| 4185 | 4202 | bool uniq_trans_scale); |
| 4186 | 4203 | void chv_data_lane_soft_reset(struct intel_encoder *encoder, |
| 4204 | + const struct intel_crtc_state *crtc_state, | |
| 4187 | 4205 | bool reset); |
| 4188 | −void chv_phy_pre_pll_enable(struct intel_encoder *encoder); | |
| 4189 | −void chv_phy_pre_encoder_enable(struct intel_encoder *encoder); | |
| 4206 | +void chv_phy_pre_pll_enable(struct intel_encoder *encoder, | |
| 4207 | + const struct intel_crtc_state *crtc_state); | |
| 4208 | +void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, | |
| 4209 | + const struct intel_crtc_state *crtc_state); | |
| 4190 | 4210 | void chv_phy_release_cl2_override(struct intel_encoder *encoder); |
| 4191 | −void chv_phy_post_pll_disable(struct intel_encoder *encoder); | |
| 4211 | +void chv_phy_post_pll_disable(struct intel_encoder *encoder, | |
| 4212 | + const struct intel_crtc_state *old_crtc_state); | |
| 4192 | 4213 | |
| 4193 | 4214 | void vlv_set_phy_signal_level(struct intel_encoder *encoder, |
| 4194 | 4215 | u32 demph_reg_value, u32 preemph_reg_value, |
| 4195 | 4216 | u32 uniqtranscale_reg_value, u32 tx3_demph); |
| 4196 | −void vlv_phy_pre_pll_enable(struct intel_encoder *encoder); | |
| 4197 | −void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder); | |
| 4198 | −void vlv_phy_reset_lanes(struct intel_encoder *encoder); | |
| 4217 | +void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, | |
| 4218 | + const struct intel_crtc_state *crtc_state); | |
| 4219 | +void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, | |
| 4220 | + const struct intel_crtc_state *crtc_state); | |
| 4221 | +void vlv_phy_reset_lanes(struct intel_encoder *encoder, | |
| 4222 | + const struct intel_crtc_state *old_crtc_state); | |
| 4199 | 4223 | |
| 4200 | 4224 | int intel_gpu_freq(struct drm_i915_private *dev_priv, int val); |
| 4201 | 4225 | int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); |
| @@ -538,7 +538,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, · 537 unmodified lines | ||
| 538 | 538 | * @obj: i915 gem object |
| 539 | 539 | * @flags: how to wait (under a lock, for all rendering or just for writes etc) |
| 540 | 540 | * @timeout: how long to wait |
| 541 | − * @rps: client (user process) to charge for any waitboosting | |
| 541 | + * @rps_client: client (user process) to charge for any waitboosting | |
| 542 | 542 | */ |
| 543 | 543 | int |
| 544 | 544 | i915_gem_object_wait(struct drm_i915_gem_object *obj, |
| @@ -1619,7 +1619,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, · 1074 unmodified lines | ||
| 1619 | 1619 | if (err) |
| 1620 | 1620 | goto out; |
| 1621 | 1621 | |
| 1622 | − /* Flush and acquire obj->pages so that we are coherent through | |
| 1622 | + /* | |
| 1623 | + * Proxy objects do not control access to the backing storage, ergo | |
| 1624 | + * they cannot be used as a means to manipulate the cache domain | |
| 1625 | + * tracking for that backing storage. The proxy object is always | |
| 1626 | + * considered to be outside of any cache domain. | |
| 1627 | + */ | |
| 1628 | + if (i915_gem_object_is_proxy(obj)) { | |
| 1629 | + err = -ENXIO; | |
| 1630 | + goto out; | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + /* | |
| 1634 | + * Flush and acquire obj->pages so that we are coherent through | |
| 1623 | 1635 | * direct access in memory with previous cached writes through |
| 1624 | 1636 | * shmemfs and that our cache domain tracking remains valid. |
| 1625 | 1637 | * For example, if the obj->filp was moved to swap without us |
| @@ -1675,6 +1687,11 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, · 49 unmodified lines | ||
| 1675 | 1687 | if (!obj) |
| 1676 | 1688 | return -ENOENT; |
| 1677 | 1689 | |
| 1690 | + /* | |
| 1691 | + * Proxy objects are barred from CPU access, so there is no | |
| 1692 | + * need to ban sw_finish as it is a nop. | |
| 1693 | + */ | |
| 1694 | + | |
| 1678 | 1695 | /* Pinned buffers may be scanout, so flush the cache */ |
| 1679 | 1696 | i915_gem_object_flush_if_display(obj); |
| 1680 | 1697 | i915_gem_object_put(obj); |
| @@ -1725,7 +1742,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, · 44 unmodified lines | ||
| 1725 | 1742 | */ |
| 1726 | 1743 | if (!obj->base.filp) { |
| 1727 | 1744 | i915_gem_object_put(obj); |
| 1728 | − return -EINVAL; | |
| 1745 | + return -ENXIO; | |
| 1729 | 1746 | } |
| 1730 | 1747 | |
| 1731 | 1748 | addr = vm_mmap(obj->base.filp, 0, args->size, |
| @@ -2669,7 +2686,8 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, · 937 unmodified lines | ||
| 2669 | 2686 | void *ptr; |
| 2670 | 2687 | int ret; |
| 2671 | 2688 | |
| 2672 | − GEM_BUG_ON(!i915_gem_object_has_struct_page(obj)); | |
| 2689 | + if (unlikely(!i915_gem_object_has_struct_page(obj))) | |
| 2690 | + return ERR_PTR(-ENXIO); | |
| 2673 | 2691 | |
| 2674 | 2692 | ret = mutex_lock_interruptible(&obj->mm.lock); |
| 2675 | 2693 | if (ret) |
| @@ -2915,13 +2933,23 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) · 239 unmodified lines | ||
| 2915 | 2933 | * Prevent request submission to the hardware until we have |
| 2916 | 2934 | * completed the reset in i915_gem_reset_finish(). If a request |
| 2917 | 2935 | * is completed by one engine, it may then queue a request |
| 2918 | − * to a second via its engine->irq_tasklet *just* as we are | |
| 2936 | + * to a second via its execlists->tasklet *just* as we are | |
| 2919 | 2937 | * calling engine->init_hw() and also writing the ELSP. |
| 2920 | − * Turning off the engine->irq_tasklet until the reset is over | |
| 2938 | + * Turning off the execlists->tasklet until the reset is over | |
| 2921 | 2939 | * prevents the race. |
| 2922 | 2940 | */ |
| 2923 | − tasklet_kill(&engine->execlists.irq_tasklet); | |
| 2924 | − tasklet_disable(&engine->execlists.irq_tasklet); | |
| 2941 | + tasklet_kill(&engine->execlists.tasklet); | |
| 2942 | + tasklet_disable(&engine->execlists.tasklet); | |
| 2943 | + | |
| 2944 | + /* | |
| 2945 | + * We're using worker to queue preemption requests from the tasklet in | |
| 2946 | + * GuC submission mode. | |
| 2947 | + * Even though tasklet was disabled, we may still have a worker queued. | |
| 2948 | + * Let's make sure that all workers scheduled before disabling the | |
| 2949 | + * tasklet are completed before continuing with the reset. | |
| 2950 | + */ | |
| 2951 | + if (engine->i915->guc.preempt_wq) | |
| 2952 | + flush_workqueue(engine->i915->guc.preempt_wq); | |
| 2925 | 2953 | |
| 2926 | 2954 | if (engine->irq_seqno_barrier) |
| 2927 | 2955 | engine->irq_seqno_barrier(engine); |
| @@ -3100,7 +3128,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) · 172 unmodified lines | ||
| 3100 | 3128 | |
| 3101 | 3129 | void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) |
| 3102 | 3130 | { |
| 3103 | − tasklet_enable(&engine->execlists.irq_tasklet); | |
| 3131 | + tasklet_enable(&engine->execlists.tasklet); | |
| 3104 | 3132 | kthread_unpark(engine->breadcrumbs.signaler); |
| 3105 | 3133 | |
| 3106 | 3134 | intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL); |
| @@ -3278,13 +3306,20 @@ i915_gem_retire_work_handler(struct work_struct *work) · 171 unmodified lines | ||
| 3278 | 3306 | } |
| 3279 | 3307 | } |
| 3280 | 3308 | |
| 3309 | +static inline bool | |
| 3310 | +new_requests_since_last_retire(const struct drm_i915_private *i915) | |
| 3311 | +{ | |
| 3312 | + return (READ_ONCE(i915->gt.active_requests) || | |
| 3313 | + work_pending(&i915->gt.idle_work.work)); | |
| 3314 | +} | |
| 3315 | + | |
| 3281 | 3316 | static void |
| 3282 | 3317 | i915_gem_idle_work_handler(struct work_struct *work) |
| 3283 | 3318 | { |
| 3284 | 3319 | struct drm_i915_private *dev_priv = |
| 3285 | 3320 | container_of(work, typeof(*dev_priv), gt.idle_work.work); |
| 3286 | − struct drm_device *dev = &dev_priv->drm; | |
| 3287 | 3321 | bool rearm_hangcheck; |
| 3322 | + ktime_t end; | |
| 3288 | 3323 | |
| 3289 | 3324 | if (!READ_ONCE(dev_priv->gt.awake)) |
| 3290 | 3325 | return; |
| @@ -3293,14 +3328,21 @@ i915_gem_idle_work_handler(struct work_struct *work) · 2 unmodified lines | ||
| 3293 | 3328 | * Wait for last execlists context complete, but bail out in case a |
| 3294 | 3329 | * new request is submitted. |
| 3295 | 3330 | */ |
| 3296 | − wait_for(intel_engines_are_idle(dev_priv), 10); | |
| 3297 | − if (READ_ONCE(dev_priv->gt.active_requests)) | |
| 3298 | − return; | |
| 3331 | + end = ktime_add_ms(ktime_get(), 200); | |
| 3332 | + do { | |
| 3333 | + if (new_requests_since_last_retire(dev_priv)) | |
| 3334 | + return; | |
| 3335 | + | |
| 3336 | + if (intel_engines_are_idle(dev_priv)) | |
| 3337 | + break; | |
| 3338 | + | |
| 3339 | + usleep_range(100, 500); | |
| 3340 | + } while (ktime_before(ktime_get(), end)); | |
| 3299 | 3341 | |
| 3300 | 3342 | rearm_hangcheck = |
| 3301 | 3343 | cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); |
| 3302 | 3344 | |
| 3303 | − if (!mutex_trylock(&dev->struct_mutex)) { | |
| 3345 | + if (!mutex_trylock(&dev_priv->drm.struct_mutex)) { | |
| 3304 | 3346 | /* Currently busy, come back later */ |
| 3305 | 3347 | mod_delayed_work(dev_priv->wq, |
| 3306 | 3348 | &dev_priv->gt.idle_work, |
| @@ -3312,16 +3354,23 @@ i915_gem_idle_work_handler(struct work_struct *work) · 5 unmodified lines | ||
| 3312 | 3354 | * New request retired after this work handler started, extend active |
| 3313 | 3355 | * period until next instance of the work. |
| 3314 | 3356 | */ |
| 3315 | − if (work_pending(work)) | |
| 3316 | − goto out_unlock; | |
| 3317 | − | |
| 3318 | − if (dev_priv->gt.active_requests) | |
| 3357 | + if (new_requests_since_last_retire(dev_priv)) | |
| 3319 | 3358 | goto out_unlock; |
| 3320 | 3359 | |
| 3321 | − if (wait_for(intel_engines_are_idle(dev_priv), 10)) | |
| 3322 | − DRM_ERROR("Timeout waiting for engines to idle\n"); | |
| 3360 | + /* | |
| 3361 | + * Be paranoid and flush a concurrent interrupt to make sure | |
| 3362 | + * we don't reactivate any irq tasklets after parking. | |
| 3363 | + * | |
| 3364 | + * FIXME: Note that even though we have waited for execlists to be idle, | |
| 3365 | + * there may still be an in-flight interrupt even though the CSB | |
| 3366 | + * is now empty. synchronize_irq() makes sure that a residual interrupt | |
| 3367 | + * is completed before we continue, but it doesn't prevent the HW from | |
| 3368 | + * raising a spurious interrupt later. To complete the shield we should | |
| 3369 | + * coordinate disabling the CS irq with flushing the interrupts. | |
| 3370 | + */ | |
| 3371 | + synchronize_irq(dev_priv->drm.irq); | |
| 3323 | 3372 | |
| 3324 | − intel_engines_mark_idle(dev_priv); | |
| 3373 | + intel_engines_park(dev_priv); | |
| 3325 | 3374 | i915_gem_timelines_mark_idle(dev_priv); |
| 3326 | 3375 | |
| 3327 | 3376 | GEM_BUG_ON(!dev_priv->gt.awake); |
| @@ -3332,7 +3381,7 @@ i915_gem_idle_work_handler(struct work_struct *work) · 4 unmodified lines | ||
| 3332 | 3381 | gen6_rps_idle(dev_priv); |
| 3333 | 3382 | intel_runtime_pm_put(dev_priv); |
| 3334 | 3383 | out_unlock: |
| 3335 | − mutex_unlock(&dev->struct_mutex); | |
| 3384 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 3336 | 3385 | |
| 3337 | 3386 | out_rearm: |
| 3338 | 3387 | if (rearm_hangcheck) { |
| @@ -3857,6 +3906,15 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, · 518 unmodified lines | ||
| 3857 | 3906 | if (!obj) |
| 3858 | 3907 | return -ENOENT; |
| 3859 | 3908 | |
| 3909 | + /* | |
| 3910 | + * The caching mode of proxy object is handled by its generator, and | |
| 3911 | + * not allowed to be changed by userspace. | |
| 3912 | + */ | |
| 3913 | + if (i915_gem_object_is_proxy(obj)) { | |
| 3914 | + ret = -ENXIO; | |
| 3915 | + goto out; | |
| 3916 | + } | |
| 3917 | + | |
| 3860 | 3918 | if (obj->cache_level == level) |
| 3861 | 3919 | goto out; |
| 3862 | 3920 | |
| @@ -4662,14 +4720,16 @@ void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj) · 799 unmodified lines | ||
| 4662 | 4720 | i915_gem_object_put(obj); |
| 4663 | 4721 | } |
| 4664 | 4722 | |
| 4665 | −static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv) | |
| 4723 | +static void assert_kernel_context_is_current(struct drm_i915_private *i915) | |
| 4666 | 4724 | { |
| 4725 | + struct i915_gem_context *kernel_context = i915->kernel_context; | |
| 4667 | 4726 | struct intel_engine_cs *engine; |
| 4668 | 4727 | enum intel_engine_id id; |
| 4669 | 4728 | |
| 4670 | − for_each_engine(engine, dev_priv, id) | |
| 4671 | − GEM_BUG_ON(engine->last_retired_context && | |
| 4672 | − !i915_gem_context_is_kernel(engine->last_retired_context)); | |
| 4729 | + for_each_engine(engine, i915, id) { | |
| 4730 | + GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline->last_request)); | |
| 4731 | + GEM_BUG_ON(engine->last_retired_context != kernel_context); | |
| 4732 | + } | |
| 4673 | 4733 | } |
| 4674 | 4734 | |
| 4675 | 4735 | void i915_gem_sanitize(struct drm_i915_private *i915) |
| @@ -4773,23 +4833,40 @@ err_unlock: · 97 unmodified lines | ||
| 4773 | 4833 | return ret; |
| 4774 | 4834 | } |
| 4775 | 4835 | |
| 4776 | −void i915_gem_resume(struct drm_i915_private *dev_priv) | |
| 4836 | +void i915_gem_resume(struct drm_i915_private *i915) | |
| 4777 | 4837 | { |
| 4778 | − struct drm_device *dev = &dev_priv->drm; | |
| 4838 | + WARN_ON(i915->gt.awake); | |
| 4779 | 4839 | |
| 4780 | − WARN_ON(dev_priv->gt.awake); | |
| 4840 | + mutex_lock(&i915->drm.struct_mutex); | |
| 4841 | + intel_uncore_forcewake_get(i915, FORCEWAKE_ALL); | |
| 4781 | 4842 | |
| 4782 | − mutex_lock(&dev->struct_mutex); | |
| 4783 | − i915_gem_restore_gtt_mappings(dev_priv); | |
| 4784 | − i915_gem_restore_fences(dev_priv); | |
| 4843 | + i915_gem_restore_gtt_mappings(i915); | |
| 4844 | + i915_gem_restore_fences(i915); | |
| 4785 | 4845 | |
| 4786 | 4846 | /* As we didn't flush the kernel context before suspend, we cannot |
| 4787 | 4847 | * guarantee that the context image is complete. So let's just reset |
| 4788 | 4848 | * it and start again. |
| 4789 | 4849 | */ |
| 4790 | − dev_priv->gt.resume(dev_priv); | |
| 4850 | + i915->gt.resume(i915); | |
| 4791 | 4851 | |
| 4792 | − mutex_unlock(&dev->struct_mutex); | |
| 4852 | + if (i915_gem_init_hw(i915)) | |
| 4853 | + goto err_wedged; | |
| 4854 | + | |
| 4855 | + intel_guc_resume(i915); | |
| 4856 | + | |
| 4857 | + /* Always reload a context for powersaving. */ | |
| 4858 | + if (i915_gem_switch_to_kernel_context(i915)) | |
| 4859 | + goto err_wedged; | |
| 4860 | + | |
| 4861 | +out_unlock: | |
| 4862 | + intel_uncore_forcewake_put(i915, FORCEWAKE_ALL); | |
| 4863 | + mutex_unlock(&i915->drm.struct_mutex); | |
| 4864 | + return; | |
| 4865 | + | |
| 4866 | +err_wedged: | |
| 4867 | + DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); | |
| 4868 | + i915_gem_set_wedged(i915); | |
| 4869 | + goto out_unlock; | |
| 4793 | 4870 | } |
| 4794 | 4871 | |
| 4795 | 4872 | void i915_gem_init_swizzling(struct drm_i915_private *dev_priv) |
| @@ -4906,18 +4983,15 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) · 110 unmodified lines | ||
| 4906 | 4983 | goto out; |
| 4907 | 4984 | } |
| 4908 | 4985 | |
| 4909 | − /* Need to do basic initialisation of all rings first: */ | |
| 4910 | − ret = __i915_gem_restart_engines(dev_priv); | |
| 4911 | − if (ret) | |
| 4912 | − goto out; | |
| 4913 | − | |
| 4914 | − intel_mocs_init_l3cc_table(dev_priv); | |
| 4915 | − | |
| 4916 | 4986 | /* We can't enable contexts until all firmware is loaded */ |
| 4917 | 4987 | ret = intel_uc_init_hw(dev_priv); |
| 4918 | 4988 | if (ret) |
| 4919 | 4989 | goto out; |
| 4920 | 4990 | |
| 4991 | + intel_mocs_init_l3cc_table(dev_priv); | |
| 4992 | + | |
| 4993 | + /* Only when the HW is re-initialised, can we replay the requests */ | |
| 4994 | + ret = __i915_gem_restart_engines(dev_priv); | |
| 4921 | 4995 | out: |
| 4922 | 4996 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
| 4923 | 4997 | return ret; |
| @@ -4942,6 +5016,120 @@ bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) · 18 unmodified lines | ||
| 4942 | 5016 | return true; |
| 4943 | 5017 | } |
| 4944 | 5018 | |
| 5019 | +static int __intel_engines_record_defaults(struct drm_i915_private *i915) | |
| 5020 | +{ | |
| 5021 | + struct i915_gem_context *ctx; | |
| 5022 | + struct intel_engine_cs *engine; | |
| 5023 | + enum intel_engine_id id; | |
| 5024 | + int err; | |
| 5025 | + | |
| 5026 | + /* | |
| 5027 | + * As we reset the gpu during very early sanitisation, the current | |
| 5028 | + * register state on the GPU should reflect its defaults values. | |
| 5029 | + * We load a context onto the hw (with restore-inhibit), then switch | |
| 5030 | + * over to a second context to save that default register state. We | |
| 5031 | + * can then prime every new context with that state so they all start | |
| 5032 | + * from the same default HW values. | |
| 5033 | + */ | |
| 5034 | + | |
| 5035 | + ctx = i915_gem_context_create_kernel(i915, 0); | |
| 5036 | + if (IS_ERR(ctx)) | |
| 5037 | + return PTR_ERR(ctx); | |
| 5038 | + | |
| 5039 | + for_each_engine(engine, i915, id) { | |
| 5040 | + struct drm_i915_gem_request *rq; | |
| 5041 | + | |
| 5042 | + rq = i915_gem_request_alloc(engine, ctx); | |
| 5043 | + if (IS_ERR(rq)) { | |
| 5044 | + err = PTR_ERR(rq); | |
| 5045 | + goto out_ctx; | |
| 5046 | + } | |
| 5047 | + | |
| 5048 | + err = i915_switch_context(rq); | |
| 5049 | + if (engine->init_context) | |
| 5050 | + err = engine->init_context(rq); | |
| 5051 | + | |
| 5052 | + __i915_add_request(rq, true); | |
| 5053 | + if (err) | |
| 5054 | + goto err_active; | |
| 5055 | + } | |
| 5056 | + | |
| 5057 | + err = i915_gem_switch_to_kernel_context(i915); | |
| 5058 | + if (err) | |
| 5059 | + goto err_active; | |
| 5060 | + | |
| 5061 | + err = i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED); | |
| 5062 | + if (err) | |
| 5063 | + goto err_active; | |
| 5064 | + | |
| 5065 | + assert_kernel_context_is_current(i915); | |
| 5066 | + | |
| 5067 | + for_each_engine(engine, i915, id) { | |
| 5068 | + struct i915_vma *state; | |
| 5069 | + | |
| 5070 | + state = ctx->engine[id].state; | |
| 5071 | + if (!state) | |
| 5072 | + continue; | |
| 5073 | + | |
| 5074 | + /* | |
| 5075 | + * As we will hold a reference to the logical state, it will | |
| 5076 | + * not be torn down with the context, and importantly the | |
| 5077 | + * object will hold onto its vma (making it possible for a | |
| 5078 | + * stray GTT write to corrupt our defaults). Unmap the vma | |
| 5079 | + * from the GTT to prevent such accidents and reclaim the | |
| 5080 | + * space. | |
| 5081 | + */ | |
| 5082 | + err = i915_vma_unbind(state); | |
| 5083 | + if (err) | |
| 5084 | + goto err_active; | |
| 5085 | + | |
| 5086 | + err = i915_gem_object_set_to_cpu_domain(state->obj, false); | |
| 5087 | + if (err) | |
| 5088 | + goto err_active; | |
| 5089 | + | |
| 5090 | + engine->default_state = i915_gem_object_get(state->obj); | |
| 5091 | + } | |
| 5092 | + | |
| 5093 | + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { | |
| 5094 | + unsigned int found = intel_engines_has_context_isolation(i915); | |
| 5095 | + | |
| 5096 | + /* | |
| 5097 | + * Make sure that classes with multiple engine instances all | |
| 5098 | + * share the same basic configuration. | |
| 5099 | + */ | |
| 5100 | + for_each_engine(engine, i915, id) { | |
| 5101 | + unsigned int bit = BIT(engine->uabi_class); | |
| 5102 | + unsigned int expected = engine->default_state ? bit : 0; | |
| 5103 | + | |
| 5104 | + if ((found & bit) != expected) { | |
| 5105 | + DRM_ERROR("mismatching default context state for class %d on engine %s\n", | |
| 5106 | + engine->uabi_class, engine->name); | |
| 5107 | + } | |
| 5108 | + } | |
| 5109 | + } | |
| 5110 | + | |
| 5111 | +out_ctx: | |
| 5112 | + i915_gem_context_set_closed(ctx); | |
| 5113 | + i915_gem_context_put(ctx); | |
| 5114 | + return err; | |
| 5115 | + | |
| 5116 | +err_active: | |
| 5117 | + /* | |
| 5118 | + * If we have to abandon now, we expect the engines to be idle | |
| 5119 | + * and ready to be torn-down. First try to flush any remaining | |
| 5120 | + * request, ensure we are pointing at the kernel context and | |
| 5121 | + * then remove it. | |
| 5122 | + */ | |
| 5123 | + if (WARN_ON(i915_gem_switch_to_kernel_context(i915))) | |
| 5124 | + goto out_ctx; | |
| 5125 | + | |
| 5126 | + if (WARN_ON(i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED))) | |
| 5127 | + goto out_ctx; | |
| 5128 | + | |
| 5129 | + i915_gem_contexts_lost(i915); | |
| 5130 | + goto out_ctx; | |
| 5131 | +} | |
| 5132 | + | |
| 4945 | 5133 | int i915_gem_init(struct drm_i915_private *dev_priv) |
| 4946 | 5134 | { |
| 4947 | 5135 | int ret; |
| @@ -4991,7 +5179,25 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 43 unmodified lines | ||
| 4991 | 5179 | if (ret) |
| 4992 | 5180 | goto out_unlock; |
| 4993 | 5181 | |
| 5182 | + intel_init_gt_powersave(dev_priv); | |
| 5183 | + | |
| 4994 | 5184 | ret = i915_gem_init_hw(dev_priv); |
| 5185 | + if (ret) | |
| 5186 | + goto out_unlock; | |
| 5187 | + | |
| 5188 | + /* | |
| 5189 | + * Despite its name intel_init_clock_gating applies both display | |
| 5190 | + * clock gating workarounds; GT mmio workarounds and the occasional | |
| 5191 | + * GT power context workaround. Worse, sometimes it includes a context | |
| 5192 | + * register workaround which we need to apply before we record the | |
| 5193 | + * default HW state for all contexts. | |
| 5194 | + * | |
| 5195 | + * FIXME: break up the workarounds and apply them at the right time! | |
| 5196 | + */ | |
| 5197 | + intel_init_clock_gating(dev_priv); | |
| 5198 | + | |
| 5199 | + ret = __intel_engines_record_defaults(dev_priv); | |
| 5200 | +out_unlock: | |
| 4995 | 5201 | if (ret == -EIO) { |
| 4996 | 5202 | /* Allow engine initialisation to fail by marking the GPU as |
| 4997 | 5203 | * wedged. But we only want to do this where the GPU is angry, |
| @@ -5003,8 +5209,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 5 unmodified lines | ||
| 5003 | 5209 | } |
| 5004 | 5210 | ret = 0; |
| 5005 | 5211 | } |
| 5006 | − | |
| 5007 | −out_unlock: | |
| 5008 | 5212 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
| 5009 | 5213 | mutex_unlock(&dev_priv->drm.struct_mutex); |
| 5010 | 5214 | |
| @@ -5058,6 +5262,22 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv) · 47 unmodified lines | ||
| 5058 | 5262 | i915_gem_detect_bit_6_swizzle(dev_priv); |
| 5059 | 5263 | } |
| 5060 | 5264 | |
| 5265 | +static void i915_gem_init__mm(struct drm_i915_private *i915) | |
| 5266 | +{ | |
| 5267 | + spin_lock_init(&i915->mm.object_stat_lock); | |
| 5268 | + spin_lock_init(&i915->mm.obj_lock); | |
| 5269 | + spin_lock_init(&i915->mm.free_lock); | |
| 5270 | + | |
| 5271 | + init_llist_head(&i915->mm.free_list); | |
| 5272 | + | |
| 5273 | + INIT_LIST_HEAD(&i915->mm.unbound_list); | |
| 5274 | + INIT_LIST_HEAD(&i915->mm.bound_list); | |
| 5275 | + INIT_LIST_HEAD(&i915->mm.fence_list); | |
| 5276 | + INIT_LIST_HEAD(&i915->mm.userfault_list); | |
| 5277 | + | |
| 5278 | + INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); | |
| 5279 | +} | |
| 5280 | + | |
| 5061 | 5281 | int |
| 5062 | 5282 | i915_gem_load_init(struct drm_i915_private *dev_priv) |
| 5063 | 5283 | { |
| @@ -5099,15 +5319,7 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) · 35 unmodified lines | ||
| 5099 | 5319 | if (err) |
| 5100 | 5320 | goto err_priorities; |
| 5101 | 5321 | |
| 5102 | − INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work); | |
| 5103 | − | |
| 5104 | − spin_lock_init(&dev_priv->mm.obj_lock); | |
| 5105 | − spin_lock_init(&dev_priv->mm.free_lock); | |
| 5106 | − init_llist_head(&dev_priv->mm.free_list); | |
| 5107 | − INIT_LIST_HEAD(&dev_priv->mm.unbound_list); | |
| 5108 | − INIT_LIST_HEAD(&dev_priv->mm.bound_list); | |
| 5109 | − INIT_LIST_HEAD(&dev_priv->mm.fence_list); | |
| 5110 | − INIT_LIST_HEAD(&dev_priv->mm.userfault_list); | |
| 5322 | + i915_gem_init__mm(dev_priv); | |
| 5111 | 5323 | |
| 5112 | 5324 | INIT_DELAYED_WORK(&dev_priv->gt.retire_work, |
| 5113 | 5325 | i915_gem_retire_work_handler); |
| @@ -28,7 +28,11 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/bug.h> |
| 29 | 29 | |
| 30 | 30 | #ifdef CONFIG_DRM_I915_DEBUG_GEM |
| 31 | −#define GEM_BUG_ON(expr) BUG_ON(expr) | |
| 31 | +#define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ | |
| 32 | + printk(KERN_ERR "GEM_BUG_ON(%s)\n", __stringify(condition)); \ | |
| 33 | + BUG(); \ | |
| 34 | + } \ | |
| 35 | + } while(0) | |
| 32 | 36 | #define GEM_WARN_ON(expr) WARN_ON(expr) |
| 33 | 37 | |
| 34 | 38 | #define GEM_DEBUG_DECL(var) var |
| @@ -44,6 +48,12 @@ · 9 unmodified lines | ||
| 44 | 48 | #define GEM_DEBUG_BUG_ON(expr) |
| 45 | 49 | #endif |
| 46 | 50 | |
| 51 | +#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM) | |
| 52 | +#define GEM_TRACE(...) trace_printk(__VA_ARGS__) | |
| 53 | +#else | |
| 54 | +#define GEM_TRACE(...) do { } while (0) | |
| 55 | +#endif | |
| 56 | + | |
| 47 | 57 | #define I915_NUM_ENGINES 5 |
| 48 | 58 | |
| 49 | 59 | #endif /* __I915_GEM_H__ */ |
| @@ -418,8 +418,8 @@ out: · 417 unmodified lines | ||
| 418 | 418 | return ctx; |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | −static struct i915_gem_context * | |
| 422 | −create_kernel_context(struct drm_i915_private *i915, int prio) | |
| 421 | +struct i915_gem_context * | |
| 422 | +i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio) | |
| 423 | 423 | { |
| 424 | 424 | struct i915_gem_context *ctx; |
| 425 | 425 | |
| @@ -473,7 +473,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) · 47 unmodified lines | ||
| 473 | 473 | ida_init(&dev_priv->contexts.hw_ida); |
| 474 | 474 | |
| 475 | 475 | /* lowest priority; idle task */ |
| 476 | − ctx = create_kernel_context(dev_priv, I915_PRIORITY_MIN); | |
| 476 | + ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN); | |
| 477 | 477 | if (IS_ERR(ctx)) { |
| 478 | 478 | DRM_ERROR("Failed to create default global context\n"); |
| 479 | 479 | err = PTR_ERR(ctx); |
| @@ -487,7 +487,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) · 7 unmodified lines | ||
| 487 | 487 | dev_priv->kernel_context = ctx; |
| 488 | 488 | |
| 489 | 489 | /* highest priority; preempting task */ |
| 490 | − ctx = create_kernel_context(dev_priv, INT_MAX); | |
| 490 | + ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); | |
| 491 | 491 | if (IS_ERR(ctx)) { |
| 492 | 492 | DRM_ERROR("Failed to create default preempt context\n"); |
| 493 | 493 | err = PTR_ERR(ctx); |
| @@ -522,28 +522,6 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) · 28 unmodified lines | ||
| 522 | 522 | engine->context_unpin(engine, engine->last_retired_context); |
| 523 | 523 | engine->last_retired_context = NULL; |
| 524 | 524 | } |
| 525 | − | |
| 526 | − /* Force the GPU state to be restored on enabling */ | |
| 527 | − if (!i915_modparams.enable_execlists) { | |
| 528 | − struct i915_gem_context *ctx; | |
| 529 | − | |
| 530 | − list_for_each_entry(ctx, &dev_priv->contexts.list, link) { | |
| 531 | − if (!i915_gem_context_is_default(ctx)) | |
| 532 | − continue; | |
| 533 | − | |
| 534 | − for_each_engine(engine, dev_priv, id) | |
| 535 | − ctx->engine[engine->id].initialised = false; | |
| 536 | − | |
| 537 | − ctx->remap_slice = ALL_L3_SLICES(dev_priv); | |
| 538 | − } | |
| 539 | − | |
| 540 | − for_each_engine(engine, dev_priv, id) { | |
| 541 | − struct intel_context *kce = | |
| 542 | − &dev_priv->kernel_context->engine[engine->id]; | |
| 543 | − | |
| 544 | − kce->initialised = true; | |
| 545 | − } | |
| 546 | − } | |
| 547 | 525 | } |
| 548 | 526 | |
| 549 | 527 | void i915_gem_contexts_fini(struct drm_i915_private *i915) |
| @@ -718,9 +696,6 @@ static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt, · 168 unmodified lines | ||
| 718 | 696 | if (to->remap_slice) |
| 719 | 697 | return false; |
| 720 | 698 | |
| 721 | − if (!to->engine[RCS].initialised) | |
| 722 | − return false; | |
| 723 | − | |
| 724 | 699 | if (ppgtt && (intel_engine_flag(engine) & ppgtt->pd_dirty_rings)) |
| 725 | 700 | return false; |
| 726 | 701 | |
| @@ -795,11 +770,14 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) · 68 unmodified lines | ||
| 795 | 770 | return ret; |
| 796 | 771 | } |
| 797 | 772 | |
| 798 | − if (!to->engine[RCS].initialised || i915_gem_context_is_default(to)) | |
| 799 | − /* NB: If we inhibit the restore, the context is not allowed to | |
| 800 | − * die because future work may end up depending on valid address | |
| 801 | − * space. This means we must enforce that a page table load | |
| 802 | − * occur when this occurs. */ | |
| 773 | + if (i915_gem_context_is_kernel(to)) | |
| 774 | + /* | |
| 775 | + * The kernel context(s) is treated as pure scratch and is not | |
| 776 | + * expected to retain any state (as we sacrifice it during | |
| 777 | + * suspend and on resume it may be corrupted). This is ok, | |
| 778 | + * as nothing actually executes using the kernel context; it | |
| 779 | + * is purely used for flushing user contexts. | |
| 780 | + */ | |
| 803 | 781 | hw_flags = MI_RESTORE_INHIBIT; |
| 804 | 782 | else if (ppgtt && intel_engine_flag(engine) & ppgtt->pd_dirty_rings) |
| 805 | 783 | hw_flags = MI_FORCE_RESTORE; |
| @@ -843,15 +821,6 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) · 37 unmodified lines | ||
| 843 | 821 | to->remap_slice &= ~(1<<i); |
| 844 | 822 | } |
| 845 | 823 | |
| 846 | − if (!to->engine[RCS].initialised) { | |
| 847 | − if (engine->init_context) { | |
| 848 | − ret = engine->init_context(req); | |
| 849 | − if (ret) | |
| 850 | − return ret; | |
| 851 | − } | |
| 852 | − to->engine[RCS].initialised = true; | |
| 853 | − } | |
| 854 | − | |
| 855 | 824 | return 0; |
| 856 | 825 | } |
| 857 | 826 | |
| @@ -899,7 +868,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) · 41 unmodified lines | ||
| 899 | 868 | return do_rcs_switch(req); |
| 900 | 869 | } |
| 901 | 870 | |
| 902 | −static bool engine_has_kernel_context(struct intel_engine_cs *engine) | |
| 871 | +static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) | |
| 903 | 872 | { |
| 904 | 873 | struct i915_gem_timeline *timeline; |
| 905 | 874 | |
| @@ -915,8 +884,7 @@ static bool engine_has_kernel_context(struct intel_engine_cs *engine) · 9 unmodified lines | ||
| 915 | 884 | return false; |
| 916 | 885 | } |
| 917 | 886 | |
| 918 | − return (!engine->last_retired_context || | |
| 919 | − i915_gem_context_is_kernel(engine->last_retired_context)); | |
| 887 | + return intel_engine_has_kernel_context(engine); | |
| 920 | 888 | } |
| 921 | 889 | |
| 922 | 890 | int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) |
| @@ -933,7 +901,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) · 10 unmodified lines | ||
| 933 | 901 | struct drm_i915_gem_request *req; |
| 934 | 902 | int ret; |
| 935 | 903 | |
| 936 | − if (engine_has_kernel_context(engine)) | |
| 904 | + if (engine_has_idle_kernel_context(engine)) | |
| 937 | 905 | continue; |
| 938 | 906 | |
| 939 | 907 | req = i915_gem_request_alloc(engine, dev_priv->kernel_context); |
| @@ -157,7 +157,6 @@ struct i915_gem_context { · 156 unmodified lines | ||
| 157 | 157 | u32 *lrc_reg_state; |
| 158 | 158 | u64 lrc_desc; |
| 159 | 159 | int pin_count; |
| 160 | − bool initialised; | |
| 161 | 160 | } engine[I915_NUM_ENGINES]; |
| 162 | 161 | |
| 163 | 162 | /** ring_size: size for allocating the per-engine ring buffer */ |
| @@ -292,6 +291,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, · 128 unmodified lines | ||
| 292 | 291 | int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data, |
| 293 | 292 | struct drm_file *file); |
| 294 | 293 | |
| 294 | +struct i915_gem_context * | |
| 295 | +i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio); | |
| 296 | + | |
| 295 | 297 | static inline struct i915_gem_context * |
| 296 | 298 | i915_gem_context_get(struct i915_gem_context *ctx) |
| 297 | 299 | { |
| @@ -46,7 +46,7 @@ static bool ggtt_is_idle(struct drm_i915_private *i915) · 45 unmodified lines | ||
| 46 | 46 | return false; |
| 47 | 47 | |
| 48 | 48 | for_each_engine(engine, i915, id) { |
| 49 | − if (engine->last_retired_context != i915->kernel_context) | |
| 49 | + if (!intel_engine_has_kernel_context(engine)) | |
| 50 | 50 | return false; |
| 51 | 51 | } |
| 52 | 52 | |
| @@ -73,6 +73,7 @@ static int ggtt_flush(struct drm_i915_private *i915) · 20 unmodified lines | ||
| 73 | 73 | if (err) |
| 74 | 74 | return err; |
| 75 | 75 | |
| 76 | + GEM_BUG_ON(!ggtt_is_idle(i915)); | |
| 76 | 77 | return 0; |
| 77 | 78 | } |
| 78 | 79 | |
| @@ -216,6 +217,7 @@ search_again: · 137 unmodified lines | ||
| 216 | 217 | if (ret) |
| 217 | 218 | return ret; |
| 218 | 219 | |
| 220 | + cond_resched(); | |
| 219 | 221 | goto search_again; |
| 220 | 222 | } |
| 221 | 223 | |
| @@ -2074,23 +2074,27 @@ static struct drm_syncobj ** · 2073 unmodified lines | ||
| 2074 | 2074 | get_fence_array(struct drm_i915_gem_execbuffer2 *args, |
| 2075 | 2075 | struct drm_file *file) |
| 2076 | 2076 | { |
| 2077 | − const unsigned int nfences = args->num_cliprects; | |
| 2077 | + const unsigned long nfences = args->num_cliprects; | |
| 2078 | 2078 | struct drm_i915_gem_exec_fence __user *user; |
| 2079 | 2079 | struct drm_syncobj **fences; |
| 2080 | − unsigned int n; | |
| 2080 | + unsigned long n; | |
| 2081 | 2081 | int err; |
| 2082 | 2082 | |
| 2083 | 2083 | if (!(args->flags & I915_EXEC_FENCE_ARRAY)) |
| 2084 | 2084 | return NULL; |
| 2085 | 2085 | |
| 2086 | − if (nfences > SIZE_MAX / sizeof(*fences)) | |
| 2086 | + /* Check multiplication overflow for access_ok() and kvmalloc_array() */ | |
| 2087 | + BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); | |
| 2088 | + if (nfences > min_t(unsigned long, | |
| 2089 | + ULONG_MAX / sizeof(*user), | |
| 2090 | + SIZE_MAX / sizeof(*fences))) | |
| 2087 | 2091 | return ERR_PTR(-EINVAL); |
| 2088 | 2092 | |
| 2089 | 2093 | user = u64_to_user_ptr(args->cliprects_ptr); |
| 2090 | − if (!access_ok(VERIFY_READ, user, nfences * 2 * sizeof(u32))) | |
| 2094 | + if (!access_ok(VERIFY_READ, user, nfences * sizeof(*user))) | |
| 2091 | 2095 | return ERR_PTR(-EFAULT); |
| 2092 | 2096 | |
| 2093 | − fences = kvmalloc_array(args->num_cliprects, sizeof(*fences), | |
| 2097 | + fences = kvmalloc_array(nfences, sizeof(*fences), | |
| 2094 | 2098 | __GFP_NOWARN | GFP_KERNEL); |
| 2095 | 2099 | if (!fences) |
| 2096 | 2100 | return ERR_PTR(-ENOMEM); |
| @@ -2447,6 +2451,26 @@ err_in_fence: · 350 unmodified lines | ||
| 2447 | 2451 | return err; |
| 2448 | 2452 | } |
| 2449 | 2453 | |
| 2454 | +static size_t eb_element_size(void) | |
| 2455 | +{ | |
| 2456 | + return (sizeof(struct drm_i915_gem_exec_object2) + | |
| 2457 | + sizeof(struct i915_vma *) + | |
| 2458 | + sizeof(unsigned int)); | |
| 2459 | +} | |
| 2460 | + | |
| 2461 | +static bool check_buffer_count(size_t count) | |
| 2462 | +{ | |
| 2463 | + const size_t sz = eb_element_size(); | |
| 2464 | + | |
| 2465 | + /* | |
| 2466 | + * When using LUT_HANDLE, we impose a limit of INT_MAX for the lookup | |
| 2467 | + * array size (see eb_create()). Otherwise, we can accept an array as | |
| 2468 | + * large as can be addressed (though use large arrays at your peril)! | |
| 2469 | + */ | |
| 2470 | + | |
| 2471 | + return !(count < 1 || count > INT_MAX || count > SIZE_MAX / sz - 1); | |
| 2472 | +} | |
| 2473 | + | |
| 2450 | 2474 | /* |
| 2451 | 2475 | * Legacy execbuffer just creates an exec2 list from the original exec object |
| 2452 | 2476 | * list array and passes it to the real function. |
| @@ -2455,18 +2479,16 @@ int · 2 unmodified lines | ||
| 2455 | 2479 | i915_gem_execbuffer(struct drm_device *dev, void *data, |
| 2456 | 2480 | struct drm_file *file) |
| 2457 | 2481 | { |
| 2458 | − const size_t sz = (sizeof(struct drm_i915_gem_exec_object2) + | |
| 2459 | − sizeof(struct i915_vma *) + | |
| 2460 | − sizeof(unsigned int)); | |
| 2461 | 2482 | struct drm_i915_gem_execbuffer *args = data; |
| 2462 | 2483 | struct drm_i915_gem_execbuffer2 exec2; |
| 2463 | 2484 | struct drm_i915_gem_exec_object *exec_list = NULL; |
| 2464 | 2485 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
| 2486 | + const size_t count = args->buffer_count; | |
| 2465 | 2487 | unsigned int i; |
| 2466 | 2488 | int err; |
| 2467 | 2489 | |
| 2468 | − if (args->buffer_count < 1 || args->buffer_count > SIZE_MAX / sz - 1) { | |
| 2469 | − DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count); | |
| 2490 | + if (!check_buffer_count(count)) { | |
| 2491 | + DRM_DEBUG("execbuf2 with %zd buffers\n", count); | |
| 2470 | 2492 | return -EINVAL; |
| 2471 | 2493 | } |
| 2472 | 2494 | |
| @@ -2485,9 +2507,9 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, · 12 unmodified lines | ||
| 2485 | 2507 | return -EINVAL; |
| 2486 | 2508 | |
| 2487 | 2509 | /* Copy in the exec list from userland */ |
| 2488 | − exec_list = kvmalloc_array(args->buffer_count, sizeof(*exec_list), | |
| 2510 | + exec_list = kvmalloc_array(count, sizeof(*exec_list), | |
| 2489 | 2511 | __GFP_NOWARN | GFP_KERNEL); |
| 2490 | − exec2_list = kvmalloc_array(args->buffer_count + 1, sz, | |
| 2512 | + exec2_list = kvmalloc_array(count + 1, eb_element_size(), | |
| 2491 | 2513 | __GFP_NOWARN | GFP_KERNEL); |
| 2492 | 2514 | if (exec_list == NULL || exec2_list == NULL) { |
| 2493 | 2515 | DRM_DEBUG("Failed to allocate exec list for %d buffers\n", |
| @@ -2498,7 +2520,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, · 4 unmodified lines | ||
| 2498 | 2520 | } |
| 2499 | 2521 | err = copy_from_user(exec_list, |
| 2500 | 2522 | u64_to_user_ptr(args->buffers_ptr), |
| 2501 | − sizeof(*exec_list) * args->buffer_count); | |
| 2523 | + sizeof(*exec_list) * count); | |
| 2502 | 2524 | if (err) { |
| 2503 | 2525 | DRM_DEBUG("copy %d exec entries failed %d\n", |
| 2504 | 2526 | args->buffer_count, err); |
| @@ -2548,16 +2570,14 @@ int · 43 unmodified lines | ||
| 2548 | 2570 | i915_gem_execbuffer2(struct drm_device *dev, void *data, |
| 2549 | 2571 | struct drm_file *file) |
| 2550 | 2572 | { |
| 2551 | − const size_t sz = (sizeof(struct drm_i915_gem_exec_object2) + | |
| 2552 | − sizeof(struct i915_vma *) + | |
| 2553 | − sizeof(unsigned int)); | |
| 2554 | 2573 | struct drm_i915_gem_execbuffer2 *args = data; |
| 2555 | 2574 | struct drm_i915_gem_exec_object2 *exec2_list; |
| 2556 | 2575 | struct drm_syncobj **fences = NULL; |
| 2576 | + const size_t count = args->buffer_count; | |
| 2557 | 2577 | int err; |
| 2558 | 2578 | |
| 2559 | − if (args->buffer_count < 1 || args->buffer_count > SIZE_MAX / sz - 1) { | |
| 2560 | − DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count); | |
| 2579 | + if (!check_buffer_count(count)) { | |
| 2580 | + DRM_DEBUG("execbuf2 with %zd buffers\n", count); | |
| 2561 | 2581 | return -EINVAL; |
| 2562 | 2582 | } |
| 2563 | 2583 | |
| @@ -2565,17 +2585,17 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, · 1 unmodified line | ||
| 2565 | 2585 | return -EINVAL; |
| 2566 | 2586 | |
| 2567 | 2587 | /* Allocate an extra slot for use by the command parser */ |
| 2568 | − exec2_list = kvmalloc_array(args->buffer_count + 1, sz, | |
| 2588 | + exec2_list = kvmalloc_array(count + 1, eb_element_size(), | |
| 2569 | 2589 | __GFP_NOWARN | GFP_KERNEL); |
| 2570 | 2590 | if (exec2_list == NULL) { |
| 2571 | − DRM_DEBUG("Failed to allocate exec list for %d buffers\n", | |
| 2572 | − args->buffer_count); | |
| 2591 | + DRM_DEBUG("Failed to allocate exec list for %zd buffers\n", | |
| 2592 | + count); | |
| 2573 | 2593 | return -ENOMEM; |
| 2574 | 2594 | } |
| 2575 | 2595 | if (copy_from_user(exec2_list, |
| 2576 | 2596 | u64_to_user_ptr(args->buffers_ptr), |
| 2577 | − sizeof(*exec2_list) * args->buffer_count)) { | |
| 2578 | − DRM_DEBUG("copy %d exec entries failed\n", args->buffer_count); | |
| 2597 | + sizeof(*exec2_list) * count)) { | |
| 2598 | + DRM_DEBUG("copy %zd exec entries failed\n", count); | |
| 2579 | 2599 | kvfree(exec2_list); |
| 2580 | 2600 | return -EFAULT; |
| 2581 | 2601 | } |
| @@ -454,6 +454,14 @@ static void vm_free_pages_release(struct i915_address_space *vm, · 453 unmodified lines | ||
| 454 | 454 | |
| 455 | 455 | static void vm_free_page(struct i915_address_space *vm, struct page *page) |
| 456 | 456 | { |
| 457 | + /* | |
| 458 | + * On !llc, we need to change the pages back to WB. We only do so | |
| 459 | + * in bulk, so we rarely need to change the page attributes here, | |
| 460 | + * but doing so requires a stop_machine() from deep inside arch/x86/mm. | |
| 461 | + * To make detection of the possible sleep more likely, use an | |
| 462 | + * unconditional might_sleep() for everybody. | |
| 463 | + */ | |
| 464 | + might_sleep(); | |
| 457 | 465 | if (!pagevec_add(&vm->free_pages, page)) |
| 458 | 466 | vm_free_pages_release(vm, false); |
| 459 | 467 | } |
| @@ -2248,35 +2256,62 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv) · 1788 unmodified lines | ||
| 2248 | 2256 | return IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_vtd_active(); |
| 2249 | 2257 | } |
| 2250 | 2258 | |
| 2251 | −void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) | |
| 2259 | +static void gen6_check_and_clear_faults(struct drm_i915_private *dev_priv) | |
| 2252 | 2260 | { |
| 2253 | 2261 | struct intel_engine_cs *engine; |
| 2254 | 2262 | enum intel_engine_id id; |
| 2255 | − | |
| 2256 | − if (INTEL_INFO(dev_priv)->gen < 6) | |
| 2257 | − return; | |
| 2263 | + u32 fault; | |
| 2258 | 2264 | |
| 2259 | 2265 | for_each_engine(engine, dev_priv, id) { |
| 2260 | − u32 fault_reg; | |
| 2261 | − fault_reg = I915_READ(RING_FAULT_REG(engine)); | |
| 2262 | − if (fault_reg & RING_FAULT_VALID) { | |
| 2266 | + fault = I915_READ(RING_FAULT_REG(engine)); | |
| 2267 | + if (fault & RING_FAULT_VALID) { | |
| 2263 | 2268 | DRM_DEBUG_DRIVER("Unexpected fault\n" |
| 2264 | 2269 | "\tAddr: 0x%08lx\n" |
| 2265 | 2270 | "\tAddress space: %s\n" |
| 2266 | 2271 | "\tSource ID: %d\n" |
| 2267 | 2272 | "\tType: %d\n", |
| 2268 | − fault_reg & PAGE_MASK, | |
| 2269 | − fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", | |
| 2270 | − RING_FAULT_SRCID(fault_reg), | |
| 2271 | − RING_FAULT_FAULT_TYPE(fault_reg)); | |
| 2273 | + fault & PAGE_MASK, | |
| 2274 | + fault & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", | |
| 2275 | + RING_FAULT_SRCID(fault), | |
| 2276 | + RING_FAULT_FAULT_TYPE(fault)); | |
| 2272 | 2277 | I915_WRITE(RING_FAULT_REG(engine), |
| 2273 | − fault_reg & ~RING_FAULT_VALID); | |
| 2278 | + fault & ~RING_FAULT_VALID); | |
| 2274 | 2279 | } |
| 2275 | 2280 | } |
| 2276 | 2281 | |
| 2277 | − /* Engine specific init may not have been done till this point. */ | |
| 2278 | − if (dev_priv->engine[RCS]) | |
| 2279 | − POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS])); | |
| 2282 | + POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS])); | |
| 2283 | +} | |
| 2284 | + | |
| 2285 | +static void gen8_check_and_clear_faults(struct drm_i915_private *dev_priv) | |
| 2286 | +{ | |
| 2287 | + u32 fault = I915_READ(GEN8_RING_FAULT_REG); | |
| 2288 | + | |
| 2289 | + if (fault & RING_FAULT_VALID) { | |
| 2290 | + DRM_DEBUG_DRIVER("Unexpected fault\n" | |
| 2291 | + "\tAddr: 0x%08lx\n" | |
| 2292 | + "\tEngine ID: %d\n" | |
| 2293 | + "\tSource ID: %d\n" | |
| 2294 | + "\tType: %d\n", | |
| 2295 | + fault & PAGE_MASK, | |
| 2296 | + GEN8_RING_FAULT_ENGINE_ID(fault), | |
| 2297 | + RING_FAULT_SRCID(fault), | |
| 2298 | + RING_FAULT_FAULT_TYPE(fault)); | |
| 2299 | + I915_WRITE(GEN8_RING_FAULT_REG, | |
| 2300 | + fault & ~RING_FAULT_VALID); | |
| 2301 | + } | |
| 2302 | + | |
| 2303 | + POSTING_READ(GEN8_RING_FAULT_REG); | |
| 2304 | +} | |
| 2305 | + | |
| 2306 | +void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) | |
| 2307 | +{ | |
| 2308 | + /* From GEN8 onwards we only have one 'All Engine Fault Register' */ | |
| 2309 | + if (INTEL_GEN(dev_priv) >= 8) | |
| 2310 | + gen8_check_and_clear_faults(dev_priv); | |
| 2311 | + else if (INTEL_GEN(dev_priv) >= 6) | |
| 2312 | + gen6_check_and_clear_faults(dev_priv); | |
| 2313 | + else | |
| 2314 | + return; | |
| 2280 | 2315 | } |
| 2281 | 2316 | |
| 2282 | 2317 | void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv) |
| @@ -3041,7 +3076,7 @@ const struct intel_ppat_entry * · 758 unmodified lines | ||
| 3041 | 3076 | intel_ppat_get(struct drm_i915_private *i915, u8 value) |
| 3042 | 3077 | { |
| 3043 | 3078 | struct intel_ppat *ppat = &i915->ppat; |
| 3044 | − struct intel_ppat_entry *entry; | |
| 3079 | + struct intel_ppat_entry *entry = NULL; | |
| 3045 | 3080 | unsigned int scanned, best_score; |
| 3046 | 3081 | int i; |
| 3047 | 3082 | |
| @@ -3064,7 +3099,7 @@ intel_ppat_get(struct drm_i915_private *i915, u8 value) · 16 unmodified lines | ||
| 3064 | 3099 | } |
| 3065 | 3100 | |
| 3066 | 3101 | if (scanned == ppat->max_entries) { |
| 3067 | − if (!best_score) | |
| 3102 | + if (!entry) | |
| 3068 | 3103 | return ERR_PTR(-ENOSPC); |
| 3069 | 3104 | |
| 3070 | 3105 | kref_get(&entry->ref); |
| @@ -3171,12 +3206,6 @@ static void cnl_setup_private_ppat(struct intel_ppat *ppat) · 100 unmodified lines | ||
| 3171 | 3206 | ppat->match = bdw_private_pat_match; |
| 3172 | 3207 | ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); |
| 3173 | 3208 | |
| 3174 | − /* XXX: spec is unclear if this is still needed for CNL+ */ | |
| 3175 | − if (!USES_PPGTT(ppat->i915)) { | |
| 3176 | − __alloc_ppat_entry(ppat, 0, GEN8_PPAT_UC); | |
| 3177 | − return; | |
| 3178 | − } | |
| 3179 | − | |
| 3180 | 3209 | __alloc_ppat_entry(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); |
| 3181 | 3210 | __alloc_ppat_entry(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); |
| 3182 | 3211 | __alloc_ppat_entry(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); |
| @@ -53,8 +53,9 @@ struct i915_lut_handle { · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | struct drm_i915_gem_object_ops { |
| 55 | 55 | unsigned int flags; |
| 56 | −#define I915_GEM_OBJECT_HAS_STRUCT_PAGE BIT(0) | |
| 57 | −#define I915_GEM_OBJECT_IS_SHRINKABLE BIT(1) | |
| 56 | +#define I915_GEM_OBJECT_HAS_STRUCT_PAGE BIT(0) | |
| 57 | +#define I915_GEM_OBJECT_IS_SHRINKABLE BIT(1) | |
| 58 | +#define I915_GEM_OBJECT_IS_PROXY BIT(2) | |
| 58 | 59 | |
| 59 | 60 | /* Interface between the GEM object and its backing storage. |
| 60 | 61 | * get_pages() is called once prior to the use of the associated set |
| @@ -361,6 +362,12 @@ i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj) · 300 unmodified lines | ||
| 361 | 362 | return obj->ops->flags & I915_GEM_OBJECT_IS_SHRINKABLE; |
| 362 | 363 | } |
| 363 | 364 | |
| 365 | +static inline bool | |
| 366 | +i915_gem_object_is_proxy(const struct drm_i915_gem_object *obj) | |
| 367 | +{ | |
| 368 | + return obj->ops->flags & I915_GEM_OBJECT_IS_PROXY; | |
| 369 | +} | |
| 370 | + | |
| 364 | 371 | static inline bool |
| 365 | 372 | i915_gem_object_is_active(const struct drm_i915_gem_object *obj) |
| 366 | 373 | { |
| @@ -26,10 +26,12 @@ · 25 unmodified lines | ||
| 26 | 26 | */ |
| 27 | 27 | |
| 28 | 28 | #include "i915_drv.h" |
| 29 | +#include "i915_gem_render_state.h" | |
| 29 | 30 | #include "intel_renderstate.h" |
| 30 | 31 | |
| 31 | 32 | struct intel_render_state { |
| 32 | 33 | const struct intel_renderstate_rodata *rodata; |
| 34 | + struct drm_i915_gem_object *obj; | |
| 33 | 35 | struct i915_vma *vma; |
| 34 | 36 | u32 batch_offset; |
| 35 | 37 | u32 batch_size; |
| @@ -40,6 +42,9 @@ struct intel_render_state { · 4 unmodified lines | ||
| 40 | 42 | static const struct intel_renderstate_rodata * |
| 41 | 43 | render_state_get_rodata(const struct intel_engine_cs *engine) |
| 42 | 44 | { |
| 45 | + if (engine->id != RCS) | |
| 46 | + return NULL; | |
| 47 | + | |
| 43 | 48 | switch (INTEL_GEN(engine->i915)) { |
| 44 | 49 | case 6: |
| 45 | 50 | return &gen6_null_state; |
| @@ -74,17 +79,16 @@ static int render_state_setup(struct intel_render_state *so, · 28 unmodified lines | ||
| 74 | 79 | struct drm_i915_private *i915) |
| 75 | 80 | { |
| 76 | 81 | const struct intel_renderstate_rodata *rodata = so->rodata; |
| 77 | − struct drm_i915_gem_object *obj = so->vma->obj; | |
| 78 | 82 | unsigned int i = 0, reloc_index = 0; |
| 79 | 83 | unsigned int needs_clflush; |
| 80 | 84 | u32 *d; |
| 81 | 85 | int ret; |
| 82 | 86 | |
| 83 | − ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); | |
| 87 | + ret = i915_gem_obj_prepare_shmem_write(so->obj, &needs_clflush); | |
| 84 | 88 | if (ret) |
| 85 | 89 | return ret; |
| 86 | 90 | |
| 87 | − d = kmap_atomic(i915_gem_object_get_dirty_page(obj, 0)); | |
| 91 | + d = kmap_atomic(i915_gem_object_get_dirty_page(so->obj, 0)); | |
| 88 | 92 | |
| 89 | 93 | while (i < rodata->batch_items) { |
| 90 | 94 | u32 s = rodata->batch[i]; |
| @@ -112,7 +116,7 @@ static int render_state_setup(struct intel_render_state *so, · 21 unmodified lines | ||
| 112 | 116 | goto err; |
| 113 | 117 | } |
| 114 | 118 | |
| 115 | − so->batch_offset = so->vma->node.start; | |
| 119 | + so->batch_offset = i915_ggtt_offset(so->vma); | |
| 116 | 120 | so->batch_size = rodata->batch_items * sizeof(u32); |
| 117 | 121 | |
| 118 | 122 | while (i % CACHELINE_DWORDS) |
| @@ -160,9 +164,9 @@ static int render_state_setup(struct intel_render_state *so, · 41 unmodified lines | ||
| 160 | 164 | drm_clflush_virt_range(d, i * sizeof(u32)); |
| 161 | 165 | kunmap_atomic(d); |
| 162 | 166 | |
| 163 | − ret = i915_gem_object_set_to_gtt_domain(obj, false); | |
| 167 | + ret = i915_gem_object_set_to_gtt_domain(so->obj, false); | |
| 164 | 168 | out: |
| 165 | − i915_gem_obj_finish_shmem_access(obj); | |
| 169 | + i915_gem_obj_finish_shmem_access(so->obj); | |
| 166 | 170 | return ret; |
| 167 | 171 | |
| 168 | 172 | err: |
| @@ -173,112 +177,61 @@ err: · 4 unmodified lines | ||
| 173 | 177 | |
| 174 | 178 | #undef OUT_BATCH |
| 175 | 179 | |
| 176 | −int i915_gem_render_state_init(struct intel_engine_cs *engine) | |
| 180 | +int i915_gem_render_state_emit(struct drm_i915_gem_request *rq) | |
| 177 | 181 | { |
| 178 | − struct intel_render_state *so; | |
| 179 | − const struct intel_renderstate_rodata *rodata; | |
| 180 | − struct drm_i915_gem_object *obj; | |
| 181 | − int ret; | |
| 182 | + struct intel_engine_cs *engine = rq->engine; | |
| 183 | + struct intel_render_state so = {}; /* keep the compiler happy */ | |
| 184 | + int err; | |
| 182 | 185 | |
| 183 | − if (engine->id != RCS) | |
| 186 | + so.rodata = render_state_get_rodata(engine); | |
| 187 | + if (!so.rodata) | |
| 184 | 188 | return 0; |
| 185 | 189 | |
| 186 | − rodata = render_state_get_rodata(engine); | |
| 187 | − if (!rodata) | |
| 188 | − return 0; | |
| 189 | − | |
| 190 | − if (rodata->batch_items * 4 > PAGE_SIZE) | |
| 190 | + if (so.rodata->batch_items * 4 > PAGE_SIZE) | |
| 191 | 191 | return -EINVAL; |
| 192 | 192 | |
| 193 | − so = kmalloc(sizeof(*so), GFP_KERNEL); | |
| 194 | − if (!so) | |
| 195 | − return -ENOMEM; | |
| 196 | − | |
| 197 | − obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); | |
| 198 | − if (IS_ERR(obj)) { | |
| 199 | − ret = PTR_ERR(obj); | |
| 200 | − goto err_free; | |
| 201 | − } | |
| 193 | + so.obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); | |
| 194 | + if (IS_ERR(so.obj)) | |
| 195 | + return PTR_ERR(so.obj); | |
| 202 | 196 | |
| 203 | − so->vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); | |
| 204 | − if (IS_ERR(so->vma)) { | |
| 205 | − ret = PTR_ERR(so->vma); | |
| 197 | + so.vma = i915_vma_instance(so.obj, &engine->i915->ggtt.base, NULL); | |
| 198 | + if (IS_ERR(so.vma)) { | |
| 199 | + err = PTR_ERR(so.vma); | |
| 206 | 200 | goto err_obj; |
| 207 | 201 | } |
| 208 | 202 | |
| 209 | − so->rodata = rodata; | |
| 210 | − engine->render_state = so; | |
| 211 | − return 0; | |
| 212 | − | |
| 213 | −err_obj: | |
| 214 | − i915_gem_object_put(obj); | |
| 215 | −err_free: | |
| 216 | − kfree(so); | |
| 217 | − return ret; | |
| 218 | −} | |
| 219 | − | |
| 220 | −int i915_gem_render_state_emit(struct drm_i915_gem_request *req) | |
| 221 | −{ | |
| 222 | − struct intel_render_state *so; | |
| 223 | − int ret; | |
| 224 | − | |
| 225 | − lockdep_assert_held(&req->i915->drm.struct_mutex); | |
| 226 | − | |
| 227 | − so = req->engine->render_state; | |
| 228 | − if (!so) | |
| 229 | − return 0; | |
| 230 | − | |
| 231 | − /* Recreate the page after shrinking */ | |
| 232 | − if (!i915_gem_object_has_pages(so->vma->obj)) | |
| 233 | − so->batch_offset = -1; | |
| 234 | − | |
| 235 | − ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); | |
| 236 | − if (ret) | |
| 237 | − return ret; | |
| 203 | + err = i915_vma_pin(so.vma, 0, 0, PIN_GLOBAL | PIN_HIGH); | |
| 204 | + if (err) | |
| 205 | + goto err_vma; | |
| 238 | 206 | |
| 239 | − if (so->vma->node.start != so->batch_offset) { | |
| 240 | − ret = render_state_setup(so, req->i915); | |
| 241 | − if (ret) | |
| 242 | − goto err_unpin; | |
| 243 | − } | |
| 207 | + err = render_state_setup(&so, rq->i915); | |
| 208 | + if (err) | |
| 209 | + goto err_unpin; | |
| 244 | 210 | |
| 245 | − ret = req->engine->emit_flush(req, EMIT_INVALIDATE); | |
| 246 | − if (ret) | |
| 211 | + err = engine->emit_flush(rq, EMIT_INVALIDATE); | |
| 212 | + if (err) | |
| 247 | 213 | goto err_unpin; |
| 248 | 214 | |
| 249 | − ret = req->engine->emit_bb_start(req, | |
| 250 | − so->batch_offset, so->batch_size, | |
| 251 | − I915_DISPATCH_SECURE); | |
| 252 | − if (ret) | |
| 215 | + err = engine->emit_bb_start(rq, | |
| 216 | + so.batch_offset, so.batch_size, | |
| 217 | + I915_DISPATCH_SECURE); | |
| 218 | + if (err) | |
| 253 | 219 | goto err_unpin; |
| 254 | 220 | |
| 255 | − if (so->aux_size > 8) { | |
| 256 | − ret = req->engine->emit_bb_start(req, | |
| 257 | − so->aux_offset, so->aux_size, | |
| 258 | − I915_DISPATCH_SECURE); | |
| 259 | − if (ret) | |
| 221 | + if (so.aux_size > 8) { | |
| 222 | + err = engine->emit_bb_start(rq, | |
| 223 | + so.aux_offset, so.aux_size, | |
| 224 | + I915_DISPATCH_SECURE); | |
| 225 | + if (err) | |
| 260 | 226 | goto err_unpin; |
| 261 | 227 | } |
| 262 | 228 | |
| 263 | − i915_vma_move_to_active(so->vma, req, 0); | |
| 229 | + i915_vma_move_to_active(so.vma, rq, 0); | |
| 264 | 230 | err_unpin: |
| 265 | − i915_vma_unpin(so->vma); | |
| 266 | − return ret; | |
| 267 | −} | |
| 268 | − | |
| 269 | −void i915_gem_render_state_fini(struct intel_engine_cs *engine) | |
| 270 | −{ | |
| 271 | − struct intel_render_state *so; | |
| 272 | − struct drm_i915_gem_object *obj; | |
| 273 | − | |
| 274 | − so = fetch_and_zero(&engine->render_state); | |
| 275 | − if (!so) | |
| 276 | − return; | |
| 277 | − | |
| 278 | − obj = so->vma->obj; | |
| 279 | − | |
| 280 | − i915_vma_close(so->vma); | |
| 281 | − __i915_gem_object_release_unless_active(obj); | |
| 282 | − | |
| 283 | − kfree(so); | |
| 231 | + i915_vma_unpin(so.vma); | |
| 232 | +err_vma: | |
| 233 | + i915_vma_close(so.vma); | |
| 234 | +err_obj: | |
| 235 | + __i915_gem_object_release_unless_active(so.obj); | |
| 236 | + return err; | |
| 284 | 237 | } |
| @@ -26,8 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | struct drm_i915_gem_request; |
| 28 | 28 | |
| 29 | −int i915_gem_render_state_init(struct intel_engine_cs *engine); | |
| 30 | −int i915_gem_render_state_emit(struct drm_i915_gem_request *req); | |
| 31 | −void i915_gem_render_state_fini(struct intel_engine_cs *engine); | |
| 29 | +int i915_gem_render_state_emit(struct drm_i915_gem_request *rq); | |
| 32 | 30 | |
| 33 | 31 | #endif /* _I915_GEM_RENDER_STATE_H_ */ |
| @@ -259,6 +259,8 @@ static void mark_busy(struct drm_i915_private *i915) · 258 unmodified lines | ||
| 259 | 259 | if (INTEL_GEN(i915) >= 6) |
| 260 | 260 | gen6_rps_busy(i915); |
| 261 | 261 | |
| 262 | + intel_engines_unpark(i915); | |
| 263 | + | |
| 262 | 264 | queue_delayed_work(i915->wq, |
| 263 | 265 | &i915->gt.retire_work, |
| 264 | 266 | round_jiffies_up_relative(HZ)); |
| @@ -294,6 +294,18 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, · 293 unmodified lines | ||
| 294 | 294 | ELK_STOLEN_RESERVED); |
| 295 | 295 | dma_addr_t stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; |
| 296 | 296 | |
| 297 | + if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) { | |
| 298 | + *base = 0; | |
| 299 | + *size = 0; | |
| 300 | + return; | |
| 301 | + } | |
| 302 | + | |
| 303 | + /* | |
| 304 | + * Whether ILK really reuses the ELK register for this is unclear. | |
| 305 | + * Let's see if we catch anyone with this supposedly enabled on ILK. | |
| 306 | + */ | |
| 307 | + WARN(IS_GEN5(dev_priv), "ILK stolen reserved found? 0x%08x\n", reg_val); | |
| 308 | + | |
| 297 | 309 | *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; |
| 298 | 310 | |
| 299 | 311 | WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); |
| @@ -313,6 +325,12 @@ static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, · 13 unmodified lines | ||
| 313 | 325 | { |
| 314 | 326 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
| 315 | 327 | |
| 328 | + if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | |
| 329 | + *base = 0; | |
| 330 | + *size = 0; | |
| 331 | + return; | |
| 332 | + } | |
| 333 | + | |
| 316 | 334 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
| 317 | 335 | |
| 318 | 336 | switch (reg_val & GEN6_STOLEN_RESERVED_SIZE_MASK) { |
| @@ -339,6 +357,12 @@ static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, · 20 unmodified lines | ||
| 339 | 357 | { |
| 340 | 358 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
| 341 | 359 | |
| 360 | + if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | |
| 361 | + *base = 0; | |
| 362 | + *size = 0; | |
| 363 | + return; | |
| 364 | + } | |
| 365 | + | |
| 342 | 366 | *base = reg_val & GEN7_STOLEN_RESERVED_ADDR_MASK; |
| 343 | 367 | |
| 344 | 368 | switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) { |
| @@ -359,6 +383,12 @@ static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, · 14 unmodified lines | ||
| 359 | 383 | { |
| 360 | 384 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
| 361 | 385 | |
| 386 | + if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | |
| 387 | + *base = 0; | |
| 388 | + *size = 0; | |
| 389 | + return; | |
| 390 | + } | |
| 391 | + | |
| 362 | 392 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
| 363 | 393 | |
| 364 | 394 | switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) { |
| @@ -387,6 +417,12 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, · 22 unmodified lines | ||
| 387 | 417 | uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); |
| 388 | 418 | dma_addr_t stolen_top; |
| 389 | 419 | |
| 420 | + if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { | |
| 421 | + *base = 0; | |
| 422 | + *size = 0; | |
| 423 | + return; | |
| 424 | + } | |
| 425 | + | |
| 390 | 426 | stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; |
| 391 | 427 | |
| 392 | 428 | *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; |
| @@ -436,14 +472,12 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) · 43 unmodified lines | ||
| 436 | 472 | case 3: |
| 437 | 473 | break; |
| 438 | 474 | case 4: |
| 439 | − if (IS_G4X(dev_priv)) | |
| 440 | − g4x_get_stolen_reserved(dev_priv, | |
| 441 | − &reserved_base, &reserved_size); | |
| 442 | − break; | |
| 475 | + if (!IS_G4X(dev_priv)) | |
| 476 | + break; | |
| 477 | + /* fall through */ | |
| 443 | 478 | case 5: |
| 444 | − /* Assume the gen6 maximum for the older platforms. */ | |
| 445 | − reserved_size = 1024 * 1024; | |
| 446 | − reserved_base = stolen_top - reserved_size; | |
| 479 | + g4x_get_stolen_reserved(dev_priv, | |
| 480 | + &reserved_base, &reserved_size); | |
| 447 | 481 | break; |
| 448 | 482 | case 6: |
| 449 | 483 | gen6_get_stolen_reserved(dev_priv, |
| @@ -473,9 +507,9 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) · 23 unmodified lines | ||
| 473 | 507 | if (reserved_base < dev_priv->mm.stolen_base || |
| 474 | 508 | reserved_base + reserved_size > stolen_top) { |
| 475 | 509 | dma_addr_t reserved_top = reserved_base + reserved_size; |
| 476 | − DRM_DEBUG_KMS("Stolen reserved area [%pad - %pad] outside stolen memory [%pad - %pad]\n", | |
| 477 | − &reserved_base, &reserved_top, | |
| 478 | − &dev_priv->mm.stolen_base, &stolen_top); | |
| 510 | + DRM_ERROR("Stolen reserved area [%pad - %pad] outside stolen memory [%pad - %pad]\n", | |
| 511 | + &reserved_base, &reserved_top, | |
| 512 | + &dev_priv->mm.stolen_base, &stolen_top); | |
| 479 | 513 | return 0; |
| 480 | 514 | } |
| 481 | 515 | |
| @@ -345,6 +345,15 @@ i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data, · 344 unmodified lines | ||
| 345 | 345 | if (!obj) |
| 346 | 346 | return -ENOENT; |
| 347 | 347 | |
| 348 | + /* | |
| 349 | + * The tiling mode of proxy objects is handled by its generator, and | |
| 350 | + * not allowed to be changed by userspace. | |
| 351 | + */ | |
| 352 | + if (i915_gem_object_is_proxy(obj)) { | |
| 353 | + err = -ENXIO; | |
| 354 | + goto err; | |
| 355 | + } | |
| 356 | + | |
| 348 | 357 | if (!i915_tiling_ok(obj, args->tiling_mode, args->stride)) { |
| 349 | 358 | err = -EINVAL; |
| 350 | 359 | goto err; |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <generated/utsrelease.h> |
| 31 | 31 | #include <linux/stop_machine.h> |
| 32 | 32 | #include <linux/zlib.h> |
| 33 | +#include <drm/drm_print.h> | |
| 34 | + | |
| 33 | 35 | #include "i915_drv.h" |
| 34 | 36 | |
| 35 | 37 | static const char *engine_str(int engine) |
| @@ -175,6 +177,21 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e, · 139 unmodified lines | ||
| 175 | 177 | #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) |
| 176 | 178 | #define err_puts(e, s) i915_error_puts(e, s) |
| 177 | 179 | |
| 180 | +static void __i915_printfn_error(struct drm_printer *p, struct va_format *vaf) | |
| 181 | +{ | |
| 182 | + i915_error_vprintf(p->arg, vaf->fmt, *vaf->va); | |
| 183 | +} | |
| 184 | + | |
| 185 | +static inline struct drm_printer | |
| 186 | +i915_error_printer(struct drm_i915_error_state_buf *e) | |
| 187 | +{ | |
| 188 | + struct drm_printer p = { | |
| 189 | + .printfn = __i915_printfn_error, | |
| 190 | + .arg = e, | |
| 191 | + }; | |
| 192 | + return p; | |
| 193 | +} | |
| 194 | + | |
| 178 | 195 | #ifdef CONFIG_DRM_I915_COMPRESS_ERROR |
| 179 | 196 | |
| 180 | 197 | struct compress { |
| @@ -589,6 +606,21 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m, · 408 unmodified lines | ||
| 589 | 606 | pdev->subsystem_device); |
| 590 | 607 | } |
| 591 | 608 | |
| 609 | +static void err_print_uc(struct drm_i915_error_state_buf *m, | |
| 610 | + const struct i915_error_uc *error_uc) | |
| 611 | +{ | |
| 612 | + struct drm_printer p = i915_error_printer(m); | |
| 613 | + const struct i915_gpu_state *error = | |
| 614 | + container_of(error_uc, typeof(*error), uc); | |
| 615 | + | |
| 616 | + if (!error->device_info.has_guc) | |
| 617 | + return; | |
| 618 | + | |
| 619 | + intel_uc_fw_dump(&error_uc->guc_fw, &p); | |
| 620 | + intel_uc_fw_dump(&error_uc->huc_fw, &p); | |
| 621 | + print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log); | |
| 622 | +} | |
| 623 | + | |
| 592 | 624 | int i915_error_state_to_str(struct drm_i915_error_state_buf *m, |
| 593 | 625 | const struct i915_gpu_state *error) |
| 594 | 626 | { |
| @@ -763,8 +795,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, · 168 unmodified lines | ||
| 763 | 795 | |
| 764 | 796 | print_error_obj(m, NULL, "Semaphores", error->semaphore); |
| 765 | 797 | |
| 766 | − print_error_obj(m, NULL, "GuC log buffer", error->guc_log); | |
| 767 | − | |
| 768 | 798 | if (error->overlay) |
| 769 | 799 | intel_overlay_print_error_state(m, error->overlay); |
| 770 | 800 | |
| @@ -773,6 +803,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, · 2 unmodified lines | ||
| 773 | 803 | |
| 774 | 804 | err_print_capabilities(m, &error->device_info); |
| 775 | 805 | err_print_params(m, &error->params); |
| 806 | + err_print_uc(m, &error->uc); | |
| 776 | 807 | |
| 777 | 808 | if (m->bytes == 0 && m->err) |
| 778 | 809 | return m->err; |
| @@ -831,6 +862,22 @@ static __always_inline void free_param(const char *type, void *x) · 52 unmodified lines | ||
| 831 | 862 | kfree(*(void **)x); |
| 832 | 863 | } |
| 833 | 864 | |
| 865 | +static void cleanup_params(struct i915_gpu_state *error) | |
| 866 | +{ | |
| 867 | +#define FREE(T, x, ...) free_param(#T, &error->params.x); | |
| 868 | + I915_PARAMS_FOR_EACH(FREE); | |
| 869 | +#undef FREE | |
| 870 | +} | |
| 871 | + | |
| 872 | +static void cleanup_uc_state(struct i915_gpu_state *error) | |
| 873 | +{ | |
| 874 | + struct i915_error_uc *error_uc = &error->uc; | |
| 875 | + | |
| 876 | + kfree(error_uc->guc_fw.path); | |
| 877 | + kfree(error_uc->huc_fw.path); | |
| 878 | + i915_error_object_free(error_uc->guc_log); | |
| 879 | +} | |
| 880 | + | |
| 834 | 881 | void __i915_gpu_state_free(struct kref *error_ref) |
| 835 | 882 | { |
| 836 | 883 | struct i915_gpu_state *error = |
| @@ -857,7 +904,6 @@ void __i915_gpu_state_free(struct kref *error_ref) · 20 unmodified lines | ||
| 857 | 904 | } |
| 858 | 905 | |
| 859 | 906 | i915_error_object_free(error->semaphore); |
| 860 | − i915_error_object_free(error->guc_log); | |
| 861 | 907 | |
| 862 | 908 | for (i = 0; i < ARRAY_SIZE(error->active_bo); i++) |
| 863 | 909 | kfree(error->active_bo[i]); |
| @@ -866,9 +912,8 @@ void __i915_gpu_state_free(struct kref *error_ref) · 2 unmodified lines | ||
| 866 | 912 | kfree(error->overlay); |
| 867 | 913 | kfree(error->display); |
| 868 | 914 | |
| 869 | −#define FREE(T, x, ...) free_param(#T, &error->params.x); | |
| 870 | − I915_PARAMS_FOR_EACH(FREE); | |
| 871 | −#undef FREE | |
| 915 | + cleanup_params(error); | |
| 916 | + cleanup_uc_state(error); | |
| 872 | 917 | |
| 873 | 918 | kfree(error); |
| 874 | 919 | } |
| @@ -1172,11 +1217,13 @@ static void error_record_engine_registers(struct i915_gpu_state *error, · 297 unmodified lines | ||
| 1172 | 1217 | |
| 1173 | 1218 | if (INTEL_GEN(dev_priv) >= 6) { |
| 1174 | 1219 | ee->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base)); |
| 1175 | − ee->fault_reg = I915_READ(RING_FAULT_REG(engine)); | |
| 1176 | − if (INTEL_GEN(dev_priv) >= 8) | |
| 1220 | + if (INTEL_GEN(dev_priv) >= 8) { | |
| 1177 | 1221 | gen8_record_semaphore_state(error, engine, ee); |
| 1178 | − else | |
| 1222 | + ee->fault_reg = I915_READ(GEN8_RING_FAULT_REG); | |
| 1223 | + } else { | |
| 1179 | 1224 | gen6_record_semaphore_state(engine, ee); |
| 1225 | + ee->fault_reg = I915_READ(RING_FAULT_REG(engine)); | |
| 1226 | + } | |
| 1180 | 1227 | } |
| 1181 | 1228 | |
| 1182 | 1229 | if (INTEL_GEN(dev_priv) >= 4) { |
| @@ -1559,15 +1606,25 @@ static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv, · 376 unmodified lines | ||
| 1559 | 1606 | error->pinned_bo = bo; |
| 1560 | 1607 | } |
| 1561 | 1608 | |
| 1562 | −static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv, | |
| 1563 | − struct i915_gpu_state *error) | |
| 1609 | +static void capture_uc_state(struct i915_gpu_state *error) | |
| 1564 | 1610 | { |
| 1565 | − /* Capturing log buf contents won't be useful if logging was disabled */ | |
| 1566 | − if (!dev_priv->guc.log.vma || (i915_modparams.guc_log_level < 0)) | |
| 1611 | + struct drm_i915_private *i915 = error->i915; | |
| 1612 | + struct i915_error_uc *error_uc = &error->uc; | |
| 1613 | + | |
| 1614 | + /* Capturing uC state won't be useful if there is no GuC */ | |
| 1615 | + if (!error->device_info.has_guc) | |
| 1567 | 1616 | return; |
| 1568 | 1617 | |
| 1569 | − error->guc_log = i915_error_object_create(dev_priv, | |
| 1570 | − dev_priv->guc.log.vma); | |
| 1618 | + error_uc->guc_fw = i915->guc.fw; | |
| 1619 | + error_uc->huc_fw = i915->huc.fw; | |
| 1620 | + | |
| 1621 | + /* Non-default firmware paths will be specified by the modparam. | |
| 1622 | + * As modparams are generally accesible from the userspace make | |
| 1623 | + * explicit copies of the firmware paths. | |
| 1624 | + */ | |
| 1625 | + error_uc->guc_fw.path = kstrdup(i915->guc.fw.path, GFP_ATOMIC); | |
| 1626 | + error_uc->huc_fw.path = kstrdup(i915->huc.fw.path, GFP_ATOMIC); | |
| 1627 | + error_uc->guc_log = i915_error_object_create(i915, i915->guc.log.vma); | |
| 1571 | 1628 | } |
| 1572 | 1629 | |
| 1573 | 1630 | /* Capture all registers which don't fit into another category. */ |
| @@ -1695,6 +1752,14 @@ static __always_inline void dup_param(const char *type, void *x) · 121 unmodified lines | ||
| 1695 | 1752 | *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC); |
| 1696 | 1753 | } |
| 1697 | 1754 | |
| 1755 | +static void capture_params(struct i915_gpu_state *error) | |
| 1756 | +{ | |
| 1757 | + error->params = i915_modparams; | |
| 1758 | +#define DUP(T, x, ...) dup_param(#T, &error->params.x); | |
| 1759 | + I915_PARAMS_FOR_EACH(DUP); | |
| 1760 | +#undef DUP | |
| 1761 | +} | |
| 1762 | + | |
| 1698 | 1763 | static int capture(void *data) |
| 1699 | 1764 | { |
| 1700 | 1765 | struct i915_gpu_state *error = data; |
| @@ -1705,10 +1770,8 @@ static int capture(void *data) · 4 unmodified lines | ||
| 1705 | 1770 | ktime_to_timeval(ktime_sub(ktime_get(), |
| 1706 | 1771 | error->i915->gt.last_init_time)); |
| 1707 | 1772 | |
| 1708 | − error->params = i915_modparams; | |
| 1709 | −#define DUP(T, x, ...) dup_param(#T, &error->params.x); | |
| 1710 | − I915_PARAMS_FOR_EACH(DUP); | |
| 1711 | −#undef DUP | |
| 1773 | + capture_params(error); | |
| 1774 | + capture_uc_state(error); | |
| 1712 | 1775 | |
| 1713 | 1776 | i915_capture_gen_state(error->i915, error); |
| 1714 | 1777 | i915_capture_reg_state(error->i915, error); |
| @@ -1716,7 +1779,6 @@ static int capture(void *data) · 1 unmodified line | ||
| 1716 | 1779 | i915_gem_record_rings(error->i915, error); |
| 1717 | 1780 | i915_capture_active_buffers(error->i915, error); |
| 1718 | 1781 | i915_capture_pinned_buffers(error->i915, error); |
| 1719 | − i915_gem_capture_guc_log_buffer(error->i915, error); | |
| 1720 | 1782 | |
| 1721 | 1783 | error->overlay = intel_overlay_capture_error_state(error->i915); |
| 1722 | 1784 | error->display = intel_display_capture_error_state(error->i915); |
| @@ -102,13 +102,6 @@ · 101 unmodified lines | ||
| 102 | 102 | #define GUC_ENABLE_MIA_CLOCK_GATING (1<<15) |
| 103 | 103 | #define GUC_GEN10_SHIM_WC_ENABLE (1<<21) |
| 104 | 104 | |
| 105 | −#define GUC_SHIM_CONTROL_VALUE (GUC_DISABLE_SRAM_INIT_TO_ZEROES | \ | |
| 106 | − GUC_ENABLE_READ_CACHE_LOGIC | \ | |
| 107 | − GUC_ENABLE_MIA_CACHING | \ | |
| 108 | − GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA | \ | |
| 109 | − GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \ | |
| 110 | − GUC_ENABLE_MIA_CLOCK_GATING) | |
| 111 | − | |
| 112 | 105 | #define GUC_SEND_INTERRUPT _MMIO(0xc4c8) |
| 113 | 106 | #define GUC_SEND_TRIGGER (1<<0) |
| 114 | 107 | |
| @@ -1068,6 +1068,9 @@ static void notify_ring(struct intel_engine_cs *engine) · 1067 unmodified lines | ||
| 1068 | 1068 | struct drm_i915_gem_request *rq = NULL; |
| 1069 | 1069 | struct intel_wait *wait; |
| 1070 | 1070 | |
| 1071 | + if (!engine->breadcrumbs.irq_armed) | |
| 1072 | + return; | |
| 1073 | + | |
| 1071 | 1074 | atomic_inc(&engine->irq_count); |
| 1072 | 1075 | set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted); |
| 1073 | 1076 | |
| @@ -1101,7 +1104,8 @@ static void notify_ring(struct intel_engine_cs *engine) · 27 unmodified lines | ||
| 1101 | 1104 | if (wakeup) |
| 1102 | 1105 | wake_up_process(wait->tsk); |
| 1103 | 1106 | } else { |
| 1104 | − __intel_engine_disarm_breadcrumbs(engine); | |
| 1107 | + if (engine->breadcrumbs.irq_armed) | |
| 1108 | + __intel_engine_disarm_breadcrumbs(engine); | |
| 1105 | 1109 | } |
| 1106 | 1110 | spin_unlock(&engine->breadcrumbs.irq_lock); |
| 1107 | 1111 | |
| @@ -1400,7 +1404,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) · 292 unmodified lines | ||
| 1400 | 1404 | } |
| 1401 | 1405 | |
| 1402 | 1406 | if (tasklet) |
| 1403 | − tasklet_hi_schedule(&execlists->irq_tasklet); | |
| 1407 | + tasklet_hi_schedule(&execlists->tasklet); | |
| 1404 | 1408 | } |
| 1405 | 1409 | |
| 1406 | 1410 | static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv, |
| @@ -85,9 +85,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 84 unmodified lines | ||
| 85 | 85 | void |
| 86 | 86 | i915_perf_load_test_config_bdw(struct drm_i915_private *dev_priv) |
| 87 | 87 | { |
| 88 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 89 | 89 | "d6de6f55-e526-4f79-a6a6-d7315c09044e", |
| 90 | − UUID_STRING_LEN); | |
| 90 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 91 | 91 | dev_priv->perf.oa.test_config.id = 1; |
| 92 | 92 | |
| 93 | 93 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -83,9 +83,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 82 unmodified lines | ||
| 83 | 83 | void |
| 84 | 84 | i915_perf_load_test_config_bxt(struct drm_i915_private *dev_priv) |
| 85 | 85 | { |
| 86 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 86 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | 87 | "5ee72f5c-092f-421e-8b70-225f7c3e9612", |
| 88 | − UUID_STRING_LEN); | |
| 88 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 89 | 89 | dev_priv->perf.oa.test_config.id = 1; |
| 90 | 90 | |
| 91 | 91 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "74fb4902-d3d3-4237-9e90-cbdc68d0a446", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -0,0 +1,109 @@ | ||
| 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_cflgt3.h" | |
| 33 | + | |
| 34 | +static const struct i915_oa_reg b_counter_config_test_oa[] = { | |
| 35 | + { _MMIO(0x2740), 0x00000000 }, | |
| 36 | + { _MMIO(0x2744), 0x00800000 }, | |
| 37 | + { _MMIO(0x2714), 0xf0800000 }, | |
| 38 | + { _MMIO(0x2710), 0x00000000 }, | |
| 39 | + { _MMIO(0x2724), 0xf0800000 }, | |
| 40 | + { _MMIO(0x2720), 0x00000000 }, | |
| 41 | + { _MMIO(0x2770), 0x00000004 }, | |
| 42 | + { _MMIO(0x2774), 0x00000000 }, | |
| 43 | + { _MMIO(0x2778), 0x00000003 }, | |
| 44 | + { _MMIO(0x277c), 0x00000000 }, | |
| 45 | + { _MMIO(0x2780), 0x00000007 }, | |
| 46 | + { _MMIO(0x2784), 0x00000000 }, | |
| 47 | + { _MMIO(0x2788), 0x00100002 }, | |
| 48 | + { _MMIO(0x278c), 0x0000fff7 }, | |
| 49 | + { _MMIO(0x2790), 0x00100002 }, | |
| 50 | + { _MMIO(0x2794), 0x0000ffcf }, | |
| 51 | + { _MMIO(0x2798), 0x00100082 }, | |
| 52 | + { _MMIO(0x279c), 0x0000ffef }, | |
| 53 | + { _MMIO(0x27a0), 0x001000c2 }, | |
| 54 | + { _MMIO(0x27a4), 0x0000ffe7 }, | |
| 55 | + { _MMIO(0x27a8), 0x00100001 }, | |
| 56 | + { _MMIO(0x27ac), 0x0000ffe7 }, | |
| 57 | +}; | |
| 58 | + | |
| 59 | +static const struct i915_oa_reg flex_eu_config_test_oa[] = { | |
| 60 | +}; | |
| 61 | + | |
| 62 | +static const struct i915_oa_reg mux_config_test_oa[] = { | |
| 63 | + { _MMIO(0x9840), 0x00000080 }, | |
| 64 | + { _MMIO(0x9888), 0x11810000 }, | |
| 65 | + { _MMIO(0x9888), 0x07810013 }, | |
| 66 | + { _MMIO(0x9888), 0x1f810000 }, | |
| 67 | + { _MMIO(0x9888), 0x1d810000 }, | |
| 68 | + { _MMIO(0x9888), 0x1b930040 }, | |
| 69 | + { _MMIO(0x9888), 0x07e54000 }, | |
| 70 | + { _MMIO(0x9888), 0x1f908000 }, | |
| 71 | + { _MMIO(0x9888), 0x11900000 }, | |
| 72 | + { _MMIO(0x9888), 0x37900000 }, | |
| 73 | + { _MMIO(0x9888), 0x53900000 }, | |
| 74 | + { _MMIO(0x9888), 0x45900000 }, | |
| 75 | + { _MMIO(0x9888), 0x33900000 }, | |
| 76 | +}; | |
| 77 | + | |
| 78 | +static ssize_t | |
| 79 | +show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) | |
| 80 | +{ | |
| 81 | + return sprintf(buf, "1\n"); | |
| 82 | +} | |
| 83 | + | |
| 84 | +void | |
| 85 | +i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) | |
| 86 | +{ | |
| 87 | + strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | + "577e8e2c-3fa0-4875-8743-3538d585e3b0", | |
| 89 | + UUID_STRING_LEN); | |
| 90 | + dev_priv->perf.oa.test_config.id = 1; | |
| 91 | + | |
| 92 | + dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; | |
| 93 | + dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa); | |
| 94 | + | |
| 95 | + dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa; | |
| 96 | + dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa); | |
| 97 | + | |
| 98 | + dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa; | |
| 99 | + dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa); | |
| 100 | + | |
| 101 | + dev_priv->perf.oa.test_config.sysfs_metric.name = "577e8e2c-3fa0-4875-8743-3538d585e3b0"; | |
| 102 | + dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs; | |
| 103 | + | |
| 104 | + dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr; | |
| 105 | + | |
| 106 | + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id"; | |
| 107 | + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444; | |
| 108 | + dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id; | |
| 109 | +} | |
| @@ -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_CFLGT3_H__ | |
| 30 | +#define __I915_OA_CFLGT3_H__ | |
| 31 | + | |
| 32 | +extern void i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv); | |
| 33 | + | |
| 34 | +#endif | |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_chv(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "4a534b07-cba3-414d-8d60-874830e883aa", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -0,0 +1,121 @@ | ||
| 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_cnl.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(0x9884), 0x00000007 }, | |
| 64 | + { _MMIO(0x9888), 0x17060000 }, | |
| 65 | + { _MMIO(0x9840), 0x00000000 }, | |
| 66 | + { _MMIO(0x9884), 0x00000007 }, | |
| 67 | + { _MMIO(0x9888), 0x13034000 }, | |
| 68 | + { _MMIO(0x9884), 0x00000007 }, | |
| 69 | + { _MMIO(0x9888), 0x07060066 }, | |
| 70 | + { _MMIO(0x9884), 0x00000007 }, | |
| 71 | + { _MMIO(0x9888), 0x05060000 }, | |
| 72 | + { _MMIO(0x9884), 0x00000007 }, | |
| 73 | + { _MMIO(0x9888), 0x0f080040 }, | |
| 74 | + { _MMIO(0x9884), 0x00000007 }, | |
| 75 | + { _MMIO(0x9888), 0x07091000 }, | |
| 76 | + { _MMIO(0x9884), 0x00000007 }, | |
| 77 | + { _MMIO(0x9888), 0x0f041000 }, | |
| 78 | + { _MMIO(0x9884), 0x00000007 }, | |
| 79 | + { _MMIO(0x9888), 0x1d004000 }, | |
| 80 | + { _MMIO(0x9884), 0x00000007 }, | |
| 81 | + { _MMIO(0x9888), 0x35000000 }, | |
| 82 | + { _MMIO(0x9884), 0x00000007 }, | |
| 83 | + { _MMIO(0x9888), 0x49000000 }, | |
| 84 | + { _MMIO(0x9884), 0x00000007 }, | |
| 85 | + { _MMIO(0x9888), 0x3d000000 }, | |
| 86 | + { _MMIO(0x9884), 0x00000007 }, | |
| 87 | + { _MMIO(0x9888), 0x31000000 }, | |
| 88 | +}; | |
| 89 | + | |
| 90 | +static ssize_t | |
| 91 | +show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) | |
| 92 | +{ | |
| 93 | + return sprintf(buf, "1\n"); | |
| 94 | +} | |
| 95 | + | |
| 96 | +void | |
| 97 | +i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) | |
| 98 | +{ | |
| 99 | + strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 100 | + "db41edd4-d8e7-4730-ad11-b9a2d6833503", | |
| 101 | + UUID_STRING_LEN); | |
| 102 | + dev_priv->perf.oa.test_config.id = 1; | |
| 103 | + | |
| 104 | + dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; | |
| 105 | + dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa); | |
| 106 | + | |
| 107 | + dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa; | |
| 108 | + dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa); | |
| 109 | + | |
| 110 | + dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa; | |
| 111 | + dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa); | |
| 112 | + | |
| 113 | + dev_priv->perf.oa.test_config.sysfs_metric.name = "db41edd4-d8e7-4730-ad11-b9a2d6833503"; | |
| 114 | + dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs; | |
| 115 | + | |
| 116 | + dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr; | |
| 117 | + | |
| 118 | + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id"; | |
| 119 | + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444; | |
| 120 | + dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id; | |
| 121 | +} | |
| @@ -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_CNL_H__ | |
| 30 | +#define __I915_OA_CNL_H__ | |
| 31 | + | |
| 32 | +extern void i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv); | |
| 33 | + | |
| 34 | +#endif | |
| @@ -83,9 +83,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 82 unmodified lines | ||
| 83 | 83 | void |
| 84 | 84 | i915_perf_load_test_config_glk(struct drm_i915_private *dev_priv) |
| 85 | 85 | { |
| 86 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 86 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | 87 | "dd3fd789-e783-4204-8cd0-b671bbccb0cf", |
| 88 | − UUID_STRING_LEN); | |
| 88 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 89 | 89 | dev_priv->perf.oa.test_config.id = 1; |
| 90 | 90 | |
| 91 | 91 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -113,9 +113,9 @@ show_render_basic_id(struct device *kdev, struct device_attribute *attr, char *b · 112 unmodified lines | ||
| 113 | 113 | void |
| 114 | 114 | i915_perf_load_test_config_hsw(struct drm_i915_private *dev_priv) |
| 115 | 115 | { |
| 116 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 116 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 117 | 117 | "403d8832-1a27-4aa6-a64e-f5389ce7b212", |
| 118 | − UUID_STRING_LEN); | |
| 118 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 119 | 119 | dev_priv->perf.oa.test_config.id = 1; |
| 120 | 120 | |
| 121 | 121 | dev_priv->perf.oa.test_config.mux_regs = mux_config_render_basic; |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_kblgt2(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "baa3c7e4-52b6-4b85-801e-465a94b746dd", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_kblgt3(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "f1792f32-6db2-4b50-b4b2-557128f1688d", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -83,9 +83,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 82 unmodified lines | ||
| 83 | 83 | void |
| 84 | 84 | i915_perf_load_test_config_sklgt2(struct drm_i915_private *dev_priv) |
| 85 | 85 | { |
| 86 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 86 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | 87 | "1651949f-0ac0-4cb1-a06f-dafd74a407d1", |
| 88 | − UUID_STRING_LEN); | |
| 88 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 89 | 89 | dev_priv->perf.oa.test_config.id = 1; |
| 90 | 90 | |
| 91 | 91 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_sklgt3(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "2b985803-d3c9-4629-8a4f-634bfecba0e8", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) · 83 unmodified lines | ||
| 84 | 84 | void |
| 85 | 85 | i915_perf_load_test_config_sklgt4(struct drm_i915_private *dev_priv) |
| 86 | 86 | { |
| 87 | − strncpy(dev_priv->perf.oa.test_config.uuid, | |
| 87 | + strlcpy(dev_priv->perf.oa.test_config.uuid, | |
| 88 | 88 | "882fa433-1f4a-4a67-a962-c741888fe5f5", |
| 89 | − UUID_STRING_LEN); | |
| 89 | + sizeof(dev_priv->perf.oa.test_config.uuid)); | |
| 90 | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | |
| 92 | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
| @@ -207,6 +207,8 @@ · 206 unmodified lines | ||
| 207 | 207 | #include "i915_oa_kblgt3.h" |
| 208 | 208 | #include "i915_oa_glk.h" |
| 209 | 209 | #include "i915_oa_cflgt2.h" |
| 210 | +#include "i915_oa_cflgt3.h" | |
| 211 | +#include "i915_oa_cnl.h" | |
| 210 | 212 | |
| 211 | 213 | /* HW requires this to be a power of two, between 128k and 16M, though driver |
| 212 | 214 | * is currently generally designed assuming the largest 16M size is used such |
| @@ -1851,7 +1853,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, · 1638 unmodified lines | ||
| 1851 | 1853 | * be read back from automatically triggered reports, as part of the |
| 1852 | 1854 | * RPT_ID field. |
| 1853 | 1855 | */ |
| 1854 | − if (IS_GEN9(dev_priv)) { | |
| 1856 | + if (IS_GEN9(dev_priv) || IS_GEN10(dev_priv)) { | |
| 1855 | 1857 | I915_WRITE(GEN8_OA_DEBUG, |
| 1856 | 1858 | _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | |
| 1857 | 1859 | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); |
| @@ -1884,6 +1886,16 @@ static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) · 26 unmodified lines | ||
| 1884 | 1886 | |
| 1885 | 1887 | } |
| 1886 | 1888 | |
| 1889 | +static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) | |
| 1890 | +{ | |
| 1891 | + /* Reset all contexts' slices/subslices configurations. */ | |
| 1892 | + gen8_configure_all_contexts(dev_priv, NULL, false); | |
| 1893 | + | |
| 1894 | + /* Make sure we disable noa to save power. */ | |
| 1895 | + I915_WRITE(RPM_CONFIG1, | |
| 1896 | + I915_READ(RPM_CONFIG1) & ~GEN10_GT_NOA_ENABLE); | |
| 1897 | +} | |
| 1898 | + | |
| 1887 | 1899 | static void gen7_oa_enable(struct drm_i915_private *dev_priv) |
| 1888 | 1900 | { |
| 1889 | 1901 | /* |
| @@ -2934,6 +2946,10 @@ void i915_perf_register(struct drm_i915_private *dev_priv) · 1044 unmodified lines | ||
| 2934 | 2946 | } else if (IS_COFFEELAKE(dev_priv)) { |
| 2935 | 2947 | if (IS_CFL_GT2(dev_priv)) |
| 2936 | 2948 | i915_perf_load_test_config_cflgt2(dev_priv); |
| 2949 | + if (IS_CFL_GT3(dev_priv)) | |
| 2950 | + i915_perf_load_test_config_cflgt3(dev_priv); | |
| 2951 | + } else if (IS_CANNONLAKE(dev_priv)) { | |
| 2952 | + i915_perf_load_test_config_cnl(dev_priv); | |
| 2937 | 2953 | } |
| 2938 | 2954 | |
| 2939 | 2955 | if (dev_priv->perf.oa.test_config.id == 0) |
| @@ -3019,11 +3035,18 @@ static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) · 79 unmodified lines | ||
| 3019 | 3035 | (addr >= RPM_CONFIG0.reg && addr <= NOA_CONFIG(8).reg); |
| 3020 | 3036 | } |
| 3021 | 3037 | |
| 3038 | +static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) | |
| 3039 | +{ | |
| 3040 | + return gen8_is_valid_mux_addr(dev_priv, addr) || | |
| 3041 | + (addr >= OA_PERFCNT3_LO.reg && addr <= OA_PERFCNT4_HI.reg); | |
| 3042 | +} | |
| 3043 | + | |
| 3022 | 3044 | static bool hsw_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) |
| 3023 | 3045 | { |
| 3024 | 3046 | return gen7_is_valid_mux_addr(dev_priv, addr) || |
| 3025 | 3047 | (addr >= 0x25100 && addr <= 0x2FF90) || |
| 3026 | − addr == 0x9ec0; | |
| 3048 | + (addr >= HSW_MBVID2_NOA0.reg && addr <= HSW_MBVID2_NOA9.reg) || | |
| 3049 | + addr == HSW_MBVID2_MISR0.reg; | |
| 3027 | 3050 | } |
| 3028 | 3051 | |
| 3029 | 3052 | static bool chv_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) |
| @@ -3419,41 +3442,46 @@ void i915_perf_init(struct drm_i915_private *dev_priv) · 389 unmodified lines | ||
| 3419 | 3442 | * worth the complexity to maintain now that BDW+ enable |
| 3420 | 3443 | * execlist mode by default. |
| 3421 | 3444 | */ |
| 3422 | − dev_priv->perf.oa.ops.is_valid_b_counter_reg = | |
| 3423 | − gen7_is_valid_b_counter_addr; | |
| 3424 | − dev_priv->perf.oa.ops.is_valid_mux_reg = | |
| 3425 | − gen8_is_valid_mux_addr; | |
| 3426 | − dev_priv->perf.oa.ops.is_valid_flex_reg = | |
| 3427 | − gen8_is_valid_flex_addr; | |
| 3445 | + dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats; | |
| 3428 | 3446 | |
| 3429 | 3447 | dev_priv->perf.oa.ops.init_oa_buffer = gen8_init_oa_buffer; |
| 3430 | − dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set; | |
| 3431 | − dev_priv->perf.oa.ops.disable_metric_set = gen8_disable_metric_set; | |
| 3432 | 3448 | dev_priv->perf.oa.ops.oa_enable = gen8_oa_enable; |
| 3433 | 3449 | dev_priv->perf.oa.ops.oa_disable = gen8_oa_disable; |
| 3434 | 3450 | dev_priv->perf.oa.ops.read = gen8_oa_read; |
| 3435 | 3451 | dev_priv->perf.oa.ops.oa_hw_tail_read = gen8_oa_hw_tail_read; |
| 3436 | 3452 | |
| 3437 | − dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats; | |
| 3438 | − | |
| 3439 | − if (IS_GEN8(dev_priv)) { | |
| 3440 | − dev_priv->perf.oa.ctx_oactxctrl_offset = 0x120; | |
| 3441 | − dev_priv->perf.oa.ctx_flexeu0_offset = 0x2ce; | |
| 3442 | − | |
| 3443 | − dev_priv->perf.oa.timestamp_frequency = 12500000; | |
| 3453 | + if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) { | |
| 3454 | + dev_priv->perf.oa.ops.is_valid_b_counter_reg = | |
| 3455 | + gen7_is_valid_b_counter_addr; | |
| 3456 | + dev_priv->perf.oa.ops.is_valid_mux_reg = | |
| 3457 | + gen8_is_valid_mux_addr; | |
| 3458 | + dev_priv->perf.oa.ops.is_valid_flex_reg = | |
| 3459 | + gen8_is_valid_flex_addr; | |
| 3444 | 3460 | |
| 3445 | − dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<25); | |
| 3446 | 3461 | if (IS_CHERRYVIEW(dev_priv)) { |
| 3447 | 3462 | dev_priv->perf.oa.ops.is_valid_mux_reg = |
| 3448 | 3463 | chv_is_valid_mux_addr; |
| 3449 | 3464 | } |
| 3450 | − } else if (IS_GEN9(dev_priv)) { | |
| 3451 | − dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128; | |
| 3452 | − dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de; | |
| 3453 | 3465 | |
| 3454 | − dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); | |
| 3466 | + dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set; | |
| 3467 | + dev_priv->perf.oa.ops.disable_metric_set = gen8_disable_metric_set; | |
| 3468 | + | |
| 3469 | + if (IS_GEN8(dev_priv)) { | |
| 3470 | + dev_priv->perf.oa.ctx_oactxctrl_offset = 0x120; | |
| 3471 | + dev_priv->perf.oa.ctx_flexeu0_offset = 0x2ce; | |
| 3472 | + | |
| 3473 | + dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<25); | |
| 3474 | + } else { | |
| 3475 | + dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128; | |
| 3476 | + dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de; | |
| 3477 | + | |
| 3478 | + dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); | |
| 3479 | + } | |
| 3455 | 3480 | |
| 3456 | 3481 | switch (dev_priv->info.platform) { |
| 3482 | + case INTEL_BROADWELL: | |
| 3483 | + dev_priv->perf.oa.timestamp_frequency = 12500000; | |
| 3484 | + break; | |
| 3457 | 3485 | case INTEL_BROXTON: |
| 3458 | 3486 | case INTEL_GEMINILAKE: |
| 3459 | 3487 | dev_priv->perf.oa.timestamp_frequency = 19200000; |
| @@ -3464,11 +3492,28 @@ void i915_perf_init(struct drm_i915_private *dev_priv) · 4 unmodified lines | ||
| 3464 | 3492 | dev_priv->perf.oa.timestamp_frequency = 12000000; |
| 3465 | 3493 | break; |
| 3466 | 3494 | default: |
| 3467 | − /* Leave timestamp_frequency to 0 so we can | |
| 3468 | − * detect unsupported platforms. | |
| 3469 | − */ | |
| 3470 | 3495 | break; |
| 3471 | 3496 | } |
| 3497 | + } else if (IS_GEN10(dev_priv)) { | |
| 3498 | + dev_priv->perf.oa.ops.is_valid_b_counter_reg = | |
| 3499 | + gen7_is_valid_b_counter_addr; | |
| 3500 | + dev_priv->perf.oa.ops.is_valid_mux_reg = | |
| 3501 | + gen10_is_valid_mux_addr; | |
| 3502 | + dev_priv->perf.oa.ops.is_valid_flex_reg = | |
| 3503 | + gen8_is_valid_flex_addr; | |
| 3504 | + | |
| 3505 | + dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set; | |
| 3506 | + dev_priv->perf.oa.ops.disable_metric_set = gen10_disable_metric_set; | |
| 3507 | + | |
| 3508 | + dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128; | |
| 3509 | + dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de; | |
| 3510 | + | |
| 3511 | + dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); | |
| 3512 | + | |
| 3513 | + /* Default frequency, although we need to read it from | |
| 3514 | + * the register as it might vary between parts. | |
| 3515 | + */ | |
| 3516 | + dev_priv->perf.oa.timestamp_frequency = 12000000; | |
| 3472 | 3517 | } |
| 3473 | 3518 | } |
| 3474 | 3519 | |
| @@ -355,9 +355,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 354 unmodified lines | ||
| 355 | 355 | #define ECOCHK_PPGTT_WT_HSW (0x2<<3) |
| 356 | 356 | #define ECOCHK_PPGTT_WB_HSW (0x3<<3) |
| 357 | 357 | |
| 358 | −#define GEN8_CONFIG0 _MMIO(0xD00) | |
| 359 | −#define GEN9_DEFAULT_FIXES (1 << 3 | 1 << 2 | 1 << 1) | |
| 360 | − | |
| 361 | 358 | #define GAC_ECO_BITS _MMIO(0x14090) |
| 362 | 359 | #define ECOBITS_SNB_BIT (1<<13) |
| 363 | 360 | #define ECOBITS_PPGTT_CACHE64B (3<<8) |
| @@ -382,6 +379,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 18 unmodified lines | ||
| 382 | 379 | #define GEN8_STOLEN_RESERVED_2M (1 << 7) |
| 383 | 380 | #define GEN8_STOLEN_RESERVED_4M (2 << 7) |
| 384 | 381 | #define GEN8_STOLEN_RESERVED_8M (3 << 7) |
| 382 | +#define GEN6_STOLEN_RESERVED_ENABLE (1 << 0) | |
| 385 | 383 | |
| 386 | 384 | /* VGA stuff */ |
| 387 | 385 | |
| @@ -1109,16 +1107,50 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 721 unmodified lines | ||
| 1109 | 1107 | #define OA_PERFCNT1_HI _MMIO(0x91BC) |
| 1110 | 1108 | #define OA_PERFCNT2_LO _MMIO(0x91C0) |
| 1111 | 1109 | #define OA_PERFCNT2_HI _MMIO(0x91C4) |
| 1110 | +#define OA_PERFCNT3_LO _MMIO(0x91C8) | |
| 1111 | +#define OA_PERFCNT3_HI _MMIO(0x91CC) | |
| 1112 | +#define OA_PERFCNT4_LO _MMIO(0x91D8) | |
| 1113 | +#define OA_PERFCNT4_HI _MMIO(0x91DC) | |
| 1112 | 1114 | |
| 1113 | 1115 | #define OA_PERFMATRIX_LO _MMIO(0x91C8) |
| 1114 | 1116 | #define OA_PERFMATRIX_HI _MMIO(0x91CC) |
| 1115 | 1117 | |
| 1116 | 1118 | /* RPM unit config (Gen8+) */ |
| 1117 | 1119 | #define RPM_CONFIG0 _MMIO(0x0D00) |
| 1118 | −#define RPM_CONFIG1 _MMIO(0x0D04) | |
| 1120 | +#define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT 3 | |
| 1121 | +#define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK (1 << GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT) | |
| 1122 | +#define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ 0 | |
| 1123 | +#define GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ 1 | |
| 1124 | +#define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT 1 | |
| 1125 | +#define GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK (0x3 << GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT) | |
| 1119 | 1126 | |
| 1120 | −/* RPC unit config (Gen8+) */ | |
| 1121 | −#define RPM_CONFIG _MMIO(0x0D08) | |
| 1127 | +#define RPM_CONFIG1 _MMIO(0x0D04) | |
| 1128 | +#define GEN10_GT_NOA_ENABLE (1 << 9) | |
| 1129 | + | |
| 1130 | +/* GPM unit config (Gen9+) */ | |
| 1131 | +#define CTC_MODE _MMIO(0xA26C) | |
| 1132 | +#define CTC_SOURCE_PARAMETER_MASK 1 | |
| 1133 | +#define CTC_SOURCE_CRYSTAL_CLOCK 0 | |
| 1134 | +#define CTC_SOURCE_DIVIDE_LOGIC 1 | |
| 1135 | +#define CTC_SHIFT_PARAMETER_SHIFT 1 | |
| 1136 | +#define CTC_SHIFT_PARAMETER_MASK (0x3 << CTC_SHIFT_PARAMETER_SHIFT) | |
| 1137 | + | |
| 1138 | +/* RCP unit config (Gen8+) */ | |
| 1139 | +#define RCP_CONFIG _MMIO(0x0D08) | |
| 1140 | + | |
| 1141 | +/* NOA (HSW) */ | |
| 1142 | +#define HSW_MBVID2_NOA0 _MMIO(0x9E80) | |
| 1143 | +#define HSW_MBVID2_NOA1 _MMIO(0x9E84) | |
| 1144 | +#define HSW_MBVID2_NOA2 _MMIO(0x9E88) | |
| 1145 | +#define HSW_MBVID2_NOA3 _MMIO(0x9E8C) | |
| 1146 | +#define HSW_MBVID2_NOA4 _MMIO(0x9E90) | |
| 1147 | +#define HSW_MBVID2_NOA5 _MMIO(0x9E94) | |
| 1148 | +#define HSW_MBVID2_NOA6 _MMIO(0x9E98) | |
| 1149 | +#define HSW_MBVID2_NOA7 _MMIO(0x9E9C) | |
| 1150 | +#define HSW_MBVID2_NOA8 _MMIO(0x9EA0) | |
| 1151 | +#define HSW_MBVID2_NOA9 _MMIO(0x9EA4) | |
| 1152 | + | |
| 1153 | +#define HSW_MBVID2_MISR0 _MMIO(0x9EC0) | |
| 1122 | 1154 | |
| 1123 | 1155 | /* NOA (Gen8+) */ |
| 1124 | 1156 | #define NOA_CONFIG(i) _MMIO(0x0D0C + (i) * 4) |
| @@ -2329,6 +2361,8 @@ enum i915_power_well_id { · 1204 unmodified lines | ||
| 2329 | 2361 | #define ARB_MODE_SWIZZLE_BDW (1<<1) |
| 2330 | 2362 | #define RENDER_HWS_PGA_GEN7 _MMIO(0x04080) |
| 2331 | 2363 | #define RING_FAULT_REG(engine) _MMIO(0x4094 + 0x100*(engine)->hw_id) |
| 2364 | +#define GEN8_RING_FAULT_REG _MMIO(0x4094) | |
| 2365 | +#define GEN8_RING_FAULT_ENGINE_ID(x) (((x) >> 12) & 0x7) | |
| 2332 | 2366 | #define RING_FAULT_GTTSEL_MASK (1<<11) |
| 2333 | 2367 | #define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff) |
| 2334 | 2368 | #define RING_FAULT_FAULT_TYPE(x) (((x) >> 1) & 0x3) |
| @@ -2951,9 +2985,6 @@ enum i915_power_well_id { · 616 unmodified lines | ||
| 2951 | 2985 | #define ILK_DPFC_CHICKEN _MMIO(0x43224) |
| 2952 | 2986 | #define ILK_DPFC_DISABLE_DUMMY0 (1<<8) |
| 2953 | 2987 | #define ILK_DPFC_NUKE_ON_ANY_MODIFICATION (1<<23) |
| 2954 | −#define GLK_SKIP_SEG_EN (1<<12) | |
| 2955 | −#define GLK_SKIP_SEG_COUNT_MASK (3<<10) | |
| 2956 | −#define GLK_SKIP_SEG_COUNT(x) ((x)<<10) | |
| 2957 | 2988 | #define ILK_FBC_RT_BASE _MMIO(0x2128) |
| 2958 | 2989 | #define ILK_FBC_RT_VALID (1<<0) |
| 2959 | 2990 | #define SNB_FBC_FRONT_BUFFER (1<<1) |
| @@ -3398,6 +3429,7 @@ enum i915_power_well_id { · 438 unmodified lines | ||
| 3398 | 3429 | #define ELK_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x48) |
| 3399 | 3430 | #define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16) |
| 3400 | 3431 | #define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4) |
| 3432 | +#define G4X_STOLEN_RESERVED_ENABLE (1 << 0) | |
| 3401 | 3433 | |
| 3402 | 3434 | /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ |
| 3403 | 3435 | #define DCLK _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5e04) |
| @@ -3819,6 +3851,7 @@ enum { · 415 unmodified lines | ||
| 3819 | 3851 | * GEN9 clock gating regs |
| 3820 | 3852 | */ |
| 3821 | 3853 | #define GEN9_CLKGATE_DIS_0 _MMIO(0x46530) |
| 3854 | +#define DARBF_GATING_DIS (1 << 27) | |
| 3822 | 3855 | #define PWM2_GATING_DIS (1 << 14) |
| 3823 | 3856 | #define PWM1_GATING_DIS (1 << 13) |
| 3824 | 3857 | |
| @@ -3837,6 +3870,7 @@ enum { · 12 unmodified lines | ||
| 3837 | 3870 | */ |
| 3838 | 3871 | #define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4) |
| 3839 | 3872 | #define SARBUNIT_CLKGATE_DIS (1 << 5) |
| 3873 | +#define RCCUNIT_CLKGATE_DIS (1 << 7) | |
| 3840 | 3874 | |
| 3841 | 3875 | /* |
| 3842 | 3876 | * Display engine regs |
| @@ -6263,7 +6297,7 @@ enum { · 2420 unmodified lines | ||
| 6263 | 6297 | #define _PLANE_CTL_2_A 0x70280 |
| 6264 | 6298 | #define _PLANE_CTL_3_A 0x70380 |
| 6265 | 6299 | #define PLANE_CTL_ENABLE (1 << 31) |
| 6266 | −#define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30) | |
| 6300 | +#define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-GLK */ | |
| 6267 | 6301 | #define PLANE_CTL_FORMAT_MASK (0xf << 24) |
| 6268 | 6302 | #define PLANE_CTL_FORMAT_YUV422 ( 0 << 24) |
| 6269 | 6303 | #define PLANE_CTL_FORMAT_NV12 ( 1 << 24) |
| @@ -6273,7 +6307,7 @@ enum { · 3 unmodified lines | ||
| 6273 | 6307 | #define PLANE_CTL_FORMAT_AYUV ( 8 << 24) |
| 6274 | 6308 | #define PLANE_CTL_FORMAT_INDEXED ( 12 << 24) |
| 6275 | 6309 | #define PLANE_CTL_FORMAT_RGB_565 ( 14 << 24) |
| 6276 | −#define PLANE_CTL_PIPE_CSC_ENABLE (1 << 23) | |
| 6310 | +#define PLANE_CTL_PIPE_CSC_ENABLE (1 << 23) /* Pre-GLK */ | |
| 6277 | 6311 | #define PLANE_CTL_KEY_ENABLE_MASK (0x3 << 21) |
| 6278 | 6312 | #define PLANE_CTL_KEY_ENABLE_SOURCE ( 1 << 21) |
| 6279 | 6313 | #define PLANE_CTL_KEY_ENABLE_DESTINATION ( 2 << 21) |
| @@ -6286,13 +6320,13 @@ enum { · 6 unmodified lines | ||
| 6286 | 6320 | #define PLANE_CTL_YUV422_VYUY ( 3 << 16) |
| 6287 | 6321 | #define PLANE_CTL_DECOMPRESSION_ENABLE (1 << 15) |
| 6288 | 6322 | #define PLANE_CTL_TRICKLE_FEED_DISABLE (1 << 14) |
| 6289 | −#define PLANE_CTL_PLANE_GAMMA_DISABLE (1 << 13) | |
| 6323 | +#define PLANE_CTL_PLANE_GAMMA_DISABLE (1 << 13) /* Pre-GLK */ | |
| 6290 | 6324 | #define PLANE_CTL_TILED_MASK (0x7 << 10) |
| 6291 | 6325 | #define PLANE_CTL_TILED_LINEAR ( 0 << 10) |
| 6292 | 6326 | #define PLANE_CTL_TILED_X ( 1 << 10) |
| 6293 | 6327 | #define PLANE_CTL_TILED_Y ( 4 << 10) |
| 6294 | 6328 | #define PLANE_CTL_TILED_YF ( 5 << 10) |
| 6295 | −#define PLANE_CTL_ALPHA_MASK (0x3 << 4) | |
| 6329 | +#define PLANE_CTL_ALPHA_MASK (0x3 << 4) /* Pre-GLK */ | |
| 6296 | 6330 | #define PLANE_CTL_ALPHA_DISABLE ( 0 << 4) |
| 6297 | 6331 | #define PLANE_CTL_ALPHA_SW_PREMULTIPLY ( 2 << 4) |
| 6298 | 6332 | #define PLANE_CTL_ALPHA_HW_PREMULTIPLY ( 3 << 4) |
| @@ -6332,6 +6366,10 @@ enum { · 33 unmodified lines | ||
| 6332 | 6366 | #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) |
| 6333 | 6367 | #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) |
| 6334 | 6368 | #define PLANE_COLOR_PLANE_GAMMA_DISABLE (1 << 13) |
| 6369 | +#define PLANE_COLOR_ALPHA_MASK (0x3 << 4) | |
| 6370 | +#define PLANE_COLOR_ALPHA_DISABLE (0 << 4) | |
| 6371 | +#define PLANE_COLOR_ALPHA_SW_PREMULTIPLY (2 << 4) | |
| 6372 | +#define PLANE_COLOR_ALPHA_HW_PREMULTIPLY (3 << 4) | |
| 6335 | 6373 | #define _PLANE_BUF_CFG_1_A 0x7027c |
| 6336 | 6374 | #define _PLANE_BUF_CFG_2_A 0x7037c |
| 6337 | 6375 | #define _PLANE_NV12_BUF_CFG_1_A 0x70278 |
| @@ -7774,8 +7812,9 @@ enum { · 1436 unmodified lines | ||
| 7774 | 7812 | #define FORCEWAKE_ACK_MEDIA_GEN9 _MMIO(0x0D88) |
| 7775 | 7813 | #define FORCEWAKE_ACK_RENDER_GEN9 _MMIO(0x0D84) |
| 7776 | 7814 | #define FORCEWAKE_ACK_BLITTER_GEN9 _MMIO(0x130044) |
| 7777 | −#define FORCEWAKE_KERNEL 0x1 | |
| 7778 | −#define FORCEWAKE_USER 0x2 | |
| 7815 | +#define FORCEWAKE_KERNEL BIT(0) | |
| 7816 | +#define FORCEWAKE_USER BIT(1) | |
| 7817 | +#define FORCEWAKE_KERNEL_FALLBACK BIT(15) | |
| 7779 | 7818 | #define FORCEWAKE_MT_ACK _MMIO(0x130040) |
| 7780 | 7819 | #define ECOBUS _MMIO(0xa180) |
| 7781 | 7820 | #define FORCEWAKE_MT_ENABLE (1<<5) |
| @@ -7905,6 +7944,7 @@ enum { · 123 unmodified lines | ||
| 7905 | 7944 | #define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098) |
| 7906 | 7945 | #define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C) |
| 7907 | 7946 | #define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0) |
| 7947 | +#define GEN10_MEDIA_WAKE_RATE_LIMIT _MMIO(0xA0A0) | |
| 7908 | 7948 | #define GEN6_RC_EVALUATION_INTERVAL _MMIO(0xA0A8) |
| 7909 | 7949 | #define GEN6_RC_IDLE_HYSTERSIS _MMIO(0xA0AC) |
| 7910 | 7950 | #define GEN6_RC_SLEEP _MMIO(0xA0B0) |
| @@ -8036,11 +8076,18 @@ enum { · 125 unmodified lines | ||
| 8036 | 8076 | #define CHV_EU311_PG_ENABLE (1<<1) |
| 8037 | 8077 | |
| 8038 | 8078 | #define GEN9_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + (slice)*0x4) |
| 8079 | +#define GEN10_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + ((slice) / 3) * 0x34 + \ | |
| 8080 | + ((slice) % 3) * 0x4) | |
| 8039 | 8081 | #define GEN9_PGCTL_SLICE_ACK (1 << 0) |
| 8040 | 8082 | #define GEN9_PGCTL_SS_ACK(subslice) (1 << (2 + (subslice)*2)) |
| 8083 | +#define GEN10_PGCTL_VALID_SS_MASK(slice) ((slice) == 0 ? 0x7F : 0x1F) | |
| 8041 | 8084 | |
| 8042 | 8085 | #define GEN9_SS01_EU_PGCTL_ACK(slice) _MMIO(0x805c + (slice)*0x8) |
| 8086 | +#define GEN10_SS01_EU_PGCTL_ACK(slice) _MMIO(0x805c + ((slice) / 3) * 0x30 + \ | |
| 8087 | + ((slice) % 3) * 0x8) | |
| 8043 | 8088 | #define GEN9_SS23_EU_PGCTL_ACK(slice) _MMIO(0x8060 + (slice)*0x8) |
| 8089 | +#define GEN10_SS23_EU_PGCTL_ACK(slice) _MMIO(0x8060 + ((slice) / 3) * 0x30 + \ | |
| 8090 | + ((slice) % 3) * 0x8) | |
| 8044 | 8091 | #define GEN9_PGCTL_SSA_EU08_ACK (1 << 0) |
| 8045 | 8092 | #define GEN9_PGCTL_SSA_EU19_ACK (1 << 2) |
| 8046 | 8093 | #define GEN9_PGCTL_SSA_EU210_ACK (1 << 4) |
| @@ -8837,6 +8884,12 @@ enum skl_power_gate { · 790 unmodified lines | ||
| 8837 | 8884 | #define ILK_TIMESTAMP_HI _MMIO(0x70070) |
| 8838 | 8885 | #define IVB_TIMESTAMP_CTR _MMIO(0x44070) |
| 8839 | 8886 | |
| 8887 | +#define GEN9_TIMESTAMP_OVERRIDE _MMIO(0x44074) | |
| 8888 | +#define GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT 0 | |
| 8889 | +#define GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK 0x3ff | |
| 8890 | +#define GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT 12 | |
| 8891 | +#define GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK (0xf << 12) | |
| 8892 | + | |
| 8840 | 8893 | #define _PIPE_FRMTMSTMP_A 0x70048 |
| 8841 | 8894 | #define PIPE_FRMTMSTMP(pipe) \ |
| 8842 | 8895 | _MMIO_PIPE2(pipe, _PIPE_FRMTMSTMP_A) |
| @@ -99,6 +99,6 @@ __printf(2, 3) · 98 unmodified lines | ||
| 99 | 99 | bool __igt_timeout(unsigned long timeout, const char *fmt, ...); |
| 100 | 100 | |
| 101 | 101 | #define igt_timeout(t, fmt, ...) \ |
| 102 | − __igt_timeout((t), KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) | |
| 102 | + __igt_timeout((t), KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) | |
| 103 | 103 | |
| 104 | 104 | #endif /* !__I915_SELFTEST_H__ */ |
| @@ -83,8 +83,11 @@ · 82 unmodified lines | ||
| 83 | 83 | (typeof(ptr))(__v & -BIT(n)); \ |
| 84 | 84 | }) |
| 85 | 85 | |
| 86 | −#define ptr_pack_bits(ptr, bits, n) \ | |
| 87 | − ((typeof(ptr))((unsigned long)(ptr) | (bits))) | |
| 86 | +#define ptr_pack_bits(ptr, bits, n) ({ \ | |
| 87 | + unsigned long __bits = (bits); \ | |
| 88 | + GEM_BUG_ON(__bits & -BIT(n)); \ | |
| 89 | + ((typeof(ptr))((unsigned long)(ptr) | __bits)); \ | |
| 90 | +}) | |
| 88 | 91 | |
| 89 | 92 | #define page_mask_bits(ptr) ptr_mask_bits(ptr, PAGE_SHIFT) |
| 90 | 93 | #define page_unmask_bits(ptr) ptr_unmask_bits(ptr, PAGE_SHIFT) |
| @@ -640,15 +640,17 @@ int __i915_vma_do_pin(struct i915_vma *vma, · 639 unmodified lines | ||
| 640 | 640 | if (ret) |
| 641 | 641 | goto err_unpin; |
| 642 | 642 | } |
| 643 | + GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); | |
| 643 | 644 | |
| 644 | 645 | ret = i915_vma_bind(vma, vma->obj->cache_level, flags); |
| 645 | 646 | if (ret) |
| 646 | 647 | goto err_remove; |
| 647 | 648 | |
| 649 | + GEM_BUG_ON((vma->flags & I915_VMA_BIND_MASK) == 0); | |
| 650 | + | |
| 648 | 651 | if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND) |
| 649 | 652 | __i915_vma_set_map_and_fenceable(vma); |
| 650 | 653 | |
| 651 | − GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); | |
| 652 | 654 | GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags)); |
| 653 | 655 | return 0; |
| 654 | 656 | |
| @@ -656,6 +658,7 @@ err_remove: · 1 unmodified line | ||
| 656 | 658 | if ((bound & I915_VMA_BIND_MASK) == 0) { |
| 657 | 659 | i915_vma_remove(vma); |
| 658 | 660 | GEM_BUG_ON(vma->pages); |
| 661 | + GEM_BUG_ON(vma->flags & I915_VMA_BIND_MASK); | |
| 659 | 662 | } |
| 660 | 663 | err_unpin: |
| 661 | 664 | __i915_vma_unpin(vma); |
| @@ -740,6 +743,7 @@ int i915_vma_unbind(struct i915_vma *vma) · 78 unmodified lines | ||
| 740 | 743 | /* First wait upon any activity as retiring the request may |
| 741 | 744 | * have side-effects such as unpinning or even unbinding this vma. |
| 742 | 745 | */ |
| 746 | + might_sleep(); | |
| 743 | 747 | active = i915_vma_get_active(vma); |
| 744 | 748 | if (active) { |
| 745 | 749 | int idx; |
| @@ -102,13 +102,13 @@ static const struct dp_aud_n_m dp_aud_n_m[] = { · 101 unmodified lines | ||
| 102 | 102 | }; |
| 103 | 103 | |
| 104 | 104 | static const struct dp_aud_n_m * |
| 105 | −audio_config_dp_get_n_m(struct intel_crtc *intel_crtc, int rate) | |
| 105 | +audio_config_dp_get_n_m(const struct intel_crtc_state *crtc_state, int rate) | |
| 106 | 106 | { |
| 107 | 107 | int i; |
| 108 | 108 | |
| 109 | 109 | for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) { |
| 110 | 110 | if (rate == dp_aud_n_m[i].sample_rate && |
| 111 | − intel_crtc->config->port_clock == dp_aud_n_m[i].clock) | |
| 111 | + crtc_state->port_clock == dp_aud_n_m[i].clock) | |
| 112 | 112 | return &dp_aud_n_m[i]; |
| 113 | 113 | } |
| 114 | 114 | |
| @@ -157,8 +157,10 @@ static const struct { · 42 unmodified lines | ||
| 157 | 157 | }; |
| 158 | 158 | |
| 159 | 159 | /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ |
| 160 | −static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode) | |
| 160 | +static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) | |
| 161 | 161 | { |
| 162 | + const struct drm_display_mode *adjusted_mode = | |
| 163 | + &crtc_state->base.adjusted_mode; | |
| 162 | 164 | int i; |
| 163 | 165 | |
| 164 | 166 | for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { |
| @@ -179,9 +181,11 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted · 14 unmodified lines | ||
| 179 | 181 | return hdmi_audio_clock[i].config; |
| 180 | 182 | } |
| 181 | 183 | |
| 182 | −static int audio_config_hdmi_get_n(const struct drm_display_mode *adjusted_mode, | |
| 184 | +static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state, | |
| 183 | 185 | int rate) |
| 184 | 186 | { |
| 187 | + const struct drm_display_mode *adjusted_mode = | |
| 188 | + &crtc_state->base.adjusted_mode; | |
| 185 | 189 | int i; |
| 186 | 190 | |
| 187 | 191 | for (i = 0; i < ARRAY_SIZE(hdmi_aud_ncts); i++) { |
| @@ -220,7 +224,9 @@ static bool intel_eld_uptodate(struct drm_connector *connector, · 32 unmodified lines | ||
| 220 | 224 | return true; |
| 221 | 225 | } |
| 222 | 226 | |
| 223 | −static void g4x_audio_codec_disable(struct intel_encoder *encoder) | |
| 227 | +static void g4x_audio_codec_disable(struct intel_encoder *encoder, | |
| 228 | + const struct intel_crtc_state *old_crtc_state, | |
| 229 | + const struct drm_connector_state *old_conn_state) | |
| 224 | 230 | { |
| 225 | 231 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 226 | 232 | uint32_t eldv, tmp; |
| @@ -239,11 +245,12 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder) · 12 unmodified lines | ||
| 239 | 245 | I915_WRITE(G4X_AUD_CNTL_ST, tmp); |
| 240 | 246 | } |
| 241 | 247 | |
| 242 | −static void g4x_audio_codec_enable(struct drm_connector *connector, | |
| 243 | − struct intel_encoder *encoder, | |
| 244 | − const struct drm_display_mode *adjusted_mode) | |
| 248 | +static void g4x_audio_codec_enable(struct intel_encoder *encoder, | |
| 249 | + const struct intel_crtc_state *crtc_state, | |
| 250 | + const struct drm_connector_state *conn_state) | |
| 245 | 251 | { |
| 246 | − struct drm_i915_private *dev_priv = to_i915(connector->dev); | |
| 252 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 253 | + struct drm_connector *connector = conn_state->connector; | |
| 247 | 254 | uint8_t *eld = connector->eld; |
| 248 | 255 | uint32_t eldv; |
| 249 | 256 | uint32_t tmp; |
| @@ -279,16 +286,20 @@ static void g4x_audio_codec_enable(struct drm_connector *connector, · 29 unmodified lines | ||
| 279 | 286 | } |
| 280 | 287 | |
| 281 | 288 | static void |
| 282 | −hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | |
| 283 | − const struct drm_display_mode *adjusted_mode) | |
| 289 | +hsw_dp_audio_config_update(struct intel_encoder *encoder, | |
| 290 | + const struct intel_crtc_state *crtc_state) | |
| 284 | 291 | { |
| 285 | − struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | |
| 292 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 286 | 293 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 287 | − int rate = acomp ? acomp->aud_sample_rate[port] : 0; | |
| 288 | − const struct dp_aud_n_m *nm = audio_config_dp_get_n_m(intel_crtc, rate); | |
| 289 | − enum pipe pipe = intel_crtc->pipe; | |
| 294 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 295 | + enum port port = encoder->port; | |
| 296 | + enum pipe pipe = crtc->pipe; | |
| 297 | + const struct dp_aud_n_m *nm; | |
| 298 | + int rate; | |
| 290 | 299 | u32 tmp; |
| 291 | 300 | |
| 301 | + rate = acomp ? acomp->aud_sample_rate[port] : 0; | |
| 302 | + nm = audio_config_dp_get_n_m(crtc_state, rate); | |
| 292 | 303 | if (nm) |
| 293 | 304 | DRM_DEBUG_KMS("using Maud %u, Naud %u\n", nm->m, nm->n); |
| 294 | 305 | else |
| @@ -323,23 +334,26 @@ hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port, · 28 unmodified lines | ||
| 323 | 334 | } |
| 324 | 335 | |
| 325 | 336 | static void |
| 326 | −hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | |
| 327 | − const struct drm_display_mode *adjusted_mode) | |
| 337 | +hsw_hdmi_audio_config_update(struct intel_encoder *encoder, | |
| 338 | + const struct intel_crtc_state *crtc_state) | |
| 328 | 339 | { |
| 329 | − struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | |
| 340 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 330 | 341 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 331 | − int rate = acomp ? acomp->aud_sample_rate[port] : 0; | |
| 332 | − enum pipe pipe = intel_crtc->pipe; | |
| 333 | − int n; | |
| 342 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 343 | + enum port port = encoder->port; | |
| 344 | + enum pipe pipe = crtc->pipe; | |
| 345 | + int n, rate; | |
| 334 | 346 | u32 tmp; |
| 335 | 347 | |
| 348 | + rate = acomp ? acomp->aud_sample_rate[port] : 0; | |
| 349 | + | |
| 336 | 350 | tmp = I915_READ(HSW_AUD_CFG(pipe)); |
| 337 | 351 | tmp &= ~AUD_CONFIG_N_VALUE_INDEX; |
| 338 | 352 | tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; |
| 339 | 353 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
| 340 | − tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); | |
| 354 | + tmp |= audio_config_hdmi_pixel_clock(crtc_state); | |
| 341 | 355 | |
| 342 | − n = audio_config_hdmi_get_n(adjusted_mode, rate); | |
| 356 | + n = audio_config_hdmi_get_n(crtc_state, rate); | |
| 343 | 357 | if (n != 0) { |
| 344 | 358 | DRM_DEBUG_KMS("using N %d\n", n); |
| 345 | 359 | |
| @@ -363,20 +377,22 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, · 17 unmodified lines | ||
| 363 | 377 | } |
| 364 | 378 | |
| 365 | 379 | static void |
| 366 | −hsw_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | |
| 367 | − const struct drm_display_mode *adjusted_mode) | |
| 380 | +hsw_audio_config_update(struct intel_encoder *encoder, | |
| 381 | + const struct intel_crtc_state *crtc_state) | |
| 368 | 382 | { |
| 369 | − if (intel_crtc_has_dp_encoder(intel_crtc->config)) | |
| 370 | − hsw_dp_audio_config_update(intel_crtc, port, adjusted_mode); | |
| 383 | + if (intel_crtc_has_dp_encoder(crtc_state)) | |
| 384 | + hsw_dp_audio_config_update(encoder, crtc_state); | |
| 371 | 385 | else |
| 372 | − hsw_hdmi_audio_config_update(intel_crtc, port, adjusted_mode); | |
| 386 | + hsw_hdmi_audio_config_update(encoder, crtc_state); | |
| 373 | 387 | } |
| 374 | 388 | |
| 375 | −static void hsw_audio_codec_disable(struct intel_encoder *encoder) | |
| 389 | +static void hsw_audio_codec_disable(struct intel_encoder *encoder, | |
| 390 | + const struct intel_crtc_state *old_crtc_state, | |
| 391 | + const struct drm_connector_state *old_conn_state) | |
| 376 | 392 | { |
| 377 | 393 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 378 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 379 | − enum pipe pipe = intel_crtc->pipe; | |
| 394 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 395 | + enum pipe pipe = crtc->pipe; | |
| 380 | 396 | uint32_t tmp; |
| 381 | 397 | |
| 382 | 398 | DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe)); |
| @@ -389,7 +405,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder) · 6 unmodified lines | ||
| 389 | 405 | tmp |= AUD_CONFIG_N_PROG_ENABLE; |
| 390 | 406 | tmp &= ~AUD_CONFIG_UPPER_N_MASK; |
| 391 | 407 | tmp &= ~AUD_CONFIG_LOWER_N_MASK; |
| 392 | − if (intel_crtc_has_dp_encoder(intel_crtc->config)) | |
| 408 | + if (intel_crtc_has_dp_encoder(old_crtc_state)) | |
| 393 | 409 | tmp |= AUD_CONFIG_N_VALUE_INDEX; |
| 394 | 410 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); |
| 395 | 411 | |
| @@ -402,14 +418,14 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder) · 6 unmodified lines | ||
| 402 | 418 | mutex_unlock(&dev_priv->av_mutex); |
| 403 | 419 | } |
| 404 | 420 | |
| 405 | −static void hsw_audio_codec_enable(struct drm_connector *connector, | |
| 406 | − struct intel_encoder *intel_encoder, | |
| 407 | − const struct drm_display_mode *adjusted_mode) | |
| 421 | +static void hsw_audio_codec_enable(struct intel_encoder *encoder, | |
| 422 | + const struct intel_crtc_state *crtc_state, | |
| 423 | + const struct drm_connector_state *conn_state) | |
| 408 | 424 | { |
| 409 | − struct drm_i915_private *dev_priv = to_i915(connector->dev); | |
| 410 | − struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); | |
| 411 | − enum pipe pipe = intel_crtc->pipe; | |
| 412 | − enum port port = intel_encoder->port; | |
| 425 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 426 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 427 | + struct drm_connector *connector = conn_state->connector; | |
| 428 | + enum pipe pipe = crtc->pipe; | |
| 413 | 429 | const uint8_t *eld = connector->eld; |
| 414 | 430 | uint32_t tmp; |
| 415 | 431 | int len, i; |
| @@ -448,17 +464,19 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, · 32 unmodified lines | ||
| 448 | 464 | I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
| 449 | 465 | |
| 450 | 466 | /* Enable timestamps */ |
| 451 | − hsw_audio_config_update(intel_crtc, port, adjusted_mode); | |
| 467 | + hsw_audio_config_update(encoder, crtc_state); | |
| 452 | 468 | |
| 453 | 469 | mutex_unlock(&dev_priv->av_mutex); |
| 454 | 470 | } |
| 455 | 471 | |
| 456 | −static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder) | |
| 472 | +static void ilk_audio_codec_disable(struct intel_encoder *encoder, | |
| 473 | + const struct intel_crtc_state *old_crtc_state, | |
| 474 | + const struct drm_connector_state *old_conn_state) | |
| 457 | 475 | { |
| 458 | − struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); | |
| 459 | − struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); | |
| 460 | − enum pipe pipe = intel_crtc->pipe; | |
| 461 | − enum port port = intel_encoder->port; | |
| 476 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 477 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 478 | + enum pipe pipe = crtc->pipe; | |
| 479 | + enum port port = encoder->port; | |
| 462 | 480 | uint32_t tmp, eldv; |
| 463 | 481 | i915_reg_t aud_config, aud_cntrl_st2; |
| 464 | 482 | |
| @@ -485,7 +503,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder) · 20 unmodified lines | ||
| 485 | 503 | tmp |= AUD_CONFIG_N_PROG_ENABLE; |
| 486 | 504 | tmp &= ~AUD_CONFIG_UPPER_N_MASK; |
| 487 | 505 | tmp &= ~AUD_CONFIG_LOWER_N_MASK; |
| 488 | − if (intel_crtc_has_dp_encoder(intel_crtc->config)) | |
| 506 | + if (intel_crtc_has_dp_encoder(old_crtc_state)) | |
| 489 | 507 | tmp |= AUD_CONFIG_N_VALUE_INDEX; |
| 490 | 508 | I915_WRITE(aud_config, tmp); |
| 491 | 509 | |
| @@ -497,14 +515,15 @@ static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder) · 5 unmodified lines | ||
| 497 | 515 | I915_WRITE(aud_cntrl_st2, tmp); |
| 498 | 516 | } |
| 499 | 517 | |
| 500 | −static void ilk_audio_codec_enable(struct drm_connector *connector, | |
| 501 | − struct intel_encoder *intel_encoder, | |
| 502 | − const struct drm_display_mode *adjusted_mode) | |
| 518 | +static void ilk_audio_codec_enable(struct intel_encoder *encoder, | |
| 519 | + const struct intel_crtc_state *crtc_state, | |
| 520 | + const struct drm_connector_state *conn_state) | |
| 503 | 521 | { |
| 504 | − struct drm_i915_private *dev_priv = to_i915(connector->dev); | |
| 505 | − struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); | |
| 506 | − enum pipe pipe = intel_crtc->pipe; | |
| 507 | − enum port port = intel_encoder->port; | |
| 522 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 523 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 524 | + struct drm_connector *connector = conn_state->connector; | |
| 525 | + enum pipe pipe = crtc->pipe; | |
| 526 | + enum port port = encoder->port; | |
| 508 | 527 | uint8_t *eld = connector->eld; |
| 509 | 528 | uint32_t tmp, eldv; |
| 510 | 529 | int len, i; |
| @@ -568,36 +587,36 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, · 57 unmodified lines | ||
| 568 | 587 | tmp &= ~AUD_CONFIG_N_VALUE_INDEX; |
| 569 | 588 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
| 570 | 589 | tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; |
| 571 | − if (intel_crtc_has_dp_encoder(intel_crtc->config)) | |
| 590 | + if (intel_crtc_has_dp_encoder(crtc_state)) | |
| 572 | 591 | tmp |= AUD_CONFIG_N_VALUE_INDEX; |
| 573 | 592 | else |
| 574 | − tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); | |
| 593 | + tmp |= audio_config_hdmi_pixel_clock(crtc_state); | |
| 575 | 594 | I915_WRITE(aud_config, tmp); |
| 576 | 595 | } |
| 577 | 596 | |
| 578 | 597 | /** |
| 579 | 598 | * intel_audio_codec_enable - Enable the audio codec for HD audio |
| 580 | − * @intel_encoder: encoder on which to enable audio | |
| 599 | + * @encoder: encoder on which to enable audio | |
| 581 | 600 | * @crtc_state: pointer to the current crtc state. |
| 582 | 601 | * @conn_state: pointer to the current connector state. |
| 583 | 602 | * |
| 584 | 603 | * The enable sequences may only be performed after enabling the transcoder and |
| 585 | 604 | * port, and after completed link training. |
| 586 | 605 | */ |
| 587 | −void intel_audio_codec_enable(struct intel_encoder *intel_encoder, | |
| 606 | +void intel_audio_codec_enable(struct intel_encoder *encoder, | |
| 588 | 607 | const struct intel_crtc_state *crtc_state, |
| 589 | 608 | const struct drm_connector_state *conn_state) |
| 590 | 609 | { |
| 591 | − struct drm_encoder *encoder = &intel_encoder->base; | |
| 592 | − const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; | |
| 593 | − struct drm_connector *connector; | |
| 594 | − struct drm_i915_private *dev_priv = to_i915(encoder->dev); | |
| 610 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 595 | 611 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 596 | − enum port port = intel_encoder->port; | |
| 597 | − enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe; | |
| 612 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 613 | + struct drm_connector *connector = conn_state->connector; | |
| 614 | + const struct drm_display_mode *adjusted_mode = | |
| 615 | + &crtc_state->base.adjusted_mode; | |
| 616 | + enum port port = encoder->port; | |
| 617 | + enum pipe pipe = crtc->pipe; | |
| 598 | 618 | |
| 599 | − connector = conn_state->connector; | |
| 600 | − if (!connector || !connector->eld[0]) | |
| 619 | + if (!connector->eld[0]) | |
| 601 | 620 | return; |
| 602 | 621 | |
| 603 | 622 | DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", |
| @@ -609,19 +628,20 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder, · 5 unmodified lines | ||
| 609 | 628 | connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; |
| 610 | 629 | |
| 611 | 630 | if (dev_priv->display.audio_codec_enable) |
| 612 | − dev_priv->display.audio_codec_enable(connector, intel_encoder, | |
| 613 | − adjusted_mode); | |
| 631 | + dev_priv->display.audio_codec_enable(encoder, | |
| 632 | + crtc_state, | |
| 633 | + conn_state); | |
| 614 | 634 | |
| 615 | 635 | mutex_lock(&dev_priv->av_mutex); |
| 616 | − intel_encoder->audio_connector = connector; | |
| 636 | + encoder->audio_connector = connector; | |
| 617 | 637 | |
| 618 | 638 | /* referred in audio callbacks */ |
| 619 | − dev_priv->av_enc_map[pipe] = intel_encoder; | |
| 639 | + dev_priv->av_enc_map[pipe] = encoder; | |
| 620 | 640 | mutex_unlock(&dev_priv->av_mutex); |
| 621 | 641 | |
| 622 | 642 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { |
| 623 | 643 | /* audio drivers expect pipe = -1 to indicate Non-MST cases */ |
| 624 | − if (intel_encoder->type != INTEL_OUTPUT_DP_MST) | |
| 644 | + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) | |
| 625 | 645 | pipe = -1; |
| 626 | 646 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, |
| 627 | 647 | (int) port, (int) pipe); |
| @@ -629,36 +649,41 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder, · 1 unmodified line | ||
| 629 | 649 | |
| 630 | 650 | intel_lpe_audio_notify(dev_priv, pipe, port, connector->eld, |
| 631 | 651 | crtc_state->port_clock, |
| 632 | − intel_encoder->type == INTEL_OUTPUT_DP); | |
| 652 | + intel_crtc_has_dp_encoder(crtc_state)); | |
| 633 | 653 | } |
| 634 | 654 | |
| 635 | 655 | /** |
| 636 | 656 | * intel_audio_codec_disable - Disable the audio codec for HD audio |
| 637 | − * @intel_encoder: encoder on which to disable audio | |
| 657 | + * @encoder: encoder on which to disable audio | |
| 658 | + * @old_crtc_state: pointer to the old crtc state. | |
| 659 | + * @old_conn_state: pointer to the old connector state. | |
| 638 | 660 | * |
| 639 | 661 | * The disable sequences must be performed before disabling the transcoder or |
| 640 | 662 | * port. |
| 641 | 663 | */ |
| 642 | −void intel_audio_codec_disable(struct intel_encoder *intel_encoder) | |
| 664 | +void intel_audio_codec_disable(struct intel_encoder *encoder, | |
| 665 | + const struct intel_crtc_state *old_crtc_state, | |
| 666 | + const struct drm_connector_state *old_conn_state) | |
| 643 | 667 | { |
| 644 | − struct drm_encoder *encoder = &intel_encoder->base; | |
| 645 | − struct drm_i915_private *dev_priv = to_i915(encoder->dev); | |
| 668 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 646 | 669 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 647 | − enum port port = intel_encoder->port; | |
| 648 | − struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); | |
| 670 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 671 | + enum port port = encoder->port; | |
| 649 | 672 | enum pipe pipe = crtc->pipe; |
| 650 | 673 | |
| 651 | 674 | if (dev_priv->display.audio_codec_disable) |
| 652 | − dev_priv->display.audio_codec_disable(intel_encoder); | |
| 675 | + dev_priv->display.audio_codec_disable(encoder, | |
| 676 | + old_crtc_state, | |
| 677 | + old_conn_state); | |
| 653 | 678 | |
| 654 | 679 | mutex_lock(&dev_priv->av_mutex); |
| 655 | − intel_encoder->audio_connector = NULL; | |
| 680 | + encoder->audio_connector = NULL; | |
| 656 | 681 | dev_priv->av_enc_map[pipe] = NULL; |
| 657 | 682 | mutex_unlock(&dev_priv->av_mutex); |
| 658 | 683 | |
| 659 | 684 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { |
| 660 | 685 | /* audio drivers expect pipe = -1 to indicate Non-MST cases */ |
| 661 | − if (intel_encoder->type != INTEL_OUTPUT_DP_MST) | |
| 686 | + if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) | |
| 662 | 687 | pipe = -1; |
| 663 | 688 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, |
| 664 | 689 | (int) port, (int) pipe); |
| @@ -793,10 +818,9 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, · 128 unmodified lines | ||
| 793 | 818 | int pipe, int rate) |
| 794 | 819 | { |
| 795 | 820 | struct drm_i915_private *dev_priv = kdev_to_i915(kdev); |
| 796 | − struct intel_encoder *intel_encoder; | |
| 797 | − struct intel_crtc *crtc; | |
| 798 | − struct drm_display_mode *adjusted_mode; | |
| 799 | 821 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 822 | + struct intel_encoder *encoder; | |
| 823 | + struct intel_crtc *crtc; | |
| 800 | 824 | int err = 0; |
| 801 | 825 | |
| 802 | 826 | if (!HAS_DDI(dev_priv)) |
| @@ -806,23 +830,19 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, · 3 unmodified lines | ||
| 806 | 830 | mutex_lock(&dev_priv->av_mutex); |
| 807 | 831 | |
| 808 | 832 | /* 1. get the pipe */ |
| 809 | − intel_encoder = get_saved_enc(dev_priv, port, pipe); | |
| 810 | − if (!intel_encoder || !intel_encoder->base.crtc) { | |
| 833 | + encoder = get_saved_enc(dev_priv, port, pipe); | |
| 834 | + if (!encoder || !encoder->base.crtc) { | |
| 811 | 835 | DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); |
| 812 | 836 | err = -ENODEV; |
| 813 | 837 | goto unlock; |
| 814 | 838 | } |
| 815 | 839 | |
| 816 | − /* pipe passed from the audio driver will be -1 for Non-MST case */ | |
| 817 | − crtc = to_intel_crtc(intel_encoder->base.crtc); | |
| 818 | − pipe = crtc->pipe; | |
| 819 | − | |
| 820 | − adjusted_mode = &crtc->config->base.adjusted_mode; | |
| 840 | + crtc = to_intel_crtc(encoder->base.crtc); | |
| 821 | 841 | |
| 822 | 842 | /* port must be valid now, otherwise the pipe will be invalid */ |
| 823 | 843 | acomp->aud_sample_rate[port] = rate; |
| 824 | 844 | |
| 825 | − hsw_audio_config_update(crtc, port, adjusted_mode); | |
| 845 | + hsw_audio_config_update(encoder, crtc->config); | |
| 826 | 846 | |
| 827 | 847 | unlock: |
| 828 | 848 | mutex_unlock(&dev_priv->av_mutex); |
| @@ -1234,6 +1234,30 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, · 1233 unmodified lines | ||
| 1234 | 1234 | info->hdmi_level_shift = hdmi_level_shift; |
| 1235 | 1235 | } |
| 1236 | 1236 | |
| 1237 | + if (bdb_version >= 204) { | |
| 1238 | + int max_tmds_clock; | |
| 1239 | + | |
| 1240 | + switch (child->hdmi_max_data_rate) { | |
| 1241 | + default: | |
| 1242 | + MISSING_CASE(child->hdmi_max_data_rate); | |
| 1243 | + /* fall through */ | |
| 1244 | + case HDMI_MAX_DATA_RATE_PLATFORM: | |
| 1245 | + max_tmds_clock = 0; | |
| 1246 | + break; | |
| 1247 | + case HDMI_MAX_DATA_RATE_297: | |
| 1248 | + max_tmds_clock = 297000; | |
| 1249 | + break; | |
| 1250 | + case HDMI_MAX_DATA_RATE_165: | |
| 1251 | + max_tmds_clock = 165000; | |
| 1252 | + break; | |
| 1253 | + } | |
| 1254 | + | |
| 1255 | + if (max_tmds_clock) | |
| 1256 | + DRM_DEBUG_KMS("VBT HDMI max TMDS clock for port %c: %d kHz\n", | |
| 1257 | + port_name(port), max_tmds_clock); | |
| 1258 | + info->max_tmds_clock = max_tmds_clock; | |
| 1259 | + } | |
| 1260 | + | |
| 1237 | 1261 | /* Parse the I_boost config for SKL and above */ |
| 1238 | 1262 | if (bdb_version >= 196 && child->iboost) { |
| 1239 | 1263 | info->dp_boost_level = translate_iboost(child->dp_iboost_level); |
| @@ -123,7 +123,7 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t) · 122 unmodified lines | ||
| 123 | 123 | */ |
| 124 | 124 | |
| 125 | 125 | spin_lock_irq(&b->irq_lock); |
| 126 | − if (!__intel_breadcrumbs_wakeup(b)) | |
| 126 | + if (b->irq_armed && !__intel_breadcrumbs_wakeup(b)) | |
| 127 | 127 | __intel_engine_disarm_breadcrumbs(engine); |
| 128 | 128 | spin_unlock_irq(&b->irq_lock); |
| 129 | 129 | if (!b->irq_armed) |
| @@ -145,6 +145,14 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t) · 15 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | static void irq_enable(struct intel_engine_cs *engine) |
| 147 | 147 | { |
| 148 | + /* | |
| 149 | + * FIXME: Ideally we want this on the API boundary, but for the | |
| 150 | + * sake of testing with mock breadcrumbs (no HW so unable to | |
| 151 | + * enable irqs) we place it deep within the bowels, at the point | |
| 152 | + * of no return. | |
| 153 | + */ | |
| 154 | + GEM_BUG_ON(!intel_irqs_enabled(engine->i915)); | |
| 155 | + | |
| 148 | 156 | /* Enabling the IRQ may miss the generation of the interrupt, but |
| 149 | 157 | * we still need to force the barrier before reading the seqno, |
| 150 | 158 | * just in case. |
| @@ -171,15 +179,37 @@ void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) · 20 unmodified lines | ||
| 171 | 179 | |
| 172 | 180 | lockdep_assert_held(&b->irq_lock); |
| 173 | 181 | GEM_BUG_ON(b->irq_wait); |
| 182 | + GEM_BUG_ON(!b->irq_armed); | |
| 174 | 183 | |
| 175 | − if (b->irq_enabled) { | |
| 184 | + GEM_BUG_ON(!b->irq_enabled); | |
| 185 | + if (!--b->irq_enabled) | |
| 176 | 186 | irq_disable(engine); |
| 177 | − b->irq_enabled = false; | |
| 178 | − } | |
| 179 | 187 | |
| 180 | 188 | b->irq_armed = false; |
| 181 | 189 | } |
| 182 | 190 | |
| 191 | +void intel_engine_pin_breadcrumbs_irq(struct intel_engine_cs *engine) | |
| 192 | +{ | |
| 193 | + struct intel_breadcrumbs *b = &engine->breadcrumbs; | |
| 194 | + | |
| 195 | + spin_lock_irq(&b->irq_lock); | |
| 196 | + if (!b->irq_enabled++) | |
| 197 | + irq_enable(engine); | |
| 198 | + GEM_BUG_ON(!b->irq_enabled); /* no overflow! */ | |
| 199 | + spin_unlock_irq(&b->irq_lock); | |
| 200 | +} | |
| 201 | + | |
| 202 | +void intel_engine_unpin_breadcrumbs_irq(struct intel_engine_cs *engine) | |
| 203 | +{ | |
| 204 | + struct intel_breadcrumbs *b = &engine->breadcrumbs; | |
| 205 | + | |
| 206 | + spin_lock_irq(&b->irq_lock); | |
| 207 | + GEM_BUG_ON(!b->irq_enabled); /* no underflow! */ | |
| 208 | + if (!--b->irq_enabled) | |
| 209 | + irq_disable(engine); | |
| 210 | + spin_unlock_irq(&b->irq_lock); | |
| 211 | +} | |
| 212 | + | |
| 183 | 213 | void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) |
| 184 | 214 | { |
| 185 | 215 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
| @@ -197,7 +227,8 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) · 11 unmodified lines | ||
| 197 | 227 | |
| 198 | 228 | spin_lock(&b->irq_lock); |
| 199 | 229 | first = fetch_and_zero(&b->irq_wait); |
| 200 | − __intel_engine_disarm_breadcrumbs(engine); | |
| 230 | + if (b->irq_armed) | |
| 231 | + __intel_engine_disarm_breadcrumbs(engine); | |
| 201 | 232 | spin_unlock(&b->irq_lock); |
| 202 | 233 | |
| 203 | 234 | rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) { |
| @@ -241,6 +272,7 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b) · 37 unmodified lines | ||
| 241 | 272 | struct intel_engine_cs *engine = |
| 242 | 273 | container_of(b, struct intel_engine_cs, breadcrumbs); |
| 243 | 274 | struct drm_i915_private *i915 = engine->i915; |
| 275 | + bool enabled; | |
| 244 | 276 | |
| 245 | 277 | lockdep_assert_held(&b->irq_lock); |
| 246 | 278 | if (b->irq_armed) |
| @@ -252,7 +284,6 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b) · 5 unmodified lines | ||
| 252 | 284 | * the irq. |
| 253 | 285 | */ |
| 254 | 286 | b->irq_armed = true; |
| 255 | − GEM_BUG_ON(b->irq_enabled); | |
| 256 | 287 | |
| 257 | 288 | if (I915_SELFTEST_ONLY(b->mock)) { |
| 258 | 289 | /* For our mock objects we want to avoid interaction |
| @@ -273,14 +304,15 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b) · 14 unmodified lines | ||
| 273 | 304 | */ |
| 274 | 305 | |
| 275 | 306 | /* No interrupts? Kick the waiter every jiffie! */ |
| 276 | − if (intel_irqs_enabled(i915)) { | |
| 277 | − if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings)) | |
| 278 | − irq_enable(engine); | |
| 279 | − b->irq_enabled = true; | |
| 307 | + enabled = false; | |
| 308 | + if (!b->irq_enabled++ && | |
| 309 | + !test_bit(engine->id, &i915->gpu_error.test_irq_rings)) { | |
| 310 | + irq_enable(engine); | |
| 311 | + enabled = true; | |
| 280 | 312 | } |
| 281 | 313 | |
| 282 | 314 | enable_fake_irq(b); |
| 283 | − return true; | |
| 315 | + return enabled; | |
| 284 | 316 | } |
| 285 | 317 | |
| 286 | 318 | static inline struct intel_wait *to_wait(struct rb_node *node) |
| @@ -437,13 +437,45 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk) · 436 unmodified lines | ||
| 437 | 437 | return 200000; |
| 438 | 438 | } |
| 439 | 439 | |
| 440 | +static u8 vlv_calc_voltage_level(struct drm_i915_private *dev_priv, int cdclk) | |
| 441 | +{ | |
| 442 | + if (IS_VALLEYVIEW(dev_priv)) { | |
| 443 | + if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ | |
| 444 | + return 2; | |
| 445 | + else if (cdclk >= 266667) | |
| 446 | + return 1; | |
| 447 | + else | |
| 448 | + return 0; | |
| 449 | + } else { | |
| 450 | + /* | |
| 451 | + * Specs are full of misinformation, but testing on actual | |
| 452 | + * hardware has shown that we just need to write the desired | |
| 453 | + * CCK divider into the Punit register. | |
| 454 | + */ | |
| 455 | + return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1; | |
| 456 | + } | |
| 457 | +} | |
| 458 | + | |
| 440 | 459 | static void vlv_get_cdclk(struct drm_i915_private *dev_priv, |
| 441 | 460 | struct intel_cdclk_state *cdclk_state) |
| 442 | 461 | { |
| 462 | + u32 val; | |
| 463 | + | |
| 443 | 464 | cdclk_state->vco = vlv_get_hpll_vco(dev_priv); |
| 444 | 465 | cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk", |
| 445 | 466 | CCK_DISPLAY_CLOCK_CONTROL, |
| 446 | 467 | cdclk_state->vco); |
| 468 | + | |
| 469 | + mutex_lock(&dev_priv->pcu_lock); | |
| 470 | + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); | |
| 471 | + mutex_unlock(&dev_priv->pcu_lock); | |
| 472 | + | |
| 473 | + if (IS_VALLEYVIEW(dev_priv)) | |
| 474 | + cdclk_state->voltage_level = (val & DSPFREQGUAR_MASK) >> | |
| 475 | + DSPFREQGUAR_SHIFT; | |
| 476 | + else | |
| 477 | + cdclk_state->voltage_level = (val & DSPFREQGUAR_MASK_CHV) >> | |
| 478 | + DSPFREQGUAR_SHIFT_CHV; | |
| 447 | 479 | } |
| 448 | 480 | |
| 449 | 481 | static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) |
| @@ -486,7 +518,19 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, · 36 unmodified lines | ||
| 486 | 518 | const struct intel_cdclk_state *cdclk_state) |
| 487 | 519 | { |
| 488 | 520 | int cdclk = cdclk_state->cdclk; |
| 489 | − u32 val, cmd; | |
| 521 | + u32 val, cmd = cdclk_state->voltage_level; | |
| 522 | + | |
| 523 | + switch (cdclk) { | |
| 524 | + case 400000: | |
| 525 | + case 333333: | |
| 526 | + case 320000: | |
| 527 | + case 266667: | |
| 528 | + case 200000: | |
| 529 | + break; | |
| 530 | + default: | |
| 531 | + MISSING_CASE(cdclk); | |
| 532 | + return; | |
| 533 | + } | |
| 490 | 534 | |
| 491 | 535 | /* There are cases where we can end up here with power domains |
| 492 | 536 | * off and a CDCLK frequency other than the minimum, like when |
| @@ -496,13 +540,6 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, · 3 unmodified lines | ||
| 496 | 540 | */ |
| 497 | 541 | intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); |
| 498 | 542 | |
| 499 | − if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ | |
| 500 | − cmd = 2; | |
| 501 | − else if (cdclk == 266667) | |
| 502 | − cmd = 1; | |
| 503 | − else | |
| 504 | − cmd = 0; | |
| 505 | − | |
| 506 | 543 | mutex_lock(&dev_priv->pcu_lock); |
| 507 | 544 | val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); |
| 508 | 545 | val &= ~DSPFREQGUAR_MASK; |
| @@ -562,7 +599,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, · 53 unmodified lines | ||
| 562 | 599 | const struct intel_cdclk_state *cdclk_state) |
| 563 | 600 | { |
| 564 | 601 | int cdclk = cdclk_state->cdclk; |
| 565 | − u32 val, cmd; | |
| 602 | + u32 val, cmd = cdclk_state->voltage_level; | |
| 566 | 603 | |
| 567 | 604 | switch (cdclk) { |
| 568 | 605 | case 333333: |
| @@ -583,13 +620,6 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, · 14 unmodified lines | ||
| 583 | 620 | */ |
| 584 | 621 | intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); |
| 585 | 622 | |
| 586 | − /* | |
| 587 | − * Specs are full of misinformation, but testing on actual | |
| 588 | − * hardware has shown that we just need to write the desired | |
| 589 | − * CCK divider into the Punit register. | |
| 590 | − */ | |
| 591 | − cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1; | |
| 592 | − | |
| 593 | 623 | mutex_lock(&dev_priv->pcu_lock); |
| 594 | 624 | val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); |
| 595 | 625 | val &= ~DSPFREQGUAR_MASK_CHV; |
| @@ -621,6 +651,21 @@ static int bdw_calc_cdclk(int min_cdclk) · 25 unmodified lines | ||
| 621 | 651 | return 337500; |
| 622 | 652 | } |
| 623 | 653 | |
| 654 | +static u8 bdw_calc_voltage_level(int cdclk) | |
| 655 | +{ | |
| 656 | + switch (cdclk) { | |
| 657 | + default: | |
| 658 | + case 337500: | |
| 659 | + return 2; | |
| 660 | + case 450000: | |
| 661 | + return 0; | |
| 662 | + case 540000: | |
| 663 | + return 1; | |
| 664 | + case 675000: | |
| 665 | + return 3; | |
| 666 | + } | |
| 667 | +} | |
| 668 | + | |
| 624 | 669 | static void bdw_get_cdclk(struct drm_i915_private *dev_priv, |
| 625 | 670 | struct intel_cdclk_state *cdclk_state) |
| 626 | 671 | { |
| @@ -639,13 +684,20 @@ static void bdw_get_cdclk(struct drm_i915_private *dev_priv, · 12 unmodified lines | ||
| 639 | 684 | cdclk_state->cdclk = 337500; |
| 640 | 685 | else |
| 641 | 686 | cdclk_state->cdclk = 675000; |
| 687 | + | |
| 688 | + /* | |
| 689 | + * Can't read this out :( Let's assume it's | |
| 690 | + * at least what the CDCLK frequency requires. | |
| 691 | + */ | |
| 692 | + cdclk_state->voltage_level = | |
| 693 | + bdw_calc_voltage_level(cdclk_state->cdclk); | |
| 642 | 694 | } |
| 643 | 695 | |
| 644 | 696 | static void bdw_set_cdclk(struct drm_i915_private *dev_priv, |
| 645 | 697 | const struct intel_cdclk_state *cdclk_state) |
| 646 | 698 | { |
| 647 | 699 | int cdclk = cdclk_state->cdclk; |
| 648 | − uint32_t val, data; | |
| 700 | + uint32_t val; | |
| 649 | 701 | int ret; |
| 650 | 702 | |
| 651 | 703 | if (WARN((I915_READ(LCPLL_CTL) & |
| @@ -681,25 +733,21 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, · 29 unmodified lines | ||
| 681 | 733 | val &= ~LCPLL_CLK_FREQ_MASK; |
| 682 | 734 | |
| 683 | 735 | switch (cdclk) { |
| 736 | + default: | |
| 737 | + MISSING_CASE(cdclk); | |
| 738 | + /* fall through */ | |
| 739 | + case 337500: | |
| 740 | + val |= LCPLL_CLK_FREQ_337_5_BDW; | |
| 741 | + break; | |
| 684 | 742 | case 450000: |
| 685 | 743 | val |= LCPLL_CLK_FREQ_450; |
| 686 | − data = 0; | |
| 687 | 744 | break; |
| 688 | 745 | case 540000: |
| 689 | 746 | val |= LCPLL_CLK_FREQ_54O_BDW; |
| 690 | − data = 1; | |
| 691 | − break; | |
| 692 | − case 337500: | |
| 693 | − val |= LCPLL_CLK_FREQ_337_5_BDW; | |
| 694 | − data = 2; | |
| 695 | 747 | break; |
| 696 | 748 | case 675000: |
| 697 | 749 | val |= LCPLL_CLK_FREQ_675_BDW; |
| 698 | − data = 3; | |
| 699 | 750 | break; |
| 700 | − default: | |
| 701 | − WARN(1, "invalid cdclk frequency\n"); | |
| 702 | − return; | |
| 703 | 751 | } |
| 704 | 752 | |
| 705 | 753 | I915_WRITE(LCPLL_CTL, val); |
| @@ -713,16 +761,13 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, · 7 unmodified lines | ||
| 713 | 761 | DRM_ERROR("Switching back to LCPLL failed\n"); |
| 714 | 762 | |
| 715 | 763 | mutex_lock(&dev_priv->pcu_lock); |
| 716 | − sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data); | |
| 764 | + sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, | |
| 765 | + cdclk_state->voltage_level); | |
| 717 | 766 | mutex_unlock(&dev_priv->pcu_lock); |
| 718 | 767 | |
| 719 | 768 | I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1); |
| 720 | 769 | |
| 721 | 770 | intel_update_cdclk(dev_priv); |
| 722 | − | |
| 723 | − WARN(cdclk != dev_priv->cdclk.hw.cdclk, | |
| 724 | − "cdclk requested %d kHz but got %d kHz\n", | |
| 725 | − cdclk, dev_priv->cdclk.hw.cdclk); | |
| 726 | 771 | } |
| 727 | 772 | |
| 728 | 773 | static int skl_calc_cdclk(int min_cdclk, int vco) |
| @@ -748,6 +793,24 @@ static int skl_calc_cdclk(int min_cdclk, int vco) · 19 unmodified lines | ||
| 748 | 793 | } |
| 749 | 794 | } |
| 750 | 795 | |
| 796 | +static u8 skl_calc_voltage_level(int cdclk) | |
| 797 | +{ | |
| 798 | + switch (cdclk) { | |
| 799 | + default: | |
| 800 | + case 308571: | |
| 801 | + case 337500: | |
| 802 | + return 0; | |
| 803 | + case 450000: | |
| 804 | + case 432000: | |
| 805 | + return 1; | |
| 806 | + case 540000: | |
| 807 | + return 2; | |
| 808 | + case 617143: | |
| 809 | + case 675000: | |
| 810 | + return 3; | |
| 811 | + } | |
| 812 | +} | |
| 813 | + | |
| 751 | 814 | static void skl_dpll0_update(struct drm_i915_private *dev_priv, |
| 752 | 815 | struct intel_cdclk_state *cdclk_state) |
| 753 | 816 | { |
| @@ -798,7 +861,7 @@ static void skl_get_cdclk(struct drm_i915_private *dev_priv, · 44 unmodified lines | ||
| 798 | 861 | cdclk_state->cdclk = cdclk_state->ref; |
| 799 | 862 | |
| 800 | 863 | if (cdclk_state->vco == 0) |
| 801 | − return; | |
| 864 | + goto out; | |
| 802 | 865 | |
| 803 | 866 | cdctl = I915_READ(CDCLK_CTL); |
| 804 | 867 | |
| @@ -839,6 +902,14 @@ static void skl_get_cdclk(struct drm_i915_private *dev_priv, · 34 unmodified lines | ||
| 839 | 902 | break; |
| 840 | 903 | } |
| 841 | 904 | } |
| 905 | + | |
| 906 | + out: | |
| 907 | + /* | |
| 908 | + * Can't read this out :( Let's assume it's | |
| 909 | + * at least what the CDCLK frequency requires. | |
| 910 | + */ | |
| 911 | + cdclk_state->voltage_level = | |
| 912 | + skl_calc_voltage_level(cdclk_state->cdclk); | |
| 842 | 913 | } |
| 843 | 914 | |
| 844 | 915 | /* convert from kHz to .1 fixpoint MHz with -1MHz offset */ |
| @@ -923,11 +994,9 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, · 78 unmodified lines | ||
| 923 | 994 | { |
| 924 | 995 | int cdclk = cdclk_state->cdclk; |
| 925 | 996 | int vco = cdclk_state->vco; |
| 926 | − u32 freq_select, pcu_ack; | |
| 997 | + u32 freq_select; | |
| 927 | 998 | int ret; |
| 928 | 999 | |
| 929 | − WARN_ON((cdclk == 24000) != (vco == 0)); | |
| 930 | − | |
| 931 | 1000 | mutex_lock(&dev_priv->pcu_lock); |
| 932 | 1001 | ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL, |
| 933 | 1002 | SKL_CDCLK_PREPARE_FOR_CHANGE, |
| @@ -942,25 +1011,24 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, · 8 unmodified lines | ||
| 942 | 1011 | |
| 943 | 1012 | /* set CDCLK_CTL */ |
| 944 | 1013 | switch (cdclk) { |
| 1014 | + default: | |
| 1015 | + WARN_ON(cdclk != dev_priv->cdclk.hw.ref); | |
| 1016 | + WARN_ON(vco != 0); | |
| 1017 | + /* fall through */ | |
| 1018 | + case 308571: | |
| 1019 | + case 337500: | |
| 1020 | + freq_select = CDCLK_FREQ_337_308; | |
| 1021 | + break; | |
| 945 | 1022 | case 450000: |
| 946 | 1023 | case 432000: |
| 947 | 1024 | freq_select = CDCLK_FREQ_450_432; |
| 948 | − pcu_ack = 1; | |
| 949 | 1025 | break; |
| 950 | 1026 | case 540000: |
| 951 | 1027 | freq_select = CDCLK_FREQ_540; |
| 952 | − pcu_ack = 2; | |
| 953 | − break; | |
| 954 | − case 308571: | |
| 955 | − case 337500: | |
| 956 | − default: | |
| 957 | − freq_select = CDCLK_FREQ_337_308; | |
| 958 | − pcu_ack = 0; | |
| 959 | 1028 | break; |
| 960 | 1029 | case 617143: |
| 961 | 1030 | case 675000: |
| 962 | 1031 | freq_select = CDCLK_FREQ_675_617; |
| 963 | − pcu_ack = 3; | |
| 964 | 1032 | break; |
| 965 | 1033 | } |
| 966 | 1034 | |
| @@ -976,7 +1044,8 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, · 9 unmodified lines | ||
| 976 | 1044 | |
| 977 | 1045 | /* inform PCU of the change */ |
| 978 | 1046 | mutex_lock(&dev_priv->pcu_lock); |
| 979 | − sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack); | |
| 1047 | + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, | |
| 1048 | + cdclk_state->voltage_level); | |
| 980 | 1049 | mutex_unlock(&dev_priv->pcu_lock); |
| 981 | 1050 | |
| 982 | 1051 | intel_update_cdclk(dev_priv); |
| @@ -995,6 +1064,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) · 12 unmodified lines | ||
| 995 | 1064 | goto sanitize; |
| 996 | 1065 | |
| 997 | 1066 | intel_update_cdclk(dev_priv); |
| 1067 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); | |
| 1068 | + | |
| 998 | 1069 | /* Is PLL enabled and locked ? */ |
| 999 | 1070 | if (dev_priv->cdclk.hw.vco == 0 || |
| 1000 | 1071 | dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref) |
| @@ -1055,6 +1126,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) · 54 unmodified lines | ||
| 1055 | 1126 | if (cdclk_state.vco == 0) |
| 1056 | 1127 | cdclk_state.vco = 8100000; |
| 1057 | 1128 | cdclk_state.cdclk = skl_calc_cdclk(0, cdclk_state.vco); |
| 1129 | + cdclk_state.voltage_level = skl_calc_voltage_level(cdclk_state.cdclk); | |
| 1058 | 1130 | |
| 1059 | 1131 | skl_set_cdclk(dev_priv, &cdclk_state); |
| 1060 | 1132 | } |
| @@ -1072,6 +1144,7 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 1072 | 1144 | |
| 1073 | 1145 | cdclk_state.cdclk = cdclk_state.ref; |
| 1074 | 1146 | cdclk_state.vco = 0; |
| 1147 | + cdclk_state.voltage_level = skl_calc_voltage_level(cdclk_state.cdclk); | |
| 1075 | 1148 | |
| 1076 | 1149 | skl_set_cdclk(dev_priv, &cdclk_state); |
| 1077 | 1150 | } |
| @@ -1100,6 +1173,11 @@ static int glk_calc_cdclk(int min_cdclk) · 22 unmodified lines | ||
| 1100 | 1173 | return 79200; |
| 1101 | 1174 | } |
| 1102 | 1175 | |
| 1176 | +static u8 bxt_calc_voltage_level(int cdclk) | |
| 1177 | +{ | |
| 1178 | + return DIV_ROUND_UP(cdclk, 25000); | |
| 1179 | +} | |
| 1180 | + | |
| 1103 | 1181 | static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) |
| 1104 | 1182 | { |
| 1105 | 1183 | int ratio; |
| @@ -1110,6 +1188,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) · 4 unmodified lines | ||
| 1110 | 1188 | switch (cdclk) { |
| 1111 | 1189 | default: |
| 1112 | 1190 | MISSING_CASE(cdclk); |
| 1191 | + /* fall through */ | |
| 1113 | 1192 | case 144000: |
| 1114 | 1193 | case 288000: |
| 1115 | 1194 | case 384000: |
| @@ -1134,6 +1213,7 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) · 18 unmodified lines | ||
| 1134 | 1213 | switch (cdclk) { |
| 1135 | 1214 | default: |
| 1136 | 1215 | MISSING_CASE(cdclk); |
| 1216 | + /* fall through */ | |
| 1137 | 1217 | case 79200: |
| 1138 | 1218 | case 158400: |
| 1139 | 1219 | case 316800: |
| @@ -1174,7 +1254,7 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv, · 34 unmodified lines | ||
| 1174 | 1254 | cdclk_state->cdclk = cdclk_state->ref; |
| 1175 | 1255 | |
| 1176 | 1256 | if (cdclk_state->vco == 0) |
| 1177 | − return; | |
| 1257 | + goto out; | |
| 1178 | 1258 | |
| 1179 | 1259 | divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK; |
| 1180 | 1260 | |
| @@ -1198,6 +1278,14 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv, · 17 unmodified lines | ||
| 1198 | 1278 | } |
| 1199 | 1279 | |
| 1200 | 1280 | cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div); |
| 1281 | + | |
| 1282 | + out: | |
| 1283 | + /* | |
| 1284 | + * Can't read this out :( Let's assume it's | |
| 1285 | + * at least what the CDCLK frequency requires. | |
| 1286 | + */ | |
| 1287 | + cdclk_state->voltage_level = | |
| 1288 | + bxt_calc_voltage_level(cdclk_state->cdclk); | |
| 1201 | 1289 | } |
| 1202 | 1290 | |
| 1203 | 1291 | static void bxt_de_pll_disable(struct drm_i915_private *dev_priv) |
| @@ -1246,24 +1334,22 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, · 42 unmodified lines | ||
| 1246 | 1334 | |
| 1247 | 1335 | /* cdclk = vco / 2 / div{1,1.5,2,4} */ |
| 1248 | 1336 | switch (DIV_ROUND_CLOSEST(vco, cdclk)) { |
| 1249 | − case 8: | |
| 1250 | − divider = BXT_CDCLK_CD2X_DIV_SEL_4; | |
| 1251 | − break; | |
| 1252 | − case 4: | |
| 1253 | − divider = BXT_CDCLK_CD2X_DIV_SEL_2; | |
| 1337 | + default: | |
| 1338 | + WARN_ON(cdclk != dev_priv->cdclk.hw.ref); | |
| 1339 | + WARN_ON(vco != 0); | |
| 1340 | + /* fall through */ | |
| 1341 | + case 2: | |
| 1342 | + divider = BXT_CDCLK_CD2X_DIV_SEL_1; | |
| 1254 | 1343 | break; |
| 1255 | 1344 | case 3: |
| 1256 | 1345 | WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n"); |
| 1257 | 1346 | divider = BXT_CDCLK_CD2X_DIV_SEL_1_5; |
| 1258 | 1347 | break; |
| 1259 | − case 2: | |
| 1260 | − divider = BXT_CDCLK_CD2X_DIV_SEL_1; | |
| 1348 | + case 4: | |
| 1349 | + divider = BXT_CDCLK_CD2X_DIV_SEL_2; | |
| 1261 | 1350 | break; |
| 1262 | − default: | |
| 1263 | − WARN_ON(cdclk != dev_priv->cdclk.hw.ref); | |
| 1264 | − WARN_ON(vco != 0); | |
| 1265 | − | |
| 1266 | − divider = BXT_CDCLK_CD2X_DIV_SEL_1; | |
| 1351 | + case 8: | |
| 1352 | + divider = BXT_CDCLK_CD2X_DIV_SEL_4; | |
| 1267 | 1353 | break; |
| 1268 | 1354 | } |
| 1269 | 1355 | |
| @@ -1302,7 +1388,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, · 32 unmodified lines | ||
| 1302 | 1388 | |
| 1303 | 1389 | mutex_lock(&dev_priv->pcu_lock); |
| 1304 | 1390 | ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, |
| 1305 | − DIV_ROUND_UP(cdclk, 25000)); | |
| 1391 | + cdclk_state->voltage_level); | |
| 1306 | 1392 | mutex_unlock(&dev_priv->pcu_lock); |
| 1307 | 1393 | |
| 1308 | 1394 | if (ret) { |
| @@ -1319,6 +1405,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) · 10 unmodified lines | ||
| 1319 | 1405 | u32 cdctl, expected; |
| 1320 | 1406 | |
| 1321 | 1407 | intel_update_cdclk(dev_priv); |
| 1408 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); | |
| 1322 | 1409 | |
| 1323 | 1410 | if (dev_priv->cdclk.hw.vco == 0 || |
| 1324 | 1411 | dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref) |
| @@ -1394,6 +1481,7 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) · 69 unmodified lines | ||
| 1394 | 1481 | cdclk_state.cdclk = bxt_calc_cdclk(0); |
| 1395 | 1482 | cdclk_state.vco = bxt_de_pll_vco(dev_priv, cdclk_state.cdclk); |
| 1396 | 1483 | } |
| 1484 | + cdclk_state.voltage_level = bxt_calc_voltage_level(cdclk_state.cdclk); | |
| 1397 | 1485 | |
| 1398 | 1486 | bxt_set_cdclk(dev_priv, &cdclk_state); |
| 1399 | 1487 | } |
| @@ -1411,6 +1499,7 @@ void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 1411 | 1499 | |
| 1412 | 1500 | cdclk_state.cdclk = cdclk_state.ref; |
| 1413 | 1501 | cdclk_state.vco = 0; |
| 1502 | + cdclk_state.voltage_level = bxt_calc_voltage_level(cdclk_state.cdclk); | |
| 1414 | 1503 | |
| 1415 | 1504 | bxt_set_cdclk(dev_priv, &cdclk_state); |
| 1416 | 1505 | } |
| @@ -1425,6 +1514,19 @@ static int cnl_calc_cdclk(int min_cdclk) · 8 unmodified lines | ||
| 1425 | 1514 | return 168000; |
| 1426 | 1515 | } |
| 1427 | 1516 | |
| 1517 | +static u8 cnl_calc_voltage_level(int cdclk) | |
| 1518 | +{ | |
| 1519 | + switch (cdclk) { | |
| 1520 | + default: | |
| 1521 | + case 168000: | |
| 1522 | + return 0; | |
| 1523 | + case 336000: | |
| 1524 | + return 1; | |
| 1525 | + case 528000: | |
| 1526 | + return 2; | |
| 1527 | + } | |
| 1528 | +} | |
| 1529 | + | |
| 1428 | 1530 | static void cnl_cdclk_pll_update(struct drm_i915_private *dev_priv, |
| 1429 | 1531 | struct intel_cdclk_state *cdclk_state) |
| 1430 | 1532 | { |
| @@ -1458,7 +1560,7 @@ static void cnl_get_cdclk(struct drm_i915_private *dev_priv, · 27 unmodified lines | ||
| 1458 | 1560 | cdclk_state->cdclk = cdclk_state->ref; |
| 1459 | 1561 | |
| 1460 | 1562 | if (cdclk_state->vco == 0) |
| 1461 | − return; | |
| 1563 | + goto out; | |
| 1462 | 1564 | |
| 1463 | 1565 | divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK; |
| 1464 | 1566 | |
| @@ -1475,6 +1577,14 @@ static void cnl_get_cdclk(struct drm_i915_private *dev_priv, · 10 unmodified lines | ||
| 1475 | 1577 | } |
| 1476 | 1578 | |
| 1477 | 1579 | cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div); |
| 1580 | + | |
| 1581 | + out: | |
| 1582 | + /* | |
| 1583 | + * Can't read this out :( Let's assume it's | |
| 1584 | + * at least what the CDCLK frequency requires. | |
| 1585 | + */ | |
| 1586 | + cdclk_state->voltage_level = | |
| 1587 | + cnl_calc_voltage_level(cdclk_state->cdclk); | |
| 1478 | 1588 | } |
| 1479 | 1589 | |
| 1480 | 1590 | static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv) |
| @@ -1515,7 +1625,7 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv, · 34 unmodified lines | ||
| 1515 | 1625 | { |
| 1516 | 1626 | int cdclk = cdclk_state->cdclk; |
| 1517 | 1627 | int vco = cdclk_state->vco; |
| 1518 | − u32 val, divider, pcu_ack; | |
| 1628 | + u32 val, divider; | |
| 1519 | 1629 | int ret; |
| 1520 | 1630 | |
| 1521 | 1631 | mutex_lock(&dev_priv->pcu_lock); |
| @@ -1532,30 +1642,15 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv, · 10 unmodified lines | ||
| 1532 | 1642 | |
| 1533 | 1643 | /* cdclk = vco / 2 / div{1,2} */ |
| 1534 | 1644 | switch (DIV_ROUND_CLOSEST(vco, cdclk)) { |
| 1535 | − case 4: | |
| 1536 | − divider = BXT_CDCLK_CD2X_DIV_SEL_2; | |
| 1537 | − break; | |
| 1538 | − case 2: | |
| 1539 | − divider = BXT_CDCLK_CD2X_DIV_SEL_1; | |
| 1540 | − break; | |
| 1541 | 1645 | default: |
| 1542 | 1646 | WARN_ON(cdclk != dev_priv->cdclk.hw.ref); |
| 1543 | 1647 | WARN_ON(vco != 0); |
| 1544 | − | |
| 1648 | + /* fall through */ | |
| 1649 | + case 2: | |
| 1545 | 1650 | divider = BXT_CDCLK_CD2X_DIV_SEL_1; |
| 1546 | 1651 | break; |
| 1547 | − } | |
| 1548 | − | |
| 1549 | − switch (cdclk) { | |
| 1550 | − case 528000: | |
| 1551 | − pcu_ack = 2; | |
| 1552 | − break; | |
| 1553 | − case 336000: | |
| 1554 | − pcu_ack = 1; | |
| 1555 | − break; | |
| 1556 | − case 168000: | |
| 1557 | − default: | |
| 1558 | − pcu_ack = 0; | |
| 1652 | + case 4: | |
| 1653 | + divider = BXT_CDCLK_CD2X_DIV_SEL_2; | |
| 1559 | 1654 | break; |
| 1560 | 1655 | } |
| 1561 | 1656 | |
| @@ -1576,10 +1671,17 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv, · 14 unmodified lines | ||
| 1576 | 1671 | |
| 1577 | 1672 | /* inform PCU of the change */ |
| 1578 | 1673 | mutex_lock(&dev_priv->pcu_lock); |
| 1579 | − sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack); | |
| 1674 | + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, | |
| 1675 | + cdclk_state->voltage_level); | |
| 1580 | 1676 | mutex_unlock(&dev_priv->pcu_lock); |
| 1581 | 1677 | |
| 1582 | 1678 | intel_update_cdclk(dev_priv); |
| 1679 | + | |
| 1680 | + /* | |
| 1681 | + * Can't read out the voltage level :( | |
| 1682 | + * Let's just assume everything is as expected. | |
| 1683 | + */ | |
| 1684 | + dev_priv->cdclk.hw.voltage_level = cdclk_state->voltage_level; | |
| 1583 | 1685 | } |
| 1584 | 1686 | |
| 1585 | 1687 | static int cnl_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk) |
| @@ -1592,6 +1694,7 @@ static int cnl_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk) · 6 unmodified lines | ||
| 1592 | 1694 | switch (cdclk) { |
| 1593 | 1695 | default: |
| 1594 | 1696 | MISSING_CASE(cdclk); |
| 1697 | + /* fall through */ | |
| 1595 | 1698 | case 168000: |
| 1596 | 1699 | case 336000: |
| 1597 | 1700 | ratio = dev_priv->cdclk.hw.ref == 19200 ? 35 : 28; |
| @@ -1609,6 +1712,7 @@ static void cnl_sanitize_cdclk(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 1609 | 1712 | u32 cdctl, expected; |
| 1610 | 1713 | |
| 1611 | 1714 | intel_update_cdclk(dev_priv); |
| 1715 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); | |
| 1612 | 1716 | |
| 1613 | 1717 | if (dev_priv->cdclk.hw.vco == 0 || |
| 1614 | 1718 | dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref) |
| @@ -1668,6 +1772,7 @@ void cnl_init_cdclk(struct drm_i915_private *dev_priv) · 53 unmodified lines | ||
| 1668 | 1772 | |
| 1669 | 1773 | cdclk_state.cdclk = cnl_calc_cdclk(0); |
| 1670 | 1774 | cdclk_state.vco = cnl_cdclk_pll_vco(dev_priv, cdclk_state.cdclk); |
| 1775 | + cdclk_state.voltage_level = cnl_calc_voltage_level(cdclk_state.cdclk); | |
| 1671 | 1776 | |
| 1672 | 1777 | cnl_set_cdclk(dev_priv, &cdclk_state); |
| 1673 | 1778 | } |
| @@ -1685,22 +1790,48 @@ void cnl_uninit_cdclk(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 1685 | 1790 | |
| 1686 | 1791 | cdclk_state.cdclk = cdclk_state.ref; |
| 1687 | 1792 | cdclk_state.vco = 0; |
| 1793 | + cdclk_state.voltage_level = cnl_calc_voltage_level(cdclk_state.cdclk); | |
| 1688 | 1794 | |
| 1689 | 1795 | cnl_set_cdclk(dev_priv, &cdclk_state); |
| 1690 | 1796 | } |
| 1691 | 1797 | |
| 1692 | 1798 | /** |
| 1693 | − * intel_cdclk_state_compare - Determine if two CDCLK states differ | |
| 1799 | + * intel_cdclk_needs_modeset - Determine if two CDCLK states require a modeset on all pipes | |
| 1694 | 1800 | * @a: first CDCLK state |
| 1695 | 1801 | * @b: second CDCLK state |
| 1696 | 1802 | * |
| 1697 | 1803 | * Returns: |
| 1698 | − * True if the CDCLK states are identical, false if they differ. | |
| 1804 | + * True if the CDCLK states require pipes to be off during reprogramming, false if not. | |
| 1699 | 1805 | */ |
| 1700 | −bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, | |
| 1806 | +bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a, | |
| 1701 | 1807 | const struct intel_cdclk_state *b) |
| 1702 | 1808 | { |
| 1703 | − return memcmp(a, b, sizeof(*a)) == 0; | |
| 1809 | + return a->cdclk != b->cdclk || | |
| 1810 | + a->vco != b->vco || | |
| 1811 | + a->ref != b->ref; | |
| 1812 | +} | |
| 1813 | + | |
| 1814 | +/** | |
| 1815 | + * intel_cdclk_changed - Determine if two CDCLK states are different | |
| 1816 | + * @a: first CDCLK state | |
| 1817 | + * @b: second CDCLK state | |
| 1818 | + * | |
| 1819 | + * Returns: | |
| 1820 | + * True if the CDCLK states don't match, false if they do. | |
| 1821 | + */ | |
| 1822 | +bool intel_cdclk_changed(const struct intel_cdclk_state *a, | |
| 1823 | + const struct intel_cdclk_state *b) | |
| 1824 | +{ | |
| 1825 | + return intel_cdclk_needs_modeset(a, b) || | |
| 1826 | + a->voltage_level != b->voltage_level; | |
| 1827 | +} | |
| 1828 | + | |
| 1829 | +void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state, | |
| 1830 | + const char *context) | |
| 1831 | +{ | |
| 1832 | + DRM_DEBUG_DRIVER("%s %d kHz, VCO %d kHz, ref %d kHz, voltage level %d\n", | |
| 1833 | + context, cdclk_state->cdclk, cdclk_state->vco, | |
| 1834 | + cdclk_state->ref, cdclk_state->voltage_level); | |
| 1704 | 1835 | } |
| 1705 | 1836 | |
| 1706 | 1837 | /** |
| @@ -1714,29 +1845,28 @@ bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, · 7 unmodified lines | ||
| 1714 | 1845 | void intel_set_cdclk(struct drm_i915_private *dev_priv, |
| 1715 | 1846 | const struct intel_cdclk_state *cdclk_state) |
| 1716 | 1847 | { |
| 1717 | − if (intel_cdclk_state_compare(&dev_priv->cdclk.hw, cdclk_state)) | |
| 1848 | + if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_state)) | |
| 1718 | 1849 | return; |
| 1719 | 1850 | |
| 1720 | 1851 | if (WARN_ON_ONCE(!dev_priv->display.set_cdclk)) |
| 1721 | 1852 | return; |
| 1722 | 1853 | |
| 1723 | − DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d kHz\n", | |
| 1724 | − cdclk_state->cdclk, cdclk_state->vco, | |
| 1725 | − cdclk_state->ref); | |
| 1854 | + intel_dump_cdclk_state(cdclk_state, "Changing CDCLK to"); | |
| 1726 | 1855 | |
| 1727 | 1856 | dev_priv->display.set_cdclk(dev_priv, cdclk_state); |
| 1857 | + | |
| 1858 | + if (WARN(intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_state), | |
| 1859 | + "cdclk state doesn't match!\n")) { | |
| 1860 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "[hw state]"); | |
| 1861 | + intel_dump_cdclk_state(cdclk_state, "[sw state]"); | |
| 1862 | + } | |
| 1728 | 1863 | } |
| 1729 | 1864 | |
| 1730 | 1865 | static int intel_pixel_rate_to_cdclk(struct drm_i915_private *dev_priv, |
| 1731 | 1866 | int pixel_rate) |
| 1732 | 1867 | { |
| 1733 | 1868 | if (INTEL_GEN(dev_priv) >= 10) |
| 1734 | − /* | |
| 1735 | − * FIXME: Switch to DIV_ROUND_UP(pixel_rate, 2) | |
| 1736 | − * once DDI clock voltage requirements are | |
| 1737 | − * handled correctly. | |
| 1738 | − */ | |
| 1739 | − return pixel_rate; | |
| 1869 | + return DIV_ROUND_UP(pixel_rate, 2); | |
| 1740 | 1870 | else if (IS_GEMINILAKE(dev_priv)) |
| 1741 | 1871 | /* |
| 1742 | 1872 | * FIXME: Avoid using a pixel clock that is more than 99% of the cdclk |
| @@ -1829,6 +1959,43 @@ static int intel_compute_min_cdclk(struct drm_atomic_state *state) · 86 unmodified lines | ||
| 1829 | 1959 | return min_cdclk; |
| 1830 | 1960 | } |
| 1831 | 1961 | |
| 1962 | +/* | |
| 1963 | + * Note that this functions assumes that 0 is | |
| 1964 | + * the lowest voltage value, and higher values | |
| 1965 | + * correspond to increasingly higher voltages. | |
| 1966 | + * | |
| 1967 | + * Should that relationship no longer hold on | |
| 1968 | + * future platforms this code will need to be | |
| 1969 | + * adjusted. | |
| 1970 | + */ | |
| 1971 | +static u8 cnl_compute_min_voltage_level(struct intel_atomic_state *state) | |
| 1972 | +{ | |
| 1973 | + struct drm_i915_private *dev_priv = to_i915(state->base.dev); | |
| 1974 | + struct intel_crtc *crtc; | |
| 1975 | + struct intel_crtc_state *crtc_state; | |
| 1976 | + u8 min_voltage_level; | |
| 1977 | + int i; | |
| 1978 | + enum pipe pipe; | |
| 1979 | + | |
| 1980 | + memcpy(state->min_voltage_level, dev_priv->min_voltage_level, | |
| 1981 | + sizeof(state->min_voltage_level)); | |
| 1982 | + | |
| 1983 | + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { | |
| 1984 | + if (crtc_state->base.enable) | |
| 1985 | + state->min_voltage_level[i] = | |
| 1986 | + crtc_state->min_voltage_level; | |
| 1987 | + else | |
| 1988 | + state->min_voltage_level[i] = 0; | |
| 1989 | + } | |
| 1990 | + | |
| 1991 | + min_voltage_level = 0; | |
| 1992 | + for_each_pipe(dev_priv, pipe) | |
| 1993 | + min_voltage_level = max(state->min_voltage_level[pipe], | |
| 1994 | + min_voltage_level); | |
| 1995 | + | |
| 1996 | + return min_voltage_level; | |
| 1997 | +} | |
| 1998 | + | |
| 1832 | 1999 | static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state) |
| 1833 | 2000 | { |
| 1834 | 2001 | struct drm_i915_private *dev_priv = to_i915(state->dev); |
| @@ -1842,11 +2009,15 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state) · 7 unmodified lines | ||
| 1842 | 2009 | cdclk = vlv_calc_cdclk(dev_priv, min_cdclk); |
| 1843 | 2010 | |
| 1844 | 2011 | intel_state->cdclk.logical.cdclk = cdclk; |
| 2012 | + intel_state->cdclk.logical.voltage_level = | |
| 2013 | + vlv_calc_voltage_level(dev_priv, cdclk); | |
| 1845 | 2014 | |
| 1846 | 2015 | if (!intel_state->active_crtcs) { |
| 1847 | 2016 | cdclk = vlv_calc_cdclk(dev_priv, 0); |
| 1848 | 2017 | |
| 1849 | 2018 | intel_state->cdclk.actual.cdclk = cdclk; |
| 2019 | + intel_state->cdclk.actual.voltage_level = | |
| 2020 | + vlv_calc_voltage_level(dev_priv, cdclk); | |
| 1850 | 2021 | } else { |
| 1851 | 2022 | intel_state->cdclk.actual = |
| 1852 | 2023 | intel_state->cdclk.logical; |
| @@ -1871,11 +2042,15 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state) · 18 unmodified lines | ||
| 1871 | 2042 | cdclk = bdw_calc_cdclk(min_cdclk); |
| 1872 | 2043 | |
| 1873 | 2044 | intel_state->cdclk.logical.cdclk = cdclk; |
| 2045 | + intel_state->cdclk.logical.voltage_level = | |
| 2046 | + bdw_calc_voltage_level(cdclk); | |
| 1874 | 2047 | |
| 1875 | 2048 | if (!intel_state->active_crtcs) { |
| 1876 | 2049 | cdclk = bdw_calc_cdclk(0); |
| 1877 | 2050 | |
| 1878 | 2051 | intel_state->cdclk.actual.cdclk = cdclk; |
| 2052 | + intel_state->cdclk.actual.voltage_level = | |
| 2053 | + bdw_calc_voltage_level(cdclk); | |
| 1879 | 2054 | } else { |
| 1880 | 2055 | intel_state->cdclk.actual = |
| 1881 | 2056 | intel_state->cdclk.logical; |
| @@ -1906,12 +2081,16 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) · 24 unmodified lines | ||
| 1906 | 2081 | |
| 1907 | 2082 | intel_state->cdclk.logical.vco = vco; |
| 1908 | 2083 | intel_state->cdclk.logical.cdclk = cdclk; |
| 2084 | + intel_state->cdclk.logical.voltage_level = | |
| 2085 | + skl_calc_voltage_level(cdclk); | |
| 1909 | 2086 | |
| 1910 | 2087 | if (!intel_state->active_crtcs) { |
| 1911 | 2088 | cdclk = skl_calc_cdclk(0, vco); |
| 1912 | 2089 | |
| 1913 | 2090 | intel_state->cdclk.actual.vco = vco; |
| 1914 | 2091 | intel_state->cdclk.actual.cdclk = cdclk; |
| 2092 | + intel_state->cdclk.actual.voltage_level = | |
| 2093 | + skl_calc_voltage_level(cdclk); | |
| 1915 | 2094 | } else { |
| 1916 | 2095 | intel_state->cdclk.actual = |
| 1917 | 2096 | intel_state->cdclk.logical; |
| @@ -1940,6 +2119,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state) · 22 unmodified lines | ||
| 1940 | 2119 | |
| 1941 | 2120 | intel_state->cdclk.logical.vco = vco; |
| 1942 | 2121 | intel_state->cdclk.logical.cdclk = cdclk; |
| 2122 | + intel_state->cdclk.logical.voltage_level = | |
| 2123 | + bxt_calc_voltage_level(cdclk); | |
| 1943 | 2124 | |
| 1944 | 2125 | if (!intel_state->active_crtcs) { |
| 1945 | 2126 | if (IS_GEMINILAKE(dev_priv)) { |
| @@ -1952,6 +2133,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state) · 6 unmodified lines | ||
| 1952 | 2133 | |
| 1953 | 2134 | intel_state->cdclk.actual.vco = vco; |
| 1954 | 2135 | intel_state->cdclk.actual.cdclk = cdclk; |
| 2136 | + intel_state->cdclk.actual.voltage_level = | |
| 2137 | + bxt_calc_voltage_level(cdclk); | |
| 1955 | 2138 | } else { |
| 1956 | 2139 | intel_state->cdclk.actual = |
| 1957 | 2140 | intel_state->cdclk.logical; |
| @@ -1975,6 +2158,9 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state) · 17 unmodified lines | ||
| 1975 | 2158 | |
| 1976 | 2159 | intel_state->cdclk.logical.vco = vco; |
| 1977 | 2160 | intel_state->cdclk.logical.cdclk = cdclk; |
| 2161 | + intel_state->cdclk.logical.voltage_level = | |
| 2162 | + max(cnl_calc_voltage_level(cdclk), | |
| 2163 | + cnl_compute_min_voltage_level(intel_state)); | |
| 1978 | 2164 | |
| 1979 | 2165 | if (!intel_state->active_crtcs) { |
| 1980 | 2166 | cdclk = cnl_calc_cdclk(0); |
| @@ -1982,6 +2168,8 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state) · 1 unmodified line | ||
| 1982 | 2168 | |
| 1983 | 2169 | intel_state->cdclk.actual.vco = vco; |
| 1984 | 2170 | intel_state->cdclk.actual.cdclk = cdclk; |
| 2171 | + intel_state->cdclk.actual.voltage_level = | |
| 2172 | + cnl_calc_voltage_level(cdclk); | |
| 1985 | 2173 | } else { |
| 1986 | 2174 | intel_state->cdclk.actual = |
| 1987 | 2175 | intel_state->cdclk.logical; |
| @@ -1995,12 +2183,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) · 7 unmodified lines | ||
| 1995 | 2183 | int max_cdclk_freq = dev_priv->max_cdclk_freq; |
| 1996 | 2184 | |
| 1997 | 2185 | if (INTEL_GEN(dev_priv) >= 10) |
| 1998 | − /* | |
| 1999 | − * FIXME: Allow '2 * max_cdclk_freq' | |
| 2000 | − * once DDI clock voltage requirements are | |
| 2001 | − * handled correctly. | |
| 2002 | − */ | |
| 2003 | − return max_cdclk_freq; | |
| 2186 | + return 2 * max_cdclk_freq; | |
| 2004 | 2187 | else if (IS_GEMINILAKE(dev_priv)) |
| 2005 | 2188 | /* |
| 2006 | 2189 | * FIXME: Limiting to 99% as a temporary workaround. See |
| @@ -2099,10 +2282,6 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv) · 92 unmodified lines | ||
| 2099 | 2282 | { |
| 2100 | 2283 | dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw); |
| 2101 | 2284 | |
| 2102 | − DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", | |
| 2103 | − dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco, | |
| 2104 | − dev_priv->cdclk.hw.ref); | |
| 2105 | − | |
| 2106 | 2285 | /* |
| 2107 | 2286 | * 9:0 CMBUS [sic] CDCLK frequency (cdfreq): |
| 2108 | 2287 | * Programmng [sic] note: bit[9:2] should be programmed to the number |
| @@ -370,7 +370,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state) · 369 unmodified lines | ||
| 370 | 370 | */ |
| 371 | 371 | if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled && |
| 372 | 372 | (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { |
| 373 | − hsw_disable_ips(intel_crtc); | |
| 373 | + hsw_disable_ips(intel_crtc_state); | |
| 374 | 374 | reenable_ips = true; |
| 375 | 375 | } |
| 376 | 376 | |
| @@ -380,7 +380,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state) · 3 unmodified lines | ||
| 380 | 380 | i9xx_load_luts(crtc_state); |
| 381 | 381 | |
| 382 | 382 | if (reenable_ips) |
| 383 | − hsw_enable_ips(intel_crtc); | |
| 383 | + hsw_enable_ips(intel_crtc_state); | |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | 386 | static void bdw_load_degamma_lut(struct drm_crtc_state *state) |
| @@ -119,6 +119,8 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) · 118 unmodified lines | ||
| 119 | 119 | static void intel_crt_get_config(struct intel_encoder *encoder, |
| 120 | 120 | struct intel_crtc_state *pipe_config) |
| 121 | 121 | { |
| 122 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG); | |
| 123 | + | |
| 122 | 124 | pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
| 123 | 125 | |
| 124 | 126 | pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; |
| @@ -217,11 +219,9 @@ static void hsw_disable_crt(struct intel_encoder *encoder, · 92 unmodified lines | ||
| 217 | 219 | const struct intel_crtc_state *old_crtc_state, |
| 218 | 220 | const struct drm_connector_state *old_conn_state) |
| 219 | 221 | { |
| 220 | − struct drm_crtc *crtc = old_crtc_state->base.crtc; | |
| 221 | − struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 222 | − struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 222 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 223 | 223 | |
| 224 | − WARN_ON(!intel_crtc->config->has_pch_encoder); | |
| 224 | + WARN_ON(!old_crtc_state->has_pch_encoder); | |
| 225 | 225 | |
| 226 | 226 | intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); |
| 227 | 227 | } |
| @@ -245,46 +245,42 @@ static void hsw_post_disable_crt(struct intel_encoder *encoder, · 17 unmodified lines | ||
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | static void hsw_pre_pll_enable_crt(struct intel_encoder *encoder, |
| 248 | − const struct intel_crtc_state *pipe_config, | |
| 248 | + const struct intel_crtc_state *crtc_state, | |
| 249 | 249 | const struct drm_connector_state *conn_state) |
| 250 | 250 | { |
| 251 | − struct drm_crtc *crtc = pipe_config->base.crtc; | |
| 252 | − struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 253 | − struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 251 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 254 | 252 | |
| 255 | − WARN_ON(!intel_crtc->config->has_pch_encoder); | |
| 253 | + WARN_ON(!crtc_state->has_pch_encoder); | |
| 256 | 254 | |
| 257 | 255 | intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); |
| 258 | 256 | } |
| 259 | 257 | |
| 260 | 258 | static void hsw_pre_enable_crt(struct intel_encoder *encoder, |
| 261 | − const struct intel_crtc_state *pipe_config, | |
| 259 | + const struct intel_crtc_state *crtc_state, | |
| 262 | 260 | const struct drm_connector_state *conn_state) |
| 263 | 261 | { |
| 264 | − struct drm_crtc *crtc = pipe_config->base.crtc; | |
| 265 | − struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 266 | − struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 267 | − int pipe = intel_crtc->pipe; | |
| 262 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 263 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 264 | + enum pipe pipe = crtc->pipe; | |
| 268 | 265 | |
| 269 | − WARN_ON(!intel_crtc->config->has_pch_encoder); | |
| 266 | + WARN_ON(!crtc_state->has_pch_encoder); | |
| 270 | 267 | |
| 271 | 268 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); |
| 272 | 269 | |
| 273 | − dev_priv->display.fdi_link_train(intel_crtc, pipe_config); | |
| 270 | + dev_priv->display.fdi_link_train(crtc, crtc_state); | |
| 274 | 271 | } |
| 275 | 272 | |
| 276 | 273 | static void hsw_enable_crt(struct intel_encoder *encoder, |
| 277 | − const struct intel_crtc_state *pipe_config, | |
| 274 | + const struct intel_crtc_state *crtc_state, | |
| 278 | 275 | const struct drm_connector_state *conn_state) |
| 279 | 276 | { |
| 280 | − struct drm_crtc *crtc = pipe_config->base.crtc; | |
| 281 | − struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 282 | − struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 283 | − int pipe = intel_crtc->pipe; | |
| 277 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 278 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 279 | + enum pipe pipe = crtc->pipe; | |
| 284 | 280 | |
| 285 | − WARN_ON(!intel_crtc->config->has_pch_encoder); | |
| 281 | + WARN_ON(!crtc_state->has_pch_encoder); | |
| 286 | 282 | |
| 287 | − intel_crt_set_dpms(encoder, pipe_config, DRM_MODE_DPMS_ON); | |
| 283 | + intel_crt_set_dpms(encoder, crtc_state, DRM_MODE_DPMS_ON); | |
| 288 | 284 | |
| 289 | 285 | intel_wait_for_vblank(dev_priv, pipe); |
| 290 | 286 | intel_wait_for_vblank(dev_priv, pipe); |
| @@ -293,10 +289,10 @@ static void hsw_enable_crt(struct intel_encoder *encoder, · 2 unmodified lines | ||
| 293 | 289 | } |
| 294 | 290 | |
| 295 | 291 | static void intel_enable_crt(struct intel_encoder *encoder, |
| 296 | − const struct intel_crtc_state *pipe_config, | |
| 292 | + const struct intel_crtc_state *crtc_state, | |
| 297 | 293 | const struct drm_connector_state *conn_state) |
| 298 | 294 | { |
| 299 | − intel_crt_set_dpms(encoder, pipe_config, DRM_MODE_DPMS_ON); | |
| 295 | + intel_crt_set_dpms(encoder, crtc_state, DRM_MODE_DPMS_ON); | |
| 300 | 296 | } |
| 301 | 297 | |
| 302 | 298 | static enum drm_mode_status |
| @@ -37,8 +37,8 @@ · 36 unmodified lines | ||
| 37 | 37 | #define I915_CSR_GLK "i915/glk_dmc_ver1_04.bin" |
| 38 | 38 | #define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 4) |
| 39 | 39 | |
| 40 | −#define I915_CSR_CNL "i915/cnl_dmc_ver1_04.bin" | |
| 41 | −#define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4) | |
| 40 | +#define I915_CSR_CNL "i915/cnl_dmc_ver1_06.bin" | |
| 41 | +#define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 6) | |
| 42 | 42 | |
| 43 | 43 | #define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin" |
| 44 | 44 | MODULE_FIRMWARE(I915_CSR_KBL); |
| @@ -198,6 +198,7 @@ intel_get_stepping_info(struct drm_i915_private *dev_priv) · 153 unmodified lines | ||
| 198 | 198 | si = bxt_stepping_info; |
| 199 | 199 | } else { |
| 200 | 200 | size = 0; |
| 201 | + si = NULL; | |
| 201 | 202 | } |
| 202 | 203 | |
| 203 | 204 | if (INTEL_REVID(dev_priv) < size) |
| @@ -492,24 +492,6 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = { · 491 unmodified lines | ||
| 492 | 492 | { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */ |
| 493 | 493 | }; |
| 494 | 494 | |
| 495 | −enum port intel_ddi_get_encoder_port(struct intel_encoder *encoder) | |
| 496 | −{ | |
| 497 | − switch (encoder->type) { | |
| 498 | − case INTEL_OUTPUT_DP_MST: | |
| 499 | − return enc_to_mst(&encoder->base)->primary->port; | |
| 500 | − case INTEL_OUTPUT_DP: | |
| 501 | − case INTEL_OUTPUT_EDP: | |
| 502 | − case INTEL_OUTPUT_HDMI: | |
| 503 | − case INTEL_OUTPUT_UNKNOWN: | |
| 504 | − return enc_to_dig_port(&encoder->base)->port; | |
| 505 | − case INTEL_OUTPUT_ANALOG: | |
| 506 | − return PORT_E; | |
| 507 | − default: | |
| 508 | − MISSING_CASE(encoder->type); | |
| 509 | − return PORT_A; | |
| 510 | − } | |
| 511 | −} | |
| 512 | − | |
| 513 | 495 | static const struct ddi_buf_trans * |
| 514 | 496 | bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) |
| 515 | 497 | { |
| @@ -811,31 +793,24 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por · 295 unmodified lines | ||
| 811 | 793 | * values in advance. This function programs the correct values for |
| 812 | 794 | * DP/eDP/FDI use cases. |
| 813 | 795 | */ |
| 814 | −static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) | |
| 796 | +static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder, | |
| 797 | + const struct intel_crtc_state *crtc_state) | |
| 815 | 798 | { |
| 816 | 799 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 817 | 800 | u32 iboost_bit = 0; |
| 818 | 801 | int i, n_entries; |
| 819 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 802 | + enum port port = encoder->port; | |
| 820 | 803 | const struct ddi_buf_trans *ddi_translations; |
| 821 | 804 | |
| 822 | − switch (encoder->type) { | |
| 823 | − case INTEL_OUTPUT_EDP: | |
| 805 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) | |
| 806 | + ddi_translations = intel_ddi_get_buf_trans_fdi(dev_priv, | |
| 807 | + &n_entries); | |
| 808 | + else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) | |
| 824 | 809 | ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, port, |
| 825 | 810 | &n_entries); |
| 826 | − break; | |
| 827 | − case INTEL_OUTPUT_DP: | |
| 811 | + else | |
| 828 | 812 | ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, port, |
| 829 | 813 | &n_entries); |
| 830 | − break; | |
| 831 | − case INTEL_OUTPUT_ANALOG: | |
| 832 | − ddi_translations = intel_ddi_get_buf_trans_fdi(dev_priv, | |
| 833 | − &n_entries); | |
| 834 | − break; | |
| 835 | − default: | |
| 836 | − MISSING_CASE(encoder->type); | |
| 837 | − return; | |
| 838 | − } | |
| 839 | 814 | |
| 840 | 815 | /* If we're boosting the current, set bit 31 of trans1 */ |
| 841 | 816 | if (IS_GEN9_BC(dev_priv) && |
| @@ -861,7 +836,7 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, · 19 unmodified lines | ||
| 861 | 836 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 862 | 837 | u32 iboost_bit = 0; |
| 863 | 838 | int n_entries; |
| 864 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 839 | + enum port port = encoder->port; | |
| 865 | 840 | const struct ddi_buf_trans *ddi_translations; |
| 866 | 841 | |
| 867 | 842 | ddi_translations = intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); |
| @@ -937,7 +912,7 @@ void hsw_fdi_link_train(struct intel_crtc *crtc, · 69 unmodified lines | ||
| 937 | 912 | |
| 938 | 913 | for_each_encoder_on_crtc(dev, &crtc->base, encoder) { |
| 939 | 914 | WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); |
| 940 | − intel_prepare_dp_ddi_buffers(encoder); | |
| 915 | + intel_prepare_dp_ddi_buffers(encoder, crtc_state); | |
| 941 | 916 | } |
| 942 | 917 | |
| 943 | 918 | /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the |
| @@ -1448,19 +1423,16 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, · 504 unmodified lines | ||
| 1448 | 1423 | ddi_dotclock_get(pipe_config); |
| 1449 | 1424 | } |
| 1450 | 1425 | |
| 1451 | −static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, | |
| 1452 | − enum intel_dpll_id pll_id) | |
| 1426 | +static int bxt_calc_pll_link(struct intel_crtc_state *crtc_state) | |
| 1453 | 1427 | { |
| 1454 | − struct intel_shared_dpll *pll; | |
| 1455 | 1428 | struct intel_dpll_hw_state *state; |
| 1456 | 1429 | struct dpll clock; |
| 1457 | 1430 | |
| 1458 | 1431 | /* For DDI ports we always use a shared PLL. */ |
| 1459 | − if (WARN_ON(pll_id == DPLL_ID_PRIVATE)) | |
| 1432 | + if (WARN_ON(!crtc_state->shared_dpll)) | |
| 1460 | 1433 | return 0; |
| 1461 | 1434 | |
| 1462 | − pll = &dev_priv->shared_dplls[pll_id]; | |
| 1463 | − state = &pll->state.hw_state; | |
| 1435 | + state = &crtc_state->dpll_hw_state; | |
| 1464 | 1436 | |
| 1465 | 1437 | clock.m1 = 2; |
| 1466 | 1438 | clock.m2 = (state->pll0 & PORT_PLL_M2_MASK) << 22; |
| @@ -1474,19 +1446,15 @@ static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, · 7 unmodified lines | ||
| 1474 | 1446 | } |
| 1475 | 1447 | |
| 1476 | 1448 | static void bxt_ddi_clock_get(struct intel_encoder *encoder, |
| 1477 | − struct intel_crtc_state *pipe_config) | |
| 1449 | + struct intel_crtc_state *pipe_config) | |
| 1478 | 1450 | { |
| 1479 | − struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1480 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1481 | − enum intel_dpll_id pll_id = port; | |
| 1482 | − | |
| 1483 | − pipe_config->port_clock = bxt_calc_pll_link(dev_priv, pll_id); | |
| 1451 | + pipe_config->port_clock = bxt_calc_pll_link(pipe_config); | |
| 1484 | 1452 | |
| 1485 | 1453 | ddi_dotclock_get(pipe_config); |
| 1486 | 1454 | } |
| 1487 | 1455 | |
| 1488 | −void intel_ddi_clock_get(struct intel_encoder *encoder, | |
| 1489 | − struct intel_crtc_state *pipe_config) | |
| 1456 | +static void intel_ddi_clock_get(struct intel_encoder *encoder, | |
| 1457 | + struct intel_crtc_state *pipe_config) | |
| 1490 | 1458 | { |
| 1491 | 1459 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1492 | 1460 | |
| @@ -1504,33 +1472,34 @@ void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state) · 11 unmodified lines | ||
| 1504 | 1472 | { |
| 1505 | 1473 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
| 1506 | 1474 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1507 | − struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc); | |
| 1508 | 1475 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
| 1509 | − int type = encoder->type; | |
| 1510 | − uint32_t temp; | |
| 1476 | + u32 temp; | |
| 1511 | 1477 | |
| 1512 | − if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) { | |
| 1513 | − WARN_ON(transcoder_is_dsi(cpu_transcoder)); | |
| 1478 | + if (!intel_crtc_has_dp_encoder(crtc_state)) | |
| 1479 | + return; | |
| 1514 | 1480 | |
| 1515 | − temp = TRANS_MSA_SYNC_CLK; | |
| 1516 | − switch (crtc_state->pipe_bpp) { | |
| 1517 | − case 18: | |
| 1518 | − temp |= TRANS_MSA_6_BPC; | |
| 1519 | − break; | |
| 1520 | − case 24: | |
| 1521 | − temp |= TRANS_MSA_8_BPC; | |
| 1522 | − break; | |
| 1523 | − case 30: | |
| 1524 | − temp |= TRANS_MSA_10_BPC; | |
| 1525 | − break; | |
| 1526 | − case 36: | |
| 1527 | − temp |= TRANS_MSA_12_BPC; | |
| 1528 | − break; | |
| 1529 | − default: | |
| 1530 | − BUG(); | |
| 1531 | − } | |
| 1532 | − I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); | |
| 1481 | + WARN_ON(transcoder_is_dsi(cpu_transcoder)); | |
| 1482 | + | |
| 1483 | + temp = TRANS_MSA_SYNC_CLK; | |
| 1484 | + switch (crtc_state->pipe_bpp) { | |
| 1485 | + case 18: | |
| 1486 | + temp |= TRANS_MSA_6_BPC; | |
| 1487 | + break; | |
| 1488 | + case 24: | |
| 1489 | + temp |= TRANS_MSA_8_BPC; | |
| 1490 | + break; | |
| 1491 | + case 30: | |
| 1492 | + temp |= TRANS_MSA_10_BPC; | |
| 1493 | + break; | |
| 1494 | + case 36: | |
| 1495 | + temp |= TRANS_MSA_12_BPC; | |
| 1496 | + break; | |
| 1497 | + default: | |
| 1498 | + MISSING_CASE(crtc_state->pipe_bpp); | |
| 1499 | + break; | |
| 1533 | 1500 | } |
| 1501 | + | |
| 1502 | + I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); | |
| 1534 | 1503 | } |
| 1535 | 1504 | |
| 1536 | 1505 | void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, |
| @@ -1540,6 +1509,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, · 3 unmodified lines | ||
| 1540 | 1509 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1541 | 1510 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
| 1542 | 1511 | uint32_t temp; |
| 1512 | + | |
| 1543 | 1513 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
| 1544 | 1514 | if (state == true) |
| 1545 | 1515 | temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; |
| @@ -1555,8 +1525,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) · 9 unmodified lines | ||
| 1555 | 1525 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1556 | 1526 | enum pipe pipe = crtc->pipe; |
| 1557 | 1527 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
| 1558 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1559 | − int type = encoder->type; | |
| 1528 | + enum port port = encoder->port; | |
| 1560 | 1529 | uint32_t temp; |
| 1561 | 1530 | |
| 1562 | 1531 | /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */ |
| @@ -1611,7 +1580,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) · 48 unmodified lines | ||
| 1611 | 1580 | } |
| 1612 | 1581 | } |
| 1613 | 1582 | |
| 1614 | − if (type == INTEL_OUTPUT_HDMI) { | |
| 1583 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { | |
| 1615 | 1584 | if (crtc_state->has_hdmi_sink) |
| 1616 | 1585 | temp |= TRANS_DDI_MODE_SELECT_HDMI; |
| 1617 | 1586 | else |
| @@ -1621,19 +1590,15 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) · 3 unmodified lines | ||
| 1621 | 1590 | temp |= TRANS_DDI_HDMI_SCRAMBLING_MASK; |
| 1622 | 1591 | if (crtc_state->hdmi_high_tmds_clock_ratio) |
| 1623 | 1592 | temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE; |
| 1624 | − } else if (type == INTEL_OUTPUT_ANALOG) { | |
| 1593 | + } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) { | |
| 1625 | 1594 | temp |= TRANS_DDI_MODE_SELECT_FDI; |
| 1626 | 1595 | temp |= (crtc_state->fdi_lanes - 1) << 1; |
| 1627 | − } else if (type == INTEL_OUTPUT_DP || | |
| 1628 | − type == INTEL_OUTPUT_EDP) { | |
| 1629 | − temp |= TRANS_DDI_MODE_SELECT_DP_SST; | |
| 1630 | − temp |= DDI_PORT_WIDTH(crtc_state->lane_count); | |
| 1631 | − } else if (type == INTEL_OUTPUT_DP_MST) { | |
| 1596 | + } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { | |
| 1632 | 1597 | temp |= TRANS_DDI_MODE_SELECT_DP_MST; |
| 1633 | 1598 | temp |= DDI_PORT_WIDTH(crtc_state->lane_count); |
| 1634 | 1599 | } else { |
| 1635 | − WARN(1, "Invalid encoder type %d for pipe %c\n", | |
| 1636 | − encoder->type, pipe_name(pipe)); | |
| 1600 | + temp |= TRANS_DDI_MODE_SELECT_DP_SST; | |
| 1601 | + temp |= DDI_PORT_WIDTH(crtc_state->lane_count); | |
| 1637 | 1602 | } |
| 1638 | 1603 | |
| 1639 | 1604 | I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
| @@ -1656,7 +1621,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) · 16 unmodified lines | ||
| 1656 | 1621 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1657 | 1622 | struct intel_encoder *encoder = intel_connector->encoder; |
| 1658 | 1623 | int type = intel_connector->base.connector_type; |
| 1659 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1624 | + enum port port = encoder->port; | |
| 1660 | 1625 | enum pipe pipe = 0; |
| 1661 | 1626 | enum transcoder cpu_transcoder; |
| 1662 | 1627 | uint32_t tmp; |
| @@ -1715,9 +1680,9 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, · 52 unmodified lines | ||
| 1715 | 1680 | { |
| 1716 | 1681 | struct drm_device *dev = encoder->base.dev; |
| 1717 | 1682 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1718 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1683 | + enum port port = encoder->port; | |
| 1684 | + enum pipe p; | |
| 1719 | 1685 | u32 tmp; |
| 1720 | − int i; | |
| 1721 | 1686 | bool ret; |
| 1722 | 1687 | |
| 1723 | 1688 | if (!intel_display_power_get_if_enabled(dev_priv, |
| @@ -1752,15 +1717,17 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, · 28 unmodified lines | ||
| 1752 | 1717 | goto out; |
| 1753 | 1718 | } |
| 1754 | 1719 | |
| 1755 | − for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { | |
| 1756 | − tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); | |
| 1720 | + for_each_pipe(dev_priv, p) { | |
| 1721 | + enum transcoder cpu_transcoder = (enum transcoder) p; | |
| 1722 | + | |
| 1723 | + tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); | |
| 1757 | 1724 | |
| 1758 | 1725 | if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) { |
| 1759 | 1726 | if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == |
| 1760 | 1727 | TRANS_DDI_MODE_SELECT_DP_MST) |
| 1761 | 1728 | goto out; |
| 1762 | 1729 | |
| 1763 | − *pipe = i; | |
| 1730 | + *pipe = p; | |
| 1764 | 1731 | ret = true; |
| 1765 | 1732 | |
| 1766 | 1733 | goto out; |
| @@ -1800,7 +1767,7 @@ void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state) · 33 unmodified lines | ||
| 1800 | 1767 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
| 1801 | 1768 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1802 | 1769 | struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc); |
| 1803 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1770 | + enum port port = encoder->port; | |
| 1804 | 1771 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
| 1805 | 1772 | |
| 1806 | 1773 | if (cpu_transcoder != TRANSCODER_EDP) |
| @@ -1836,8 +1803,8 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, · 29 unmodified lines | ||
| 1836 | 1803 | int level, enum intel_output_type type) |
| 1837 | 1804 | { |
| 1838 | 1805 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); |
| 1839 | − struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); | |
| 1840 | − enum port port = intel_dig_port->port; | |
| 1806 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1807 | + enum port port = encoder->port; | |
| 1841 | 1808 | uint8_t iboost; |
| 1842 | 1809 | |
| 1843 | 1810 | if (type == INTEL_OUTPUT_HDMI) |
| @@ -1939,8 +1906,8 @@ static void cnl_ddi_vswing_program(struct intel_encoder *encoder, · 95 unmodified lines | ||
| 1939 | 1906 | int level, enum intel_output_type type) |
| 1940 | 1907 | { |
| 1941 | 1908 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1942 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1943 | 1909 | const struct cnl_ddi_buf_trans *ddi_translations; |
| 1910 | + enum port port = encoder->port; | |
| 1944 | 1911 | int n_entries, ln; |
| 1945 | 1912 | u32 val; |
| 1946 | 1913 | |
| @@ -2003,7 +1970,7 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, · 56 unmodified lines | ||
| 2003 | 1970 | int level, enum intel_output_type type) |
| 2004 | 1971 | { |
| 2005 | 1972 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2006 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 1973 | + enum port port = encoder->port; | |
| 2007 | 1974 | int width, rate, ln; |
| 2008 | 1975 | u32 val; |
| 2009 | 1976 | |
| @@ -2122,7 +2089,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, · 112 unmodified lines | ||
| 2122 | 2089 | const struct intel_shared_dpll *pll) |
| 2123 | 2090 | { |
| 2124 | 2091 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2125 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2092 | + enum port port = encoder->port; | |
| 2126 | 2093 | uint32_t val; |
| 2127 | 2094 | |
| 2128 | 2095 | if (WARN_ON(!pll)) |
| @@ -2161,7 +2128,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, · 32 unmodified lines | ||
| 2161 | 2128 | static void intel_ddi_clk_disable(struct intel_encoder *encoder) |
| 2162 | 2129 | { |
| 2163 | 2130 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2164 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2131 | + enum port port = encoder->port; | |
| 2165 | 2132 | |
| 2166 | 2133 | if (IS_CANNONLAKE(dev_priv)) |
| 2167 | 2134 | I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | |
| @@ -2179,7 +2146,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, · 11 unmodified lines | ||
| 2179 | 2146 | { |
| 2180 | 2147 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2181 | 2148 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2182 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2149 | + enum port port = encoder->port; | |
| 2183 | 2150 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2184 | 2151 | bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); |
| 2185 | 2152 | int level = intel_ddi_dp_level(intel_dp); |
| @@ -2200,7 +2167,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, · 14 unmodified lines | ||
| 2200 | 2167 | else if (IS_GEN9_LP(dev_priv)) |
| 2201 | 2168 | bxt_ddi_vswing_sequence(encoder, level, encoder->type); |
| 2202 | 2169 | else |
| 2203 | − intel_prepare_dp_ddi_buffers(encoder); | |
| 2170 | + intel_prepare_dp_ddi_buffers(encoder, crtc_state); | |
| 2204 | 2171 | |
| 2205 | 2172 | intel_ddi_init_dp_buf_reg(encoder); |
| 2206 | 2173 | if (!is_mst) |
| @@ -2217,7 +2184,7 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, · 10 unmodified lines | ||
| 2217 | 2184 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); |
| 2218 | 2185 | struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; |
| 2219 | 2186 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2220 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2187 | + enum port port = encoder->port; | |
| 2221 | 2188 | int level = intel_ddi_hdmi_level(dev_priv, port); |
| 2222 | 2189 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2223 | 2190 | |
| @@ -2249,6 +2216,19 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder, · 25 unmodified lines | ||
| 2249 | 2216 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 2250 | 2217 | enum pipe pipe = crtc->pipe; |
| 2251 | 2218 | |
| 2219 | + /* | |
| 2220 | + * When called from DP MST code: | |
| 2221 | + * - conn_state will be NULL | |
| 2222 | + * - encoder will be the main encoder (ie. mst->primary) | |
| 2223 | + * - the main connector associated with this port | |
| 2224 | + * won't be active or linked to a crtc | |
| 2225 | + * - crtc_state will be the state of the first stream to | |
| 2226 | + * be activated on this port, and it may not be the same | |
| 2227 | + * stream that will be deactivated last, but each stream | |
| 2228 | + * should have a state that is identical when it comes to | |
| 2229 | + * the DP link parameteres | |
| 2230 | + */ | |
| 2231 | + | |
| 2252 | 2232 | WARN_ON(crtc_state->has_pch_encoder); |
| 2253 | 2233 | |
| 2254 | 2234 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); |
| @@ -2262,7 +2242,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder, · 7 unmodified lines | ||
| 2262 | 2242 | static void intel_disable_ddi_buf(struct intel_encoder *encoder) |
| 2263 | 2243 | { |
| 2264 | 2244 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2265 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2245 | + enum port port = encoder->port; | |
| 2266 | 2246 | bool wait = false; |
| 2267 | 2247 | u32 val; |
| 2268 | 2248 | |
| @@ -2289,12 +2269,7 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, · 20 unmodified lines | ||
| 2289 | 2269 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2290 | 2270 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2291 | 2271 | struct intel_dp *intel_dp = &dig_port->dp; |
| 2292 | − /* | |
| 2293 | − * old_crtc_state and old_conn_state are NULL when called from | |
| 2294 | − * DP_MST. The main connector associated with this port is never | |
| 2295 | − * bound to a crtc for MST. | |
| 2296 | − */ | |
| 2297 | − bool is_mst = !old_crtc_state; | |
| 2272 | + bool is_mst = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST); | |
| 2298 | 2273 | |
| 2299 | 2274 | /* |
| 2300 | 2275 | * Power down sink before disabling the port, otherwise we end |
| @@ -2338,12 +2313,19 @@ static void intel_ddi_post_disable(struct intel_encoder *encoder, · 37 unmodified lines | ||
| 2338 | 2313 | const struct drm_connector_state *old_conn_state) |
| 2339 | 2314 | { |
| 2340 | 2315 | /* |
| 2341 | − * old_crtc_state and old_conn_state are NULL when called from | |
| 2342 | − * DP_MST. The main connector associated with this port is never | |
| 2343 | − * bound to a crtc for MST. | |
| 2316 | + * When called from DP MST code: | |
| 2317 | + * - old_conn_state will be NULL | |
| 2318 | + * - encoder will be the main encoder (ie. mst->primary) | |
| 2319 | + * - the main connector associated with this port | |
| 2320 | + * won't be active or linked to a crtc | |
| 2321 | + * - old_crtc_state will be the state of the last stream to | |
| 2322 | + * be deactivated on this port, and it may not be the same | |
| 2323 | + * stream that was activated last, but each stream | |
| 2324 | + * should have a state that is identical when it comes to | |
| 2325 | + * the DP link parameteres | |
| 2344 | 2326 | */ |
| 2345 | − if (old_crtc_state && | |
| 2346 | − intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) | |
| 2327 | + | |
| 2328 | + if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) | |
| 2347 | 2329 | intel_ddi_post_disable_hdmi(encoder, |
| 2348 | 2330 | old_crtc_state, old_conn_state); |
| 2349 | 2331 | else |
| @@ -2391,7 +2373,7 @@ static void intel_enable_ddi_dp(struct intel_encoder *encoder, · 41 unmodified lines | ||
| 2391 | 2373 | { |
| 2392 | 2374 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2393 | 2375 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2394 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2376 | + enum port port = encoder->port; | |
| 2395 | 2377 | |
| 2396 | 2378 | if (port == PORT_A && INTEL_GEN(dev_priv) < 9) |
| 2397 | 2379 | intel_dp_stop_link_train(intel_dp); |
| @@ -2410,7 +2392,7 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder, · 12 unmodified lines | ||
| 2410 | 2392 | { |
| 2411 | 2393 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2412 | 2394 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
| 2413 | − enum port port = intel_ddi_get_encoder_port(encoder); | |
| 2395 | + enum port port = encoder->port; | |
| 2414 | 2396 | |
| 2415 | 2397 | intel_hdmi_handle_sink_scrambling(encoder, |
| 2416 | 2398 | conn_state->connector, |
| @@ -2445,7 +2427,8 @@ static void intel_disable_ddi_dp(struct intel_encoder *encoder, · 28 unmodified lines | ||
| 2445 | 2427 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2446 | 2428 | |
| 2447 | 2429 | if (old_crtc_state->has_audio) |
| 2448 | − intel_audio_codec_disable(encoder); | |
| 2430 | + intel_audio_codec_disable(encoder, | |
| 2431 | + old_crtc_state, old_conn_state); | |
| 2449 | 2432 | |
| 2450 | 2433 | intel_edp_drrs_disable(intel_dp, old_crtc_state); |
| 2451 | 2434 | intel_psr_disable(intel_dp, old_crtc_state); |
| @@ -2457,7 +2440,8 @@ static void intel_disable_ddi_hdmi(struct intel_encoder *encoder, · 5 unmodified lines | ||
| 2457 | 2440 | const struct drm_connector_state *old_conn_state) |
| 2458 | 2441 | { |
| 2459 | 2442 | if (old_crtc_state->has_audio) |
| 2460 | − intel_audio_codec_disable(encoder); | |
| 2443 | + intel_audio_codec_disable(encoder, | |
| 2444 | + old_crtc_state, old_conn_state); | |
| 2461 | 2445 | |
| 2462 | 2446 | intel_hdmi_handle_sink_scrambling(encoder, |
| 2463 | 2447 | old_conn_state->connector, |
| @@ -2488,7 +2472,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) · 24 unmodified lines | ||
| 2488 | 2472 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 2489 | 2473 | struct drm_i915_private *dev_priv = |
| 2490 | 2474 | to_i915(intel_dig_port->base.base.dev); |
| 2491 | − enum port port = intel_dig_port->port; | |
| 2475 | + enum port port = intel_dig_port->base.port; | |
| 2492 | 2476 | uint32_t val; |
| 2493 | 2477 | bool wait = false; |
| 2494 | 2478 | |
| @@ -2542,11 +2526,18 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, · 47 unmodified lines | ||
| 2542 | 2526 | return false; |
| 2543 | 2527 | } |
| 2544 | 2528 | |
| 2529 | +void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, | |
| 2530 | + struct intel_crtc_state *crtc_state) | |
| 2531 | +{ | |
| 2532 | + if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000) | |
| 2533 | + crtc_state->min_voltage_level = 2; | |
| 2534 | +} | |
| 2535 | + | |
| 2545 | 2536 | void intel_ddi_get_config(struct intel_encoder *encoder, |
| 2546 | 2537 | struct intel_crtc_state *pipe_config) |
| 2547 | 2538 | { |
| 2548 | 2539 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2549 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 2540 | + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 2550 | 2541 | enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; |
| 2551 | 2542 | struct intel_digital_port *intel_dig_port; |
| 2552 | 2543 | u32 temp, flags = 0; |
| @@ -2599,12 +2590,23 @@ void intel_ddi_get_config(struct intel_encoder *encoder, · 46 unmodified lines | ||
| 2599 | 2590 | pipe_config->hdmi_high_tmds_clock_ratio = true; |
| 2600 | 2591 | /* fall through */ |
| 2601 | 2592 | case TRANS_DDI_MODE_SELECT_DVI: |
| 2593 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI); | |
| 2602 | 2594 | pipe_config->lane_count = 4; |
| 2603 | 2595 | break; |
| 2604 | 2596 | case TRANS_DDI_MODE_SELECT_FDI: |
| 2597 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG); | |
| 2605 | 2598 | break; |
| 2606 | 2599 | case TRANS_DDI_MODE_SELECT_DP_SST: |
| 2600 | + if (encoder->type == INTEL_OUTPUT_EDP) | |
| 2601 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP); | |
| 2602 | + else | |
| 2603 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_DP); | |
| 2604 | + pipe_config->lane_count = | |
| 2605 | + ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; | |
| 2606 | + intel_dp_get_m_n(intel_crtc, pipe_config); | |
| 2607 | + break; | |
| 2607 | 2608 | case TRANS_DDI_MODE_SELECT_DP_MST: |
| 2609 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST); | |
| 2608 | 2610 | pipe_config->lane_count = |
| 2609 | 2611 | ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; |
| 2610 | 2612 | intel_dp_get_m_n(intel_crtc, pipe_config); |
| @@ -2641,6 +2643,26 @@ void intel_ddi_get_config(struct intel_encoder *encoder, · 30 unmodified lines | ||
| 2641 | 2643 | if (IS_GEN9_LP(dev_priv)) |
| 2642 | 2644 | pipe_config->lane_lat_optim_mask = |
| 2643 | 2645 | bxt_ddi_phy_get_lane_lat_optim_mask(encoder); |
| 2646 | + | |
| 2647 | + intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); | |
| 2648 | +} | |
| 2649 | + | |
| 2650 | +static enum intel_output_type | |
| 2651 | +intel_ddi_compute_output_type(struct intel_encoder *encoder, | |
| 2652 | + struct intel_crtc_state *crtc_state, | |
| 2653 | + struct drm_connector_state *conn_state) | |
| 2654 | +{ | |
| 2655 | + switch (conn_state->connector->connector_type) { | |
| 2656 | + case DRM_MODE_CONNECTOR_HDMIA: | |
| 2657 | + return INTEL_OUTPUT_HDMI; | |
| 2658 | + case DRM_MODE_CONNECTOR_eDP: | |
| 2659 | + return INTEL_OUTPUT_EDP; | |
| 2660 | + case DRM_MODE_CONNECTOR_DisplayPort: | |
| 2661 | + return INTEL_OUTPUT_DP; | |
| 2662 | + default: | |
| 2663 | + MISSING_CASE(conn_state->connector->connector_type); | |
| 2664 | + return INTEL_OUTPUT_UNUSED; | |
| 2665 | + } | |
| 2644 | 2666 | } |
| 2645 | 2667 | |
| 2646 | 2668 | static bool intel_ddi_compute_config(struct intel_encoder *encoder, |
| @@ -2648,24 +2670,22 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder, · 1 unmodified line | ||
| 2648 | 2670 | struct drm_connector_state *conn_state) |
| 2649 | 2671 | { |
| 2650 | 2672 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 2651 | − int type = encoder->type; | |
| 2652 | − int port = intel_ddi_get_encoder_port(encoder); | |
| 2673 | + enum port port = encoder->port; | |
| 2653 | 2674 | int ret; |
| 2654 | 2675 | |
| 2655 | − WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n"); | |
| 2656 | − | |
| 2657 | 2676 | if (port == PORT_A) |
| 2658 | 2677 | pipe_config->cpu_transcoder = TRANSCODER_EDP; |
| 2659 | 2678 | |
| 2660 | − if (type == INTEL_OUTPUT_HDMI) | |
| 2679 | + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) | |
| 2661 | 2680 | ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state); |
| 2662 | 2681 | else |
| 2663 | 2682 | ret = intel_dp_compute_config(encoder, pipe_config, conn_state); |
| 2664 | 2683 | |
| 2665 | 2684 | if (IS_GEN9_LP(dev_priv) && ret) |
| 2666 | 2685 | pipe_config->lane_lat_optim_mask = |
| 2667 | − bxt_ddi_phy_calc_lane_lat_optim_mask(encoder, | |
| 2668 | − pipe_config->lane_count); | |
| 2686 | + bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); | |
| 2687 | + | |
| 2688 | + intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); | |
| 2669 | 2689 | |
| 2670 | 2690 | return ret; |
| 2671 | 2691 | |
| @@ -2680,7 +2700,7 @@ static struct intel_connector * · 8 unmodified lines | ||
| 2680 | 2700 | intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) |
| 2681 | 2701 | { |
| 2682 | 2702 | struct intel_connector *connector; |
| 2683 | − enum port port = intel_dig_port->port; | |
| 2703 | + enum port port = intel_dig_port->base.port; | |
| 2684 | 2704 | |
| 2685 | 2705 | connector = intel_connector_alloc(); |
| 2686 | 2706 | if (!connector) |
| @@ -2699,7 +2719,7 @@ static struct intel_connector * · 12 unmodified lines | ||
| 2699 | 2719 | intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) |
| 2700 | 2720 | { |
| 2701 | 2721 | struct intel_connector *connector; |
| 2702 | − enum port port = intel_dig_port->port; | |
| 2722 | + enum port port = intel_dig_port->base.port; | |
| 2703 | 2723 | |
| 2704 | 2724 | connector = intel_connector_alloc(); |
| 2705 | 2725 | if (!connector) |
| @@ -2711,6 +2731,34 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) · 5 unmodified lines | ||
| 2711 | 2731 | return connector; |
| 2712 | 2732 | } |
| 2713 | 2733 | |
| 2734 | +static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) | |
| 2735 | +{ | |
| 2736 | + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); | |
| 2737 | + | |
| 2738 | + if (dport->base.port != PORT_A) | |
| 2739 | + return false; | |
| 2740 | + | |
| 2741 | + if (dport->saved_port_bits & DDI_A_4_LANES) | |
| 2742 | + return false; | |
| 2743 | + | |
| 2744 | + /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only | |
| 2745 | + * supported configuration | |
| 2746 | + */ | |
| 2747 | + if (IS_GEN9_LP(dev_priv)) | |
| 2748 | + return true; | |
| 2749 | + | |
| 2750 | + /* Cannonlake: Most of SKUs don't support DDI_E, and the only | |
| 2751 | + * one who does also have a full A/E split called | |
| 2752 | + * DDI_F what makes DDI_E useless. However for this | |
| 2753 | + * case let's trust VBT info. | |
| 2754 | + */ | |
| 2755 | + if (IS_CANNONLAKE(dev_priv) && | |
| 2756 | + !intel_bios_is_port_present(dev_priv, PORT_E)) | |
| 2757 | + return true; | |
| 2758 | + | |
| 2759 | + return false; | |
| 2760 | +} | |
| 2761 | + | |
| 2714 | 2762 | void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) |
| 2715 | 2763 | { |
| 2716 | 2764 | struct intel_digital_port *intel_dig_port; |
| @@ -2777,6 +2825,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) · 60 unmodified lines | ||
| 2777 | 2825 | drm_encoder_init(&dev_priv->drm, encoder, &intel_ddi_funcs, |
| 2778 | 2826 | DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port)); |
| 2779 | 2827 | |
| 2828 | + intel_encoder->compute_output_type = intel_ddi_compute_output_type; | |
| 2780 | 2829 | intel_encoder->compute_config = intel_ddi_compute_config; |
| 2781 | 2830 | intel_encoder->enable = intel_enable_ddi; |
| 2782 | 2831 | if (IS_GEN9_LP(dev_priv)) |
| @@ -2789,7 +2838,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) · 6 unmodified lines | ||
| 2789 | 2838 | intel_encoder->suspend = intel_dp_encoder_suspend; |
| 2790 | 2839 | intel_encoder->get_power_domains = intel_ddi_get_power_domains; |
| 2791 | 2840 | |
| 2792 | − intel_dig_port->port = port; | |
| 2793 | 2841 | intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & |
| 2794 | 2842 | (DDI_BUF_PORT_REVERSAL | |
| 2795 | 2843 | DDI_A_4_LANES); |
| @@ -2820,23 +2868,20 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) · 24 unmodified lines | ||
| 2820 | 2868 | } |
| 2821 | 2869 | |
| 2822 | 2870 | /* |
| 2823 | − * Bspec says that DDI_A_4_LANES is the only supported configuration | |
| 2824 | − * for Broxton. Yet some BIOS fail to set this bit on port A if eDP | |
| 2825 | − * wasn't lit up at boot. Force this bit on in our internal | |
| 2826 | − * configuration so that we use the proper lane count for our | |
| 2827 | − * calculations. | |
| 2871 | + * Some BIOS might fail to set this bit on port A if eDP | |
| 2872 | + * wasn't lit up at boot. Force this bit set when needed | |
| 2873 | + * so we use the proper lane count for our calculations. | |
| 2828 | 2874 | */ |
| 2829 | − if (IS_GEN9_LP(dev_priv) && port == PORT_A) { | |
| 2830 | − if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { | |
| 2831 | − DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); | |
| 2832 | − intel_dig_port->saved_port_bits |= DDI_A_4_LANES; | |
| 2833 | − max_lanes = 4; | |
| 2834 | − } | |
| 2875 | + if (intel_ddi_a_force_4_lanes(intel_dig_port)) { | |
| 2876 | + DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); | |
| 2877 | + intel_dig_port->saved_port_bits |= DDI_A_4_LANES; | |
| 2878 | + max_lanes = 4; | |
| 2835 | 2879 | } |
| 2836 | 2880 | |
| 2881 | + intel_dig_port->dp.output_reg = INVALID_MMIO_REG; | |
| 2837 | 2882 | intel_dig_port->max_lanes = max_lanes; |
| 2838 | 2883 | |
| 2839 | − intel_encoder->type = INTEL_OUTPUT_UNKNOWN; | |
| 2884 | + intel_encoder->type = INTEL_OUTPUT_DDI; | |
| 2840 | 2885 | intel_encoder->power_domain = intel_port_to_power_domain(port); |
| 2841 | 2886 | intel_encoder->port = port; |
| 2842 | 2887 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| @@ -235,16 +235,6 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) · 234 unmodified lines | ||
| 235 | 235 | #define IS_SS_DISABLED(ss) (!(sseu->subslice_mask & BIT(ss))) |
| 236 | 236 | info->has_pooled_eu = hweight8(sseu->subslice_mask) == 3; |
| 237 | 237 | |
| 238 | − /* | |
| 239 | − * There is a HW issue in 2x6 fused down parts that requires | |
| 240 | − * Pooled EU to be enabled as a WA. The pool configuration | |
| 241 | − * changes depending upon which subslice is fused down. This | |
| 242 | − * doesn't affect if the device has all 3 subslices enabled. | |
| 243 | − */ | |
| 244 | − /* WaEnablePooledEuFor2x6:bxt */ | |
| 245 | − info->has_pooled_eu |= (hweight8(sseu->subslice_mask) == 2 && | |
| 246 | − IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST)); | |
| 247 | − | |
| 248 | 238 | sseu->min_eu_in_pool = 0; |
| 249 | 239 | if (info->has_pooled_eu) { |
| 250 | 240 | if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) |
| @@ -329,6 +319,107 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) · 78 unmodified lines | ||
| 329 | 319 | sseu->has_eu_pg = 0; |
| 330 | 320 | } |
| 331 | 321 | |
| 322 | +static u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) | |
| 323 | +{ | |
| 324 | + u32 ts_override = I915_READ(GEN9_TIMESTAMP_OVERRIDE); | |
| 325 | + u32 base_freq, frac_freq; | |
| 326 | + | |
| 327 | + base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >> | |
| 328 | + GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1; | |
| 329 | + base_freq *= 1000; | |
| 330 | + | |
| 331 | + frac_freq = ((ts_override & | |
| 332 | + GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >> | |
| 333 | + GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT); | |
| 334 | + frac_freq = 1000 / (frac_freq + 1); | |
| 335 | + | |
| 336 | + return base_freq + frac_freq; | |
| 337 | +} | |
| 338 | + | |
| 339 | +static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) | |
| 340 | +{ | |
| 341 | + u32 f12_5_mhz = 12500; | |
| 342 | + u32 f19_2_mhz = 19200; | |
| 343 | + u32 f24_mhz = 24000; | |
| 344 | + | |
| 345 | + if (INTEL_GEN(dev_priv) <= 4) { | |
| 346 | + /* PRMs say: | |
| 347 | + * | |
| 348 | + * "The value in this register increments once every 16 | |
| 349 | + * hclks." (through the “Clocking Configuration” | |
| 350 | + * (“CLKCFG”) MCHBAR register) | |
| 351 | + */ | |
| 352 | + return dev_priv->rawclk_freq / 16; | |
| 353 | + } else if (INTEL_GEN(dev_priv) <= 8) { | |
| 354 | + /* PRMs say: | |
| 355 | + * | |
| 356 | + * "The PCU TSC counts 10ns increments; this timestamp | |
| 357 | + * reflects bits 38:3 of the TSC (i.e. 80ns granularity, | |
| 358 | + * rolling over every 1.5 hours). | |
| 359 | + */ | |
| 360 | + return f12_5_mhz; | |
| 361 | + } else if (INTEL_GEN(dev_priv) <= 9) { | |
| 362 | + u32 ctc_reg = I915_READ(CTC_MODE); | |
| 363 | + u32 freq = 0; | |
| 364 | + | |
| 365 | + if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
| 366 | + freq = read_reference_ts_freq(dev_priv); | |
| 367 | + } else { | |
| 368 | + freq = IS_GEN9_LP(dev_priv) ? f19_2_mhz : f24_mhz; | |
| 369 | + | |
| 370 | + /* Now figure out how the command stream's timestamp | |
| 371 | + * register increments from this frequency (it might | |
| 372 | + * increment only every few clock cycle). | |
| 373 | + */ | |
| 374 | + freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >> | |
| 375 | + CTC_SHIFT_PARAMETER_SHIFT); | |
| 376 | + } | |
| 377 | + | |
| 378 | + return freq; | |
| 379 | + } else if (INTEL_GEN(dev_priv) <= 10) { | |
| 380 | + u32 ctc_reg = I915_READ(CTC_MODE); | |
| 381 | + u32 freq = 0; | |
| 382 | + u32 rpm_config_reg = 0; | |
| 383 | + | |
| 384 | + /* First figure out the reference frequency. There are 2 ways | |
| 385 | + * we can compute the frequency, either through the | |
| 386 | + * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE | |
| 387 | + * tells us which one we should use. | |
| 388 | + */ | |
| 389 | + if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
| 390 | + freq = read_reference_ts_freq(dev_priv); | |
| 391 | + } else { | |
| 392 | + u32 crystal_clock; | |
| 393 | + | |
| 394 | + rpm_config_reg = I915_READ(RPM_CONFIG0); | |
| 395 | + crystal_clock = (rpm_config_reg & | |
| 396 | + GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
| 397 | + GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
| 398 | + switch (crystal_clock) { | |
| 399 | + case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
| 400 | + freq = f19_2_mhz; | |
| 401 | + break; | |
| 402 | + case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
| 403 | + freq = f24_mhz; | |
| 404 | + break; | |
| 405 | + } | |
| 406 | + } | |
| 407 | + | |
| 408 | + /* Now figure out how the command stream's timestamp register | |
| 409 | + * increments from this frequency (it might increment only | |
| 410 | + * every few clock cycle). | |
| 411 | + */ | |
| 412 | + freq >>= 3 - ((rpm_config_reg & | |
| 413 | + GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> | |
| 414 | + GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); | |
| 415 | + | |
| 416 | + return freq; | |
| 417 | + } | |
| 418 | + | |
| 419 | + DRM_ERROR("Unknown gen, unable to compute command stream timestamp frequency\n"); | |
| 420 | + return 0; | |
| 421 | +} | |
| 422 | + | |
| 332 | 423 | /* |
| 333 | 424 | * Determine various intel_device_info fields at runtime. |
| 334 | 425 | * |
| @@ -347,7 +438,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) · 12 unmodified lines | ||
| 347 | 438 | struct intel_device_info *info = mkwrite_device_info(dev_priv); |
| 348 | 439 | enum pipe pipe; |
| 349 | 440 | |
| 350 | − if (INTEL_GEN(dev_priv) >= 9) { | |
| 441 | + if (INTEL_GEN(dev_priv) >= 10) { | |
| 442 | + for_each_pipe(dev_priv, pipe) | |
| 443 | + info->num_scalers[pipe] = 2; | |
| 444 | + } else if (INTEL_GEN(dev_priv) == 9) { | |
| 351 | 445 | info->num_scalers[PIPE_A] = 2; |
| 352 | 446 | info->num_scalers[PIPE_B] = 2; |
| 353 | 447 | info->num_scalers[PIPE_C] = 1; |
| @@ -447,6 +541,9 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) · 93 unmodified lines | ||
| 447 | 541 | else if (INTEL_GEN(dev_priv) >= 10) |
| 448 | 542 | gen10_sseu_info_init(dev_priv); |
| 449 | 543 | |
| 544 | + /* Initialize command stream timestamp frequency */ | |
| 545 | + info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); | |
| 546 | + | |
| 450 | 547 | DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); |
| 451 | 548 | DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); |
| 452 | 549 | DRM_DEBUG_DRIVER("subslice total: %u\n", |
| @@ -462,4 +559,6 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) · 9 unmodified lines | ||
| 462 | 559 | info->sseu.has_subslice_pg ? "y" : "n"); |
| 463 | 560 | DRM_DEBUG_DRIVER("has EU power gating: %s\n", |
| 464 | 561 | info->sseu.has_eu_pg ? "y" : "n"); |
| 562 | + DRM_DEBUG_DRIVER("CS timestamp frequency: %u kHz\n", | |
| 563 | + info->cs_timestamp_frequency_khz); | |
| 465 | 564 | } |
| @@ -219,10 +219,8 @@ intel_fdi_link_freq(struct drm_i915_private *dev_priv, · 218 unmodified lines | ||
| 219 | 219 | { |
| 220 | 220 | if (HAS_DDI(dev_priv)) |
| 221 | 221 | return pipe_config->port_clock; /* SPLL */ |
| 222 | − else if (IS_GEN5(dev_priv)) | |
| 223 | − return ((I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2) * 10000; | |
| 224 | 222 | else |
| 225 | − return 270000; | |
| 223 | + return dev_priv->fdi_pll_freq; | |
| 226 | 224 | } |
| 227 | 225 | |
| 228 | 226 | static const struct intel_limit intel_limits_i8xx_dac = { |
| @@ -1703,7 +1701,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, · 1474 unmodified lines | ||
| 1703 | 1701 | u32 port_mask; |
| 1704 | 1702 | i915_reg_t dpll_reg; |
| 1705 | 1703 | |
| 1706 | − switch (dport->port) { | |
| 1704 | + switch (dport->base.port) { | |
| 1707 | 1705 | case PORT_B: |
| 1708 | 1706 | port_mask = DPLL_PORTB_READY_MASK; |
| 1709 | 1707 | dpll_reg = DPLL(0); |
| @@ -1725,7 +1723,8 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, · 15 unmodified lines | ||
| 1725 | 1723 | dpll_reg, port_mask, expected_mask, |
| 1726 | 1724 | 1000)) |
| 1727 | 1725 | WARN(1, "timed out waiting for port %c ready: got 0x%x, expected 0x%x\n", |
| 1728 | − port_name(dport->port), I915_READ(dpll_reg) & port_mask, expected_mask); | |
| 1726 | + port_name(dport->base.port), | |
| 1727 | + I915_READ(dpll_reg) & port_mask, expected_mask); | |
| 1729 | 1728 | } |
| 1730 | 1729 | |
| 1731 | 1730 | static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, |
| @@ -1873,8 +1872,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) · 141 unmodified lines | ||
| 1873 | 1872 | { |
| 1874 | 1873 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1875 | 1874 | |
| 1876 | − WARN_ON(!crtc->config->has_pch_encoder); | |
| 1877 | − | |
| 1878 | 1875 | if (HAS_PCH_LPT(dev_priv)) |
| 1879 | 1876 | return PIPE_A; |
| 1880 | 1877 | else |
| @@ -3433,20 +3430,11 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format) · 1552 unmodified lines | ||
| 3433 | 3430 | case DRM_FORMAT_RGB565: |
| 3434 | 3431 | return PLANE_CTL_FORMAT_RGB_565; |
| 3435 | 3432 | case DRM_FORMAT_XBGR8888: |
| 3433 | + case DRM_FORMAT_ABGR8888: | |
| 3436 | 3434 | return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX; |
| 3437 | 3435 | case DRM_FORMAT_XRGB8888: |
| 3438 | − return PLANE_CTL_FORMAT_XRGB_8888; | |
| 3439 | − /* | |
| 3440 | − * XXX: For ARBG/ABGR formats we default to expecting scanout buffers | |
| 3441 | − * to be already pre-multiplied. We need to add a knob (or a different | |
| 3442 | − * DRM_FORMAT) for user-space to configure that. | |
| 3443 | − */ | |
| 3444 | − case DRM_FORMAT_ABGR8888: | |
| 3445 | − return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX | | |
| 3446 | − PLANE_CTL_ALPHA_SW_PREMULTIPLY; | |
| 3447 | 3436 | case DRM_FORMAT_ARGB8888: |
| 3448 | − return PLANE_CTL_FORMAT_XRGB_8888 | | |
| 3449 | − PLANE_CTL_ALPHA_SW_PREMULTIPLY; | |
| 3437 | + return PLANE_CTL_FORMAT_XRGB_8888; | |
| 3450 | 3438 | case DRM_FORMAT_XRGB2101010: |
| 3451 | 3439 | return PLANE_CTL_FORMAT_XRGB_2101010; |
| 3452 | 3440 | case DRM_FORMAT_XBGR2101010: |
| @@ -3466,6 +3454,33 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format) · 13 unmodified lines | ||
| 3466 | 3454 | return 0; |
| 3467 | 3455 | } |
| 3468 | 3456 | |
| 3457 | +/* | |
| 3458 | + * XXX: For ARBG/ABGR formats we default to expecting scanout buffers | |
| 3459 | + * to be already pre-multiplied. We need to add a knob (or a different | |
| 3460 | + * DRM_FORMAT) for user-space to configure that. | |
| 3461 | + */ | |
| 3462 | +static u32 skl_plane_ctl_alpha(uint32_t pixel_format) | |
| 3463 | +{ | |
| 3464 | + switch (pixel_format) { | |
| 3465 | + case DRM_FORMAT_ABGR8888: | |
| 3466 | + case DRM_FORMAT_ARGB8888: | |
| 3467 | + return PLANE_CTL_ALPHA_SW_PREMULTIPLY; | |
| 3468 | + default: | |
| 3469 | + return PLANE_CTL_ALPHA_DISABLE; | |
| 3470 | + } | |
| 3471 | +} | |
| 3472 | + | |
| 3473 | +static u32 glk_plane_color_ctl_alpha(uint32_t pixel_format) | |
| 3474 | +{ | |
| 3475 | + switch (pixel_format) { | |
| 3476 | + case DRM_FORMAT_ABGR8888: | |
| 3477 | + case DRM_FORMAT_ARGB8888: | |
| 3478 | + return PLANE_COLOR_ALPHA_SW_PREMULTIPLY; | |
| 3479 | + default: | |
| 3480 | + return PLANE_COLOR_ALPHA_DISABLE; | |
| 3481 | + } | |
| 3482 | +} | |
| 3483 | + | |
| 3469 | 3484 | static u32 skl_plane_ctl_tiling(uint64_t fb_modifier) |
| 3470 | 3485 | { |
| 3471 | 3486 | switch (fb_modifier) { |
| @@ -3522,7 +3537,8 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, · 50 unmodified lines | ||
| 3522 | 3537 | |
| 3523 | 3538 | plane_ctl = PLANE_CTL_ENABLE; |
| 3524 | 3539 | |
| 3525 | − if (!IS_GEMINILAKE(dev_priv) && !IS_CANNONLAKE(dev_priv)) { | |
| 3540 | + if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) { | |
| 3541 | + plane_ctl |= skl_plane_ctl_alpha(fb->format->format); | |
| 3526 | 3542 | plane_ctl |= |
| 3527 | 3543 | PLANE_CTL_PIPE_GAMMA_ENABLE | |
| 3528 | 3544 | PLANE_CTL_PIPE_CSC_ENABLE | |
| @@ -3541,6 +3557,20 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, · 12 unmodified lines | ||
| 3541 | 3557 | return plane_ctl; |
| 3542 | 3558 | } |
| 3543 | 3559 | |
| 3560 | +u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |
| 3561 | + const struct intel_plane_state *plane_state) | |
| 3562 | +{ | |
| 3563 | + const struct drm_framebuffer *fb = plane_state->base.fb; | |
| 3564 | + u32 plane_color_ctl = 0; | |
| 3565 | + | |
| 3566 | + plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; | |
| 3567 | + plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; | |
| 3568 | + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; | |
| 3569 | + plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); | |
| 3570 | + | |
| 3571 | + return plane_color_ctl; | |
| 3572 | +} | |
| 3573 | + | |
| 3544 | 3574 | static int |
| 3545 | 3575 | __intel_display_resume(struct drm_device *dev, |
| 3546 | 3576 | struct drm_atomic_state *state, |
| @@ -4483,7 +4513,7 @@ intel_trans_dp_port_sel(struct intel_crtc *crtc) · 936 unmodified lines | ||
| 4483 | 4513 | for_each_encoder_on_crtc(dev, &crtc->base, encoder) { |
| 4484 | 4514 | if (encoder->type == INTEL_OUTPUT_DP || |
| 4485 | 4515 | encoder->type == INTEL_OUTPUT_EDP) |
| 4486 | − return enc_to_dig_port(&encoder->base)->port; | |
| 4516 | + return encoder->port; | |
| 4487 | 4517 | } |
| 4488 | 4518 | |
| 4489 | 4519 | return -1; |
| @@ -4834,8 +4864,9 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) · 344 unmodified lines | ||
| 4834 | 4864 | } |
| 4835 | 4865 | } |
| 4836 | 4866 | |
| 4837 | −void hsw_enable_ips(struct intel_crtc *crtc) | |
| 4867 | +void hsw_enable_ips(const struct intel_crtc_state *crtc_state) | |
| 4838 | 4868 | { |
| 4869 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 4839 | 4870 | struct drm_device *dev = crtc->base.dev; |
| 4840 | 4871 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4841 | 4872 | |
| @@ -4873,12 +4904,13 @@ void hsw_enable_ips(struct intel_crtc *crtc) · 31 unmodified lines | ||
| 4873 | 4904 | } |
| 4874 | 4905 | } |
| 4875 | 4906 | |
| 4876 | −void hsw_disable_ips(struct intel_crtc *crtc) | |
| 4907 | +void hsw_disable_ips(const struct intel_crtc_state *crtc_state) | |
| 4877 | 4908 | { |
| 4909 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 4878 | 4910 | struct drm_device *dev = crtc->base.dev; |
| 4879 | 4911 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4880 | 4912 | |
| 4881 | − if (!crtc->config->ips_enabled) | |
| 4913 | + if (!crtc_state->ips_enabled) | |
| 4882 | 4914 | return; |
| 4883 | 4915 | |
| 4884 | 4916 | assert_plane_enabled(dev_priv, crtc->plane); |
| @@ -4926,7 +4958,8 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) · 41 unmodified lines | ||
| 4926 | 4958 | * completely hide the primary plane. |
| 4927 | 4959 | */ |
| 4928 | 4960 | static void |
| 4929 | −intel_post_enable_primary(struct drm_crtc *crtc) | |
| 4961 | +intel_post_enable_primary(struct drm_crtc *crtc, | |
| 4962 | + const struct intel_crtc_state *new_crtc_state) | |
| 4930 | 4963 | { |
| 4931 | 4964 | struct drm_device *dev = crtc->dev; |
| 4932 | 4965 | struct drm_i915_private *dev_priv = to_i915(dev); |
| @@ -4939,7 +4972,7 @@ intel_post_enable_primary(struct drm_crtc *crtc) · 6 unmodified lines | ||
| 4939 | 4972 | * when going from primary only to sprite only and vice |
| 4940 | 4973 | * versa. |
| 4941 | 4974 | */ |
| 4942 | − hsw_enable_ips(intel_crtc); | |
| 4975 | + hsw_enable_ips(new_crtc_state); | |
| 4943 | 4976 | |
| 4944 | 4977 | /* |
| 4945 | 4978 | * Gen2 reports pipe underruns whenever all planes are disabled. |
| @@ -4958,7 +4991,8 @@ intel_post_enable_primary(struct drm_crtc *crtc) · 12 unmodified lines | ||
| 4958 | 4991 | |
| 4959 | 4992 | /* FIXME move all this to pre_plane_update() with proper state tracking */ |
| 4960 | 4993 | static void |
| 4961 | −intel_pre_disable_primary(struct drm_crtc *crtc) | |
| 4994 | +intel_pre_disable_primary(struct drm_crtc *crtc, | |
| 4995 | + const struct intel_crtc_state *old_crtc_state) | |
| 4962 | 4996 | { |
| 4963 | 4997 | struct drm_device *dev = crtc->dev; |
| 4964 | 4998 | struct drm_i915_private *dev_priv = to_i915(dev); |
| @@ -4980,7 +5014,7 @@ intel_pre_disable_primary(struct drm_crtc *crtc) · 15 unmodified lines | ||
| 4980 | 5014 | * when going from primary only to sprite only and vice |
| 4981 | 5015 | * versa. |
| 4982 | 5016 | */ |
| 4983 | − hsw_disable_ips(intel_crtc); | |
| 5017 | + hsw_disable_ips(old_crtc_state); | |
| 4984 | 5018 | } |
| 4985 | 5019 | |
| 4986 | 5020 | /* FIXME get rid of this and use pre_plane_update */ |
| @@ -4992,7 +5026,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) · 5 unmodified lines | ||
| 4992 | 5026 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 4993 | 5027 | int pipe = intel_crtc->pipe; |
| 4994 | 5028 | |
| 4995 | − intel_pre_disable_primary(crtc); | |
| 5029 | + intel_pre_disable_primary(crtc, to_intel_crtc_state(crtc->state)); | |
| 4996 | 5030 | |
| 4997 | 5031 | /* |
| 4998 | 5032 | * Vblank time updates from the shadow to live plane control register |
| @@ -5036,7 +5070,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) · 37 unmodified lines | ||
| 5036 | 5070 | if (primary_state->base.visible && |
| 5037 | 5071 | (needs_modeset(&pipe_config->base) || |
| 5038 | 5072 | !old_primary_state->base.visible)) |
| 5039 | − intel_post_enable_primary(&crtc->base); | |
| 5073 | + intel_post_enable_primary(&crtc->base, pipe_config); | |
| 5040 | 5074 | } |
| 5041 | 5075 | } |
| 5042 | 5076 | |
| @@ -5065,7 +5099,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, · 22 unmodified lines | ||
| 5065 | 5099 | |
| 5066 | 5100 | if (old_primary_state->base.visible && |
| 5067 | 5101 | (modeset || !primary_state->base.visible)) |
| 5068 | − intel_pre_disable_primary(&crtc->base); | |
| 5102 | + intel_pre_disable_primary(&crtc->base, old_crtc_state); | |
| 5069 | 5103 | } |
| 5070 | 5104 | |
| 5071 | 5105 | /* |
| @@ -5939,6 +5973,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, · 867 unmodified lines | ||
| 5939 | 5973 | |
| 5940 | 5974 | dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe); |
| 5941 | 5975 | dev_priv->min_cdclk[intel_crtc->pipe] = 0; |
| 5976 | + dev_priv->min_voltage_level[intel_crtc->pipe] = 0; | |
| 5942 | 5977 | } |
| 5943 | 5978 | |
| 5944 | 5979 | /* |
| @@ -7633,7 +7668,7 @@ static void ironlake_init_pch_refclk(struct drm_i915_private *dev_priv) · 1688 unmodified lines | ||
| 7633 | 7668 | break; |
| 7634 | 7669 | case INTEL_OUTPUT_EDP: |
| 7635 | 7670 | has_panel = true; |
| 7636 | − if (enc_to_dig_port(&encoder->base)->port == PORT_A) | |
| 7671 | + if (encoder->port == PORT_A) | |
| 7637 | 7672 | has_cpu_edp = true; |
| 7638 | 7673 | break; |
| 7639 | 7674 | default: |
| @@ -8426,7 +8461,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, · 786 unmodified lines | ||
| 8426 | 8461 | { |
| 8427 | 8462 | struct drm_device *dev = crtc->base.dev; |
| 8428 | 8463 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 8429 | − u32 val, base, offset, stride_mult, tiling; | |
| 8464 | + u32 val, base, offset, stride_mult, tiling, alpha; | |
| 8430 | 8465 | int pipe = crtc->pipe; |
| 8431 | 8466 | int fourcc, pixel_format; |
| 8432 | 8467 | unsigned int aligned_height; |
| @@ -8448,9 +8483,16 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, · 15 unmodified lines | ||
| 8448 | 8483 | goto error; |
| 8449 | 8484 | |
| 8450 | 8485 | pixel_format = val & PLANE_CTL_FORMAT_MASK; |
| 8486 | + | |
| 8487 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { | |
| 8488 | + alpha = I915_READ(PLANE_COLOR_CTL(pipe, 0)); | |
| 8489 | + alpha &= PLANE_COLOR_ALPHA_MASK; | |
| 8490 | + } else { | |
| 8491 | + alpha = val & PLANE_CTL_ALPHA_MASK; | |
| 8492 | + } | |
| 8493 | + | |
| 8451 | 8494 | fourcc = skl_format_to_fourcc(pixel_format, |
| 8452 | − val & PLANE_CTL_ORDER_RGBX, | |
| 8453 | − val & PLANE_CTL_ALPHA_MASK); | |
| 8495 | + val & PLANE_CTL_ORDER_RGBX, alpha); | |
| 8454 | 8496 | fb->format = drm_format_info(fourcc); |
| 8455 | 8497 | |
| 8456 | 8498 | tiling = val & PLANE_CTL_TILED_MASK; |
| @@ -8857,7 +8899,9 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) · 400 unmodified lines | ||
| 8857 | 8899 | } |
| 8858 | 8900 | |
| 8859 | 8901 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
| 8902 | + | |
| 8860 | 8903 | intel_update_cdclk(dev_priv); |
| 8904 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); | |
| 8861 | 8905 | } |
| 8862 | 8906 | |
| 8863 | 8907 | /* |
| @@ -9231,10 +9275,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, · 367 unmodified lines | ||
| 9231 | 9275 | ironlake_get_pfit_config(crtc, pipe_config); |
| 9232 | 9276 | } |
| 9233 | 9277 | |
| 9234 | − if (IS_HASWELL(dev_priv)) | |
| 9235 | − pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && | |
| 9236 | − (I915_READ(IPS_CTL) & IPS_ENABLE); | |
| 9237 | − | |
| 9238 | 9278 | if (pipe_config->cpu_transcoder != TRANSCODER_EDP && |
| 9239 | 9279 | !transcoder_is_dsi(pipe_config->cpu_transcoder)) { |
| 9240 | 9280 | pipe_config->pixel_multiplier = |
| @@ -10578,7 +10618,7 @@ static const char * const output_type_str[] = { · 1337 unmodified lines | ||
| 10578 | 10618 | OUTPUT_TYPE(DP), |
| 10579 | 10619 | OUTPUT_TYPE(EDP), |
| 10580 | 10620 | OUTPUT_TYPE(DSI), |
| 10581 | − OUTPUT_TYPE(UNKNOWN), | |
| 10621 | + OUTPUT_TYPE(DDI), | |
| 10582 | 10622 | OUTPUT_TYPE(DP_MST), |
| 10583 | 10623 | }; |
| 10584 | 10624 | |
| @@ -10749,13 +10789,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) · 164 unmodified lines | ||
| 10749 | 10789 | |
| 10750 | 10790 | switch (encoder->type) { |
| 10751 | 10791 | unsigned int port_mask; |
| 10752 | − case INTEL_OUTPUT_UNKNOWN: | |
| 10792 | + case INTEL_OUTPUT_DDI: | |
| 10753 | 10793 | if (WARN_ON(!HAS_DDI(to_i915(dev)))) |
| 10754 | 10794 | break; |
| 10755 | 10795 | case INTEL_OUTPUT_DP: |
| 10756 | 10796 | case INTEL_OUTPUT_HDMI: |
| 10757 | 10797 | case INTEL_OUTPUT_EDP: |
| 10758 | − port_mask = 1 << enc_to_dig_port(&encoder->base)->port; | |
| 10798 | + port_mask = 1 << encoder->port; | |
| 10759 | 10799 | |
| 10760 | 10800 | /* the same port mustn't appear more than once */ |
| 10761 | 10801 | if (used_ports & port_mask) |
| @@ -10765,7 +10805,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) · 3 unmodified lines | ||
| 10765 | 10805 | break; |
| 10766 | 10806 | case INTEL_OUTPUT_DP_MST: |
| 10767 | 10807 | used_mst_ports |= |
| 10768 | − 1 << enc_to_mst(&encoder->base)->primary->port; | |
| 10808 | + 1 << encoder->port; | |
| 10769 | 10809 | break; |
| 10770 | 10810 | default: |
| 10771 | 10811 | break; |
| @@ -10882,7 +10922,12 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, · 110 unmodified lines | ||
| 10882 | 10922 | * Determine output_types before calling the .compute_config() |
| 10883 | 10923 | * hooks so that the hooks can use this information safely. |
| 10884 | 10924 | */ |
| 10885 | − pipe_config->output_types |= 1 << encoder->type; | |
| 10925 | + if (encoder->compute_output_type) | |
| 10926 | + pipe_config->output_types |= | |
| 10927 | + BIT(encoder->compute_output_type(encoder, pipe_config, | |
| 10928 | + connector_state)); | |
| 10929 | + else | |
| 10930 | + pipe_config->output_types |= BIT(encoder->type); | |
| 10886 | 10931 | } |
| 10887 | 10932 | |
| 10888 | 10933 | encoder_retry: |
| @@ -11071,6 +11116,9 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 182 unmodified lines | ||
| 11071 | 11116 | bool adjust) |
| 11072 | 11117 | { |
| 11073 | 11118 | bool ret = true; |
| 11119 | + bool fixup_inherited = adjust && | |
| 11120 | + (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && | |
| 11121 | + !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); | |
| 11074 | 11122 | |
| 11075 | 11123 | #define PIPE_CONF_CHECK_X(name) \ |
| 11076 | 11124 | if (current_config->name != pipe_config->name) { \ |
| @@ -11090,6 +11138,31 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 13 unmodified lines | ||
| 11090 | 11138 | ret = false; \ |
| 11091 | 11139 | } |
| 11092 | 11140 | |
| 11141 | +#define PIPE_CONF_CHECK_BOOL(name) \ | |
| 11142 | + if (current_config->name != pipe_config->name) { \ | |
| 11143 | + pipe_config_err(adjust, __stringify(name), \ | |
| 11144 | + "(expected %s, found %s)\n", \ | |
| 11145 | + yesno(current_config->name), \ | |
| 11146 | + yesno(pipe_config->name)); \ | |
| 11147 | + ret = false; \ | |
| 11148 | + } | |
| 11149 | + | |
| 11150 | +/* | |
| 11151 | + * Checks state where we only read out the enabling, but not the entire | |
| 11152 | + * state itself (like full infoframes or ELD for audio). These states | |
| 11153 | + * require a full modeset on bootup to fix up. | |
| 11154 | + */ | |
| 11155 | +#define PIPE_CONF_CHECK_BOOL_INCOMPLETE(name) \ | |
| 11156 | + if (!fixup_inherited || (!current_config->name && !pipe_config->name)) { \ | |
| 11157 | + PIPE_CONF_CHECK_BOOL(name); \ | |
| 11158 | + } else { \ | |
| 11159 | + pipe_config_err(adjust, __stringify(name), \ | |
| 11160 | + "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)\n", \ | |
| 11161 | + yesno(current_config->name), \ | |
| 11162 | + yesno(pipe_config->name)); \ | |
| 11163 | + ret = false; \ | |
| 11164 | + } | |
| 11165 | + | |
| 11093 | 11166 | #define PIPE_CONF_CHECK_P(name) \ |
| 11094 | 11167 | if (current_config->name != pipe_config->name) { \ |
| 11095 | 11168 | pipe_config_err(adjust, __stringify(name), \ |
| @@ -11175,7 +11248,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 79 unmodified lines | ||
| 11175 | 11248 | |
| 11176 | 11249 | PIPE_CONF_CHECK_I(cpu_transcoder); |
| 11177 | 11250 | |
| 11178 | − PIPE_CONF_CHECK_I(has_pch_encoder); | |
| 11251 | + PIPE_CONF_CHECK_BOOL(has_pch_encoder); | |
| 11179 | 11252 | PIPE_CONF_CHECK_I(fdi_lanes); |
| 11180 | 11253 | PIPE_CONF_CHECK_M_N(fdi_m_n); |
| 11181 | 11254 | |
| @@ -11207,17 +11280,17 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 25 unmodified lines | ||
| 11207 | 11280 | PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end); |
| 11208 | 11281 | |
| 11209 | 11282 | PIPE_CONF_CHECK_I(pixel_multiplier); |
| 11210 | − PIPE_CONF_CHECK_I(has_hdmi_sink); | |
| 11283 | + PIPE_CONF_CHECK_BOOL(has_hdmi_sink); | |
| 11211 | 11284 | if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || |
| 11212 | 11285 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 11213 | − PIPE_CONF_CHECK_I(limited_color_range); | |
| 11286 | + PIPE_CONF_CHECK_BOOL(limited_color_range); | |
| 11214 | 11287 | |
| 11215 | − PIPE_CONF_CHECK_I(hdmi_scrambling); | |
| 11216 | − PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio); | |
| 11217 | − PIPE_CONF_CHECK_I(has_infoframe); | |
| 11218 | − PIPE_CONF_CHECK_I(ycbcr420); | |
| 11288 | + PIPE_CONF_CHECK_BOOL(hdmi_scrambling); | |
| 11289 | + PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio); | |
| 11290 | + PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_infoframe); | |
| 11291 | + PIPE_CONF_CHECK_BOOL(ycbcr420); | |
| 11219 | 11292 | |
| 11220 | − PIPE_CONF_CHECK_I(has_audio); | |
| 11293 | + PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); | |
| 11221 | 11294 | |
| 11222 | 11295 | PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, |
| 11223 | 11296 | DRM_MODE_FLAG_INTERLACE); |
| @@ -11243,7 +11316,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 19 unmodified lines | ||
| 11243 | 11316 | PIPE_CONF_CHECK_I(pipe_src_w); |
| 11244 | 11317 | PIPE_CONF_CHECK_I(pipe_src_h); |
| 11245 | 11318 | |
| 11246 | − PIPE_CONF_CHECK_I(pch_pfit.enabled); | |
| 11319 | + PIPE_CONF_CHECK_BOOL(pch_pfit.enabled); | |
| 11247 | 11320 | if (current_config->pch_pfit.enabled) { |
| 11248 | 11321 | PIPE_CONF_CHECK_X(pch_pfit.pos); |
| 11249 | 11322 | PIPE_CONF_CHECK_X(pch_pfit.size); |
| @@ -11253,11 +11326,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 3 unmodified lines | ||
| 11253 | 11326 | PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); |
| 11254 | 11327 | } |
| 11255 | 11328 | |
| 11256 | − /* BDW+ don't expose a synchronous way to read the state */ | |
| 11257 | − if (IS_HASWELL(dev_priv)) | |
| 11258 | − PIPE_CONF_CHECK_I(ips_enabled); | |
| 11259 | − | |
| 11260 | − PIPE_CONF_CHECK_I(double_wide); | |
| 11329 | + PIPE_CONF_CHECK_BOOL(double_wide); | |
| 11261 | 11330 | |
| 11262 | 11331 | PIPE_CONF_CHECK_P(shared_dpll); |
| 11263 | 11332 | PIPE_CONF_CHECK_X(dpll_hw_state.dpll); |
| @@ -11291,8 +11360,12 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, · 27 unmodified lines | ||
| 11291 | 11360 | PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); |
| 11292 | 11361 | PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); |
| 11293 | 11362 | |
| 11363 | + PIPE_CONF_CHECK_I(min_voltage_level); | |
| 11364 | + | |
| 11294 | 11365 | #undef PIPE_CONF_CHECK_X |
| 11295 | 11366 | #undef PIPE_CONF_CHECK_I |
| 11367 | +#undef PIPE_CONF_CHECK_BOOL | |
| 11368 | +#undef PIPE_CONF_CHECK_BOOL_INCOMPLETE | |
| 11296 | 11369 | #undef PIPE_CONF_CHECK_P |
| 11297 | 11370 | #undef PIPE_CONF_CHECK_FLAGS |
| 11298 | 11371 | #undef PIPE_CONF_CHECK_CLOCK_FUZZY |
| @@ -11559,10 +11632,8 @@ verify_crtc_state(struct drm_crtc *crtc, · 260 unmodified lines | ||
| 11559 | 11632 | "Encoder connected to wrong pipe %c\n", |
| 11560 | 11633 | pipe_name(pipe)); |
| 11561 | 11634 | |
| 11562 | − if (active) { | |
| 11563 | − pipe_config->output_types |= 1 << encoder->type; | |
| 11635 | + if (active) | |
| 11564 | 11636 | encoder->get_config(encoder, pipe_config); |
| 11565 | − } | |
| 11566 | 11637 | } |
| 11567 | 11638 | |
| 11568 | 11639 | intel_crtc_compute_pixel_rate(pipe_config); |
| @@ -11933,16 +12004,16 @@ static int intel_modeset_checks(struct drm_atomic_state *state) · 364 unmodified lines | ||
| 11933 | 12004 | * holding all the crtc locks, even if we don't end up |
| 11934 | 12005 | * touching the hardware |
| 11935 | 12006 | */ |
| 11936 | − if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical, | |
| 11937 | − &intel_state->cdclk.logical)) { | |
| 12007 | + if (intel_cdclk_changed(&dev_priv->cdclk.logical, | |
| 12008 | + &intel_state->cdclk.logical)) { | |
| 11938 | 12009 | ret = intel_lock_all_pipes(state); |
| 11939 | 12010 | if (ret < 0) |
| 11940 | 12011 | return ret; |
| 11941 | 12012 | } |
| 11942 | 12013 | |
| 11943 | 12014 | /* All pipes must be switched off while we change the cdclk. */ |
| 11944 | − if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual, | |
| 11945 | − &intel_state->cdclk.actual)) { | |
| 12015 | + if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual, | |
| 12016 | + &intel_state->cdclk.actual)) { | |
| 11946 | 12017 | ret = intel_modeset_all_pipes(state); |
| 11947 | 12018 | if (ret < 0) |
| 11948 | 12019 | return ret; |
| @@ -11951,6 +12022,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state) · 2 unmodified lines | ||
| 11951 | 12022 | DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n", |
| 11952 | 12023 | intel_state->cdclk.logical.cdclk, |
| 11953 | 12024 | intel_state->cdclk.actual.cdclk); |
| 12025 | + DRM_DEBUG_KMS("New voltage level calculated to be logical %u, actual %u\n", | |
| 12026 | + intel_state->cdclk.logical.voltage_level, | |
| 12027 | + intel_state->cdclk.actual.voltage_level); | |
| 11954 | 12028 | } else { |
| 11955 | 12029 | to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical; |
| 11956 | 12030 | } |
| @@ -12519,6 +12593,9 @@ static int intel_atomic_commit(struct drm_device *dev, · 562 unmodified lines | ||
| 12519 | 12593 | if (intel_state->modeset) { |
| 12520 | 12594 | memcpy(dev_priv->min_cdclk, intel_state->min_cdclk, |
| 12521 | 12595 | sizeof(intel_state->min_cdclk)); |
| 12596 | + memcpy(dev_priv->min_voltage_level, | |
| 12597 | + intel_state->min_voltage_level, | |
| 12598 | + sizeof(intel_state->min_voltage_level)); | |
| 12522 | 12599 | dev_priv->active_crtcs = intel_state->active_crtcs; |
| 12523 | 12600 | dev_priv->cdclk.logical = intel_state->cdclk.logical; |
| 12524 | 12601 | dev_priv->cdclk.actual = intel_state->cdclk.actual; |
| @@ -12756,7 +12833,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state · 231 unmodified lines | ||
| 12756 | 12833 | crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; |
| 12757 | 12834 | max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk; |
| 12758 | 12835 | |
| 12759 | − if (IS_GEMINILAKE(dev_priv)) | |
| 12836 | + if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) | |
| 12760 | 12837 | max_dotclk *= 2; |
| 12761 | 12838 | |
| 12762 | 12839 | if (WARN_ON_ONCE(!crtc_clock || max_dotclk < crtc_clock)) |
| @@ -12820,6 +12897,9 @@ intel_check_primary_plane(struct intel_plane *plane, · 57 unmodified lines | ||
| 12820 | 12897 | state->ctl = i9xx_plane_ctl(crtc_state, state); |
| 12821 | 12898 | } |
| 12822 | 12899 | |
| 12900 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | |
| 12901 | + state->color_ctl = glk_plane_color_ctl(crtc_state, state); | |
| 12902 | + | |
| 12823 | 12903 | return 0; |
| 12824 | 12904 | } |
| 12825 | 12905 | |
| @@ -12864,6 +12944,7 @@ out: · 38 unmodified lines | ||
| 12864 | 12944 | static void intel_finish_crtc_commit(struct drm_crtc *crtc, |
| 12865 | 12945 | struct drm_crtc_state *old_crtc_state) |
| 12866 | 12946 | { |
| 12947 | + struct drm_i915_private *dev_priv = to_i915(crtc->dev); | |
| 12867 | 12948 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 12868 | 12949 | struct intel_atomic_state *old_intel_state = |
| 12869 | 12950 | to_intel_atomic_state(old_crtc_state->state); |
| @@ -12871,6 +12952,20 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, · 1 unmodified line | ||
| 12871 | 12952 | intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc); |
| 12872 | 12953 | |
| 12873 | 12954 | intel_pipe_update_end(new_crtc_state); |
| 12955 | + | |
| 12956 | + if (new_crtc_state->update_pipe && | |
| 12957 | + !needs_modeset(&new_crtc_state->base) && | |
| 12958 | + old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) { | |
| 12959 | + if (!IS_GEN2(dev_priv)) | |
| 12960 | + intel_set_cpu_fifo_underrun_reporting(dev_priv, intel_crtc->pipe, true); | |
| 12961 | + | |
| 12962 | + if (new_crtc_state->has_pch_encoder) { | |
| 12963 | + enum pipe pch_transcoder = | |
| 12964 | + intel_crtc_pch_transcoder(intel_crtc); | |
| 12965 | + | |
| 12966 | + intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true); | |
| 12967 | + } | |
| 12968 | + } | |
| 12874 | 12969 | } |
| 12875 | 12970 | |
| 12876 | 12971 | /** |
| @@ -14352,6 +14447,7 @@ void intel_modeset_init_hw(struct drm_device *dev) · 1475 unmodified lines | ||
| 14352 | 14447 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 14353 | 14448 | |
| 14354 | 14449 | intel_update_cdclk(dev_priv); |
| 14450 | + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); | |
| 14355 | 14451 | dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw; |
| 14356 | 14452 | } |
| 14357 | 14453 | |
| @@ -14431,6 +14527,8 @@ retry: · 73 unmodified lines | ||
| 14431 | 14527 | |
| 14432 | 14528 | cs->wm.need_postvbl_update = true; |
| 14433 | 14529 | dev_priv->display.optimize_watermarks(intel_state, cs); |
| 14530 | + | |
| 14531 | + to_intel_crtc_state(crtc->state)->wm = cs->wm; | |
| 14434 | 14532 | } |
| 14435 | 14533 | |
| 14436 | 14534 | put_state: |
| @@ -14440,6 +14538,22 @@ fail: · 3 unmodified lines | ||
| 14440 | 14538 | drm_modeset_acquire_fini(&ctx); |
| 14441 | 14539 | } |
| 14442 | 14540 | |
| 14541 | +static void intel_update_fdi_pll_freq(struct drm_i915_private *dev_priv) | |
| 14542 | +{ | |
| 14543 | + if (IS_GEN5(dev_priv)) { | |
| 14544 | + u32 fdi_pll_clk = | |
| 14545 | + I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK; | |
| 14546 | + | |
| 14547 | + dev_priv->fdi_pll_freq = (fdi_pll_clk + 2) * 10000; | |
| 14548 | + } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { | |
| 14549 | + dev_priv->fdi_pll_freq = 270000; | |
| 14550 | + } else { | |
| 14551 | + return; | |
| 14552 | + } | |
| 14553 | + | |
| 14554 | + DRM_DEBUG_DRIVER("FDI PLL freq=%d\n", dev_priv->fdi_pll_freq); | |
| 14555 | +} | |
| 14556 | + | |
| 14443 | 14557 | int intel_modeset_init(struct drm_device *dev) |
| 14444 | 14558 | { |
| 14445 | 14559 | struct drm_i915_private *dev_priv = to_i915(dev); |
| @@ -14527,6 +14641,7 @@ int intel_modeset_init(struct drm_device *dev) · 81 unmodified lines | ||
| 14527 | 14641 | } |
| 14528 | 14642 | |
| 14529 | 14643 | intel_shared_dpll_init(dev); |
| 14644 | + intel_update_fdi_pll_freq(dev_priv); | |
| 14530 | 14645 | |
| 14531 | 14646 | intel_update_czclk(dev_priv); |
| 14532 | 14647 | intel_modeset_init_hw(dev); |
| @@ -14716,7 +14831,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, · 183 unmodified lines | ||
| 14716 | 14831 | enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; |
| 14717 | 14832 | |
| 14718 | 14833 | /* Clear any frame start delays used for debugging left by the BIOS */ |
| 14719 | − if (!transcoder_is_dsi(cpu_transcoder)) { | |
| 14834 | + if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) { | |
| 14720 | 14835 | i915_reg_t reg = PIPECONF(cpu_transcoder); |
| 14721 | 14836 | |
| 14722 | 14837 | I915_WRITE(reg, |
| @@ -14949,7 +15064,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) · 226 unmodified lines | ||
| 14949 | 15064 | crtc_state = to_intel_crtc_state(crtc->base.state); |
| 14950 | 15065 | |
| 14951 | 15066 | encoder->base.crtc = &crtc->base; |
| 14952 | − crtc_state->output_types |= 1 << encoder->type; | |
| 14953 | 15067 | encoder->get_config(encoder, crtc_state); |
| 14954 | 15068 | } else { |
| 14955 | 15069 | encoder->base.crtc = NULL; |
| @@ -15028,6 +15142,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) · 72 unmodified lines | ||
| 15028 | 15142 | } |
| 15029 | 15143 | |
| 15030 | 15144 | dev_priv->min_cdclk[crtc->pipe] = min_cdclk; |
| 15145 | + dev_priv->min_voltage_level[crtc->pipe] = | |
| 15146 | + crtc_state->min_voltage_level; | |
| 15031 | 15147 | |
| 15032 | 15148 | intel_pipe_config_sanity_check(dev_priv, crtc_state); |
| 15033 | 15149 | } |
| @@ -15051,6 +15167,23 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv) · 17 unmodified lines | ||
| 15051 | 15167 | } |
| 15052 | 15168 | } |
| 15053 | 15169 | |
| 15170 | +static void intel_early_display_was(struct drm_i915_private *dev_priv) | |
| 15171 | +{ | |
| 15172 | + /* Display WA #1185 WaDisableDARBFClkGating:cnl,glk */ | |
| 15173 | + if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) | |
| 15174 | + I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) | | |
| 15175 | + DARBF_GATING_DIS); | |
| 15176 | + | |
| 15177 | + if (IS_HASWELL(dev_priv)) { | |
| 15178 | + /* | |
| 15179 | + * WaRsPkgCStateDisplayPMReq:hsw | |
| 15180 | + * System hang if this isn't done before disabling all planes! | |
| 15181 | + */ | |
| 15182 | + I915_WRITE(CHICKEN_PAR1_1, | |
| 15183 | + I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); | |
| 15184 | + } | |
| 15185 | +} | |
| 15186 | + | |
| 15054 | 15187 | /* Scan out the current hw modeset state, |
| 15055 | 15188 | * and sanitizes it to the current state |
| 15056 | 15189 | */ |
| @@ -15064,15 +15197,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev, · 7 unmodified lines | ||
| 15064 | 15197 | struct intel_encoder *encoder; |
| 15065 | 15198 | int i; |
| 15066 | 15199 | |
| 15067 | − if (IS_HASWELL(dev_priv)) { | |
| 15068 | − /* | |
| 15069 | − * WaRsPkgCStateDisplayPMReq:hsw | |
| 15070 | − * System hang if this isn't done before disabling all planes! | |
| 15071 | − */ | |
| 15072 | − I915_WRITE(CHICKEN_PAR1_1, | |
| 15073 | − I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); | |
| 15074 | − } | |
| 15075 | − | |
| 15200 | + intel_early_display_was(dev_priv); | |
| 15076 | 15201 | intel_modeset_readout_hw_state(dev); |
| 15077 | 15202 | |
| 15078 | 15203 | /* HW state is read out, now we need to sanitize this mess. */ |
| @@ -15164,17 +15289,6 @@ void intel_display_resume(struct drm_device *dev) · 85 unmodified lines | ||
| 15164 | 15289 | drm_atomic_state_put(state); |
| 15165 | 15290 | } |
| 15166 | 15291 | |
| 15167 | −void intel_modeset_gem_init(struct drm_device *dev) | |
| 15168 | −{ | |
| 15169 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 15170 | − | |
| 15171 | − intel_init_gt_powersave(dev_priv); | |
| 15172 | − | |
| 15173 | − intel_init_clock_gating(dev_priv); | |
| 15174 | − | |
| 15175 | − intel_setup_overlay(dev_priv); | |
| 15176 | −} | |
| 15177 | − | |
| 15178 | 15292 | int intel_connector_register(struct drm_connector *connector) |
| 15179 | 15293 | { |
| 15180 | 15294 | struct intel_connector *intel_connector = to_intel_connector(connector); |
| @@ -129,11 +129,13 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector) · 128 unmodified lines | ||
| 129 | 129 | return enc_to_intel_dp(&intel_attached_encoder(connector)->base); |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | −static void intel_dp_link_down(struct intel_dp *intel_dp); | |
| 132 | +static void intel_dp_link_down(struct intel_encoder *encoder, | |
| 133 | + const struct intel_crtc_state *old_crtc_state); | |
| 133 | 134 | static bool edp_panel_vdd_on(struct intel_dp *intel_dp); |
| 134 | 135 | static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); |
| 135 | −static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); | |
| 136 | −static void vlv_steal_power_sequencer(struct drm_device *dev, | |
| 136 | +static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder, | |
| 137 | + const struct intel_crtc_state *crtc_state); | |
| 138 | +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, | |
| 137 | 139 | enum pipe pipe); |
| 138 | 140 | static void intel_dp_unset_edid(struct intel_dp *intel_dp); |
| 139 | 141 | |
| @@ -221,7 +223,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) · 81 unmodified lines | ||
| 221 | 223 | { |
| 222 | 224 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 223 | 225 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 224 | − enum port port = dig_port->port; | |
| 226 | + enum port port = dig_port->base.port; | |
| 225 | 227 | const int *source_rates; |
| 226 | 228 | int size; |
| 227 | 229 | u32 voltage; |
| @@ -427,24 +429,19 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) · 199 unmodified lines | ||
| 427 | 429 | } |
| 428 | 430 | |
| 429 | 431 | static void |
| 430 | −intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |
| 431 | − struct intel_dp *intel_dp); | |
| 432 | +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp); | |
| 432 | 433 | static void |
| 433 | −intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |
| 434 | − struct intel_dp *intel_dp, | |
| 434 | +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp, | |
| 435 | 435 | bool force_disable_vdd); |
| 436 | 436 | static void |
| 437 | −intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp); | |
| 437 | +intel_dp_pps_init(struct intel_dp *intel_dp); | |
| 438 | 438 | |
| 439 | 439 | static void pps_lock(struct intel_dp *intel_dp) |
| 440 | 440 | { |
| 441 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 442 | − struct intel_encoder *encoder = &intel_dig_port->base; | |
| 443 | − struct drm_device *dev = encoder->base.dev; | |
| 444 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 441 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 445 | 442 | |
| 446 | 443 | /* |
| 447 | − * See vlv_power_sequencer_reset() why we need | |
| 444 | + * See intel_power_sequencer_reset() why we need | |
| 448 | 445 | * a power domain reference here. |
| 449 | 446 | */ |
| 450 | 447 | intel_display_power_get(dev_priv, intel_dp->aux_power_domain); |
| @@ -454,10 +451,7 @@ static void pps_lock(struct intel_dp *intel_dp) · 3 unmodified lines | ||
| 454 | 451 | |
| 455 | 452 | static void pps_unlock(struct intel_dp *intel_dp) |
| 456 | 453 | { |
| 457 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 458 | − struct intel_encoder *encoder = &intel_dig_port->base; | |
| 459 | − struct drm_device *dev = encoder->base.dev; | |
| 460 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 454 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 461 | 455 | |
| 462 | 456 | mutex_unlock(&dev_priv->pps_mutex); |
| 463 | 457 | |
| @@ -467,8 +461,8 @@ static void pps_unlock(struct intel_dp *intel_dp) · 3 unmodified lines | ||
| 467 | 461 | static void |
| 468 | 462 | vlv_power_sequencer_kick(struct intel_dp *intel_dp) |
| 469 | 463 | { |
| 464 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 470 | 465 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 471 | − struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); | |
| 472 | 466 | enum pipe pipe = intel_dp->pps_pipe; |
| 473 | 467 | bool pll_enabled, release_cl_override = false; |
| 474 | 468 | enum dpio_phy phy = DPIO_PHY(pipe); |
| @@ -477,11 +471,11 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) · 2 unmodified lines | ||
| 477 | 471 | |
| 478 | 472 | if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, |
| 479 | 473 | "skipping pipe %c power seqeuncer kick due to port %c being active\n", |
| 480 | − pipe_name(pipe), port_name(intel_dig_port->port))) | |
| 474 | + pipe_name(pipe), port_name(intel_dig_port->base.port))) | |
| 481 | 475 | return; |
| 482 | 476 | |
| 483 | 477 | DRM_DEBUG_KMS("kicking pipe %c power sequencer for port %c\n", |
| 484 | − pipe_name(pipe), port_name(intel_dig_port->port)); | |
| 478 | + pipe_name(pipe), port_name(intel_dig_port->base.port)); | |
| 485 | 479 | |
| 486 | 480 | /* Preserve the BIOS-computed detected bit. This is |
| 487 | 481 | * supposed to be read-only. |
| @@ -578,9 +572,8 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv) · 90 unmodified lines | ||
| 578 | 572 | static enum pipe |
| 579 | 573 | vlv_power_sequencer_pipe(struct intel_dp *intel_dp) |
| 580 | 574 | { |
| 575 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 581 | 576 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 582 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 583 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 584 | 577 | enum pipe pipe; |
| 585 | 578 | |
| 586 | 579 | lockdep_assert_held(&dev_priv->pps_mutex); |
| @@ -603,16 +596,16 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) · 16 unmodified lines | ||
| 603 | 596 | if (WARN_ON(pipe == INVALID_PIPE)) |
| 604 | 597 | pipe = PIPE_A; |
| 605 | 598 | |
| 606 | − vlv_steal_power_sequencer(dev, pipe); | |
| 599 | + vlv_steal_power_sequencer(dev_priv, pipe); | |
| 607 | 600 | intel_dp->pps_pipe = pipe; |
| 608 | 601 | |
| 609 | 602 | DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n", |
| 610 | 603 | pipe_name(intel_dp->pps_pipe), |
| 611 | − port_name(intel_dig_port->port)); | |
| 604 | + port_name(intel_dig_port->base.port)); | |
| 612 | 605 | |
| 613 | 606 | /* init power sequencer on this pipe and port */ |
| 614 | − intel_dp_init_panel_power_sequencer(dev, intel_dp); | |
| 615 | − intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true); | |
| 607 | + intel_dp_init_panel_power_sequencer(intel_dp); | |
| 608 | + intel_dp_init_panel_power_sequencer_registers(intel_dp, true); | |
| 616 | 609 | |
| 617 | 610 | /* |
| 618 | 611 | * Even vdd force doesn't work until we've made |
| @@ -626,9 +619,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) · 7 unmodified lines | ||
| 626 | 619 | static int |
| 627 | 620 | bxt_power_sequencer_idx(struct intel_dp *intel_dp) |
| 628 | 621 | { |
| 629 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 630 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 631 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 622 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 632 | 623 | |
| 633 | 624 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 634 | 625 | |
| @@ -649,7 +640,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) · 14 unmodified lines | ||
| 649 | 640 | * Only the HW needs to be reprogrammed, the SW state is fixed and |
| 650 | 641 | * has been setup during connector init. |
| 651 | 642 | */ |
| 652 | − intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false); | |
| 643 | + intel_dp_init_panel_power_sequencer_registers(intel_dp, false); | |
| 653 | 644 | |
| 654 | 645 | return 0; |
| 655 | 646 | } |
| @@ -701,10 +692,9 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, · 45 unmodified lines | ||
| 701 | 692 | static void |
| 702 | 693 | vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) |
| 703 | 694 | { |
| 695 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 704 | 696 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 705 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 706 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 707 | − enum port port = intel_dig_port->port; | |
| 697 | + enum port port = intel_dig_port->base.port; | |
| 708 | 698 | |
| 709 | 699 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 710 | 700 | |
| @@ -731,13 +721,12 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) · 20 unmodified lines | ||
| 731 | 721 | DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n", |
| 732 | 722 | port_name(port), pipe_name(intel_dp->pps_pipe)); |
| 733 | 723 | |
| 734 | − intel_dp_init_panel_power_sequencer(dev, intel_dp); | |
| 735 | − intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false); | |
| 724 | + intel_dp_init_panel_power_sequencer(intel_dp); | |
| 725 | + intel_dp_init_panel_power_sequencer_registers(intel_dp, false); | |
| 736 | 726 | } |
| 737 | 727 | |
| 738 | 728 | void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) |
| 739 | 729 | { |
| 740 | − struct drm_device *dev = &dev_priv->drm; | |
| 741 | 730 | struct intel_encoder *encoder; |
| 742 | 731 | |
| 743 | 732 | if (WARN_ON(!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && |
| @@ -754,15 +743,20 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) · 10 unmodified lines | ||
| 754 | 743 | * should use them always. |
| 755 | 744 | */ |
| 756 | 745 | |
| 757 | − for_each_intel_encoder(dev, encoder) { | |
| 746 | + for_each_intel_encoder(&dev_priv->drm, encoder) { | |
| 758 | 747 | struct intel_dp *intel_dp; |
| 759 | 748 | |
| 760 | 749 | if (encoder->type != INTEL_OUTPUT_DP && |
| 761 | − encoder->type != INTEL_OUTPUT_EDP) | |
| 750 | + encoder->type != INTEL_OUTPUT_EDP && | |
| 751 | + encoder->type != INTEL_OUTPUT_DDI) | |
| 762 | 752 | continue; |
| 763 | 753 | |
| 764 | 754 | intel_dp = enc_to_intel_dp(&encoder->base); |
| 765 | 755 | |
| 756 | + /* Skip pure DVI/HDMI DDI encoders */ | |
| 757 | + if (!i915_mmio_reg_valid(intel_dp->output_reg)) | |
| 758 | + continue; | |
| 759 | + | |
| 766 | 760 | WARN_ON(intel_dp->active_pipe != INVALID_PIPE); |
| 767 | 761 | |
| 768 | 762 | if (encoder->type != INTEL_OUTPUT_EDP) |
| @@ -783,10 +777,10 @@ struct pps_registers { · 14 unmodified lines | ||
| 783 | 777 | i915_reg_t pp_div; |
| 784 | 778 | }; |
| 785 | 779 | |
| 786 | −static void intel_pps_get_registers(struct drm_i915_private *dev_priv, | |
| 787 | − struct intel_dp *intel_dp, | |
| 780 | +static void intel_pps_get_registers(struct intel_dp *intel_dp, | |
| 788 | 781 | struct pps_registers *regs) |
| 789 | 782 | { |
| 783 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 790 | 784 | int pps_idx = 0; |
| 791 | 785 | |
| 792 | 786 | memset(regs, 0, sizeof(*regs)); |
| @@ -809,8 +803,7 @@ _pp_ctrl_reg(struct intel_dp *intel_dp) · 16 unmodified lines | ||
| 809 | 803 | { |
| 810 | 804 | struct pps_registers regs; |
| 811 | 805 | |
| 812 | − intel_pps_get_registers(to_i915(intel_dp_to_dev(intel_dp)), intel_dp, | |
| 813 | − ®s); | |
| 806 | + intel_pps_get_registers(intel_dp, ®s); | |
| 814 | 807 | |
| 815 | 808 | return regs.pp_ctrl; |
| 816 | 809 | } |
| @@ -820,8 +813,7 @@ _pp_stat_reg(struct intel_dp *intel_dp) · 3 unmodified lines | ||
| 820 | 813 | { |
| 821 | 814 | struct pps_registers regs; |
| 822 | 815 | |
| 823 | − intel_pps_get_registers(to_i915(intel_dp_to_dev(intel_dp)), intel_dp, | |
| 824 | − ®s); | |
| 816 | + intel_pps_get_registers(intel_dp, ®s); | |
| 825 | 817 | |
| 826 | 818 | return regs.pp_stat; |
| 827 | 819 | } |
| @@ -833,8 +825,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, · 5 unmodified lines | ||
| 833 | 825 | { |
| 834 | 826 | struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp), |
| 835 | 827 | edp_notifier); |
| 836 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 837 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 828 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 838 | 829 | |
| 839 | 830 | if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART) |
| 840 | 831 | return 0; |
| @@ -864,8 +855,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, · 23 unmodified lines | ||
| 864 | 855 | |
| 865 | 856 | static bool edp_have_panel_power(struct intel_dp *intel_dp) |
| 866 | 857 | { |
| 867 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 868 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 858 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 869 | 859 | |
| 870 | 860 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 871 | 861 | |
| @@ -878,8 +868,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) · 6 unmodified lines | ||
| 878 | 868 | |
| 879 | 869 | static bool edp_have_panel_vdd(struct intel_dp *intel_dp) |
| 880 | 870 | { |
| 881 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 882 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 871 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 883 | 872 | |
| 884 | 873 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 885 | 874 | |
| @@ -893,8 +882,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) · 7 unmodified lines | ||
| 893 | 882 | static void |
| 894 | 883 | intel_dp_check_edp(struct intel_dp *intel_dp) |
| 895 | 884 | { |
| 896 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 897 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 885 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 898 | 886 | |
| 899 | 887 | if (!intel_dp_is_edp(intel_dp)) |
| 900 | 888 | return; |
| @@ -910,9 +898,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) · 9 unmodified lines | ||
| 910 | 898 | static uint32_t |
| 911 | 899 | intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) |
| 912 | 900 | { |
| 913 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 914 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 915 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 901 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 916 | 902 | i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg; |
| 917 | 903 | uint32_t status; |
| 918 | 904 | bool done; |
| @@ -959,7 +945,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) · 40 unmodified lines | ||
| 959 | 945 | * like to run at 2MHz. So, take the cdclk or PCH rawclk value and |
| 960 | 946 | * divide by 2000 and use that |
| 961 | 947 | */ |
| 962 | − if (intel_dig_port->port == PORT_A) | |
| 948 | + if (intel_dig_port->base.port == PORT_A) | |
| 963 | 949 | return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000); |
| 964 | 950 | else |
| 965 | 951 | return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); |
| @@ -970,7 +956,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) · 4 unmodified lines | ||
| 970 | 956 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 971 | 957 | struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); |
| 972 | 958 | |
| 973 | − if (intel_dig_port->port != PORT_A && HAS_PCH_LPT_H(dev_priv)) { | |
| 959 | + if (intel_dig_port->base.port != PORT_A && HAS_PCH_LPT_H(dev_priv)) { | |
| 974 | 960 | /* Workaround for non-ULT HSW */ |
| 975 | 961 | switch (index) { |
| 976 | 962 | case 0: return 63; |
| @@ -1440,7 +1426,7 @@ static void intel_aux_reg_init(struct intel_dp *intel_dp) · 463 unmodified lines | ||
| 1440 | 1426 | { |
| 1441 | 1427 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
| 1442 | 1428 | enum port port = intel_aux_port(dev_priv, |
| 1443 | − dp_to_dig_port(intel_dp)->port); | |
| 1429 | + dp_to_dig_port(intel_dp)->base.port); | |
| 1444 | 1430 | int i; |
| 1445 | 1431 | |
| 1446 | 1432 | intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); |
| @@ -1458,7 +1444,7 @@ static void · 11 unmodified lines | ||
| 1458 | 1444 | intel_dp_aux_init(struct intel_dp *intel_dp) |
| 1459 | 1445 | { |
| 1460 | 1446 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 1461 | − enum port port = intel_dig_port->port; | |
| 1447 | + enum port port = intel_dig_port->base.port; | |
| 1462 | 1448 | |
| 1463 | 1449 | intel_aux_reg_init(intel_dp); |
| 1464 | 1450 | drm_dp_aux_init(&intel_dp->aux); |
| @@ -1479,8 +1465,7 @@ static void · 14 unmodified lines | ||
| 1479 | 1465 | intel_dp_set_clock(struct intel_encoder *encoder, |
| 1480 | 1466 | struct intel_crtc_state *pipe_config) |
| 1481 | 1467 | { |
| 1482 | − struct drm_device *dev = encoder->base.dev; | |
| 1483 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1468 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1484 | 1469 | const struct dp_link_dpll *divisor = NULL; |
| 1485 | 1470 | int i, count = 0; |
| 1486 | 1471 | |
| @@ -1628,7 +1613,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, · 141 unmodified lines | ||
| 1628 | 1613 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1629 | 1614 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
| 1630 | 1615 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 1631 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 1616 | + enum port port = encoder->port; | |
| 1632 | 1617 | struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); |
| 1633 | 1618 | struct intel_connector *intel_connector = intel_dp->attached_connector; |
| 1634 | 1619 | struct intel_digital_connector_state *intel_conn_state = |
| @@ -1849,11 +1834,10 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, · 214 unmodified lines | ||
| 1849 | 1834 | static void intel_dp_prepare(struct intel_encoder *encoder, |
| 1850 | 1835 | const struct intel_crtc_state *pipe_config) |
| 1851 | 1836 | { |
| 1852 | − struct drm_device *dev = encoder->base.dev; | |
| 1853 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1837 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1854 | 1838 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 1855 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 1856 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 1839 | + enum port port = encoder->port; | |
| 1840 | + struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 1857 | 1841 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
| 1858 | 1842 | |
| 1859 | 1843 | intel_dp_set_link_params(intel_dp, pipe_config->port_clock, |
| @@ -1940,20 +1924,18 @@ static void intel_dp_prepare(struct intel_encoder *encoder, · 80 unmodified lines | ||
| 1940 | 1924 | #define IDLE_CYCLE_MASK (PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK) |
| 1941 | 1925 | #define IDLE_CYCLE_VALUE (0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE) |
| 1942 | 1926 | |
| 1943 | −static void intel_pps_verify_state(struct drm_i915_private *dev_priv, | |
| 1944 | − struct intel_dp *intel_dp); | |
| 1927 | +static void intel_pps_verify_state(struct intel_dp *intel_dp); | |
| 1945 | 1928 | |
| 1946 | 1929 | static void wait_panel_status(struct intel_dp *intel_dp, |
| 1947 | 1930 | u32 mask, |
| 1948 | 1931 | u32 value) |
| 1949 | 1932 | { |
| 1950 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 1951 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1933 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 1952 | 1934 | i915_reg_t pp_stat_reg, pp_ctrl_reg; |
| 1953 | 1935 | |
| 1954 | 1936 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 1955 | 1937 | |
| 1956 | − intel_pps_verify_state(dev_priv, intel_dp); | |
| 1938 | + intel_pps_verify_state(intel_dp); | |
| 1957 | 1939 | |
| 1958 | 1940 | pp_stat_reg = _pp_stat_reg(intel_dp); |
| 1959 | 1941 | pp_ctrl_reg = _pp_ctrl_reg(intel_dp); |
| @@ -2024,8 +2006,7 @@ static void edp_wait_backlight_off(struct intel_dp *intel_dp) · 64 unmodified lines | ||
| 2024 | 2006 | |
| 2025 | 2007 | static u32 ironlake_get_pp_control(struct intel_dp *intel_dp) |
| 2026 | 2008 | { |
| 2027 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2028 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2009 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2029 | 2010 | u32 control; |
| 2030 | 2011 | |
| 2031 | 2012 | lockdep_assert_held(&dev_priv->pps_mutex); |
| @@ -2046,9 +2027,8 @@ static u32 ironlake_get_pp_control(struct intel_dp *intel_dp) · 14 unmodified lines | ||
| 2046 | 2027 | */ |
| 2047 | 2028 | static bool edp_panel_vdd_on(struct intel_dp *intel_dp) |
| 2048 | 2029 | { |
| 2049 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2030 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2050 | 2031 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 2051 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2052 | 2032 | u32 pp; |
| 2053 | 2033 | i915_reg_t pp_stat_reg, pp_ctrl_reg; |
| 2054 | 2034 | bool need_to_disable = !intel_dp->want_panel_vdd; |
| @@ -2067,7 +2047,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) · 12 unmodified lines | ||
| 2067 | 2047 | intel_display_power_get(dev_priv, intel_dp->aux_power_domain); |
| 2068 | 2048 | |
| 2069 | 2049 | DRM_DEBUG_KMS("Turning eDP port %c VDD on\n", |
| 2070 | − port_name(intel_dig_port->port)); | |
| 2050 | + port_name(intel_dig_port->base.port)); | |
| 2071 | 2051 | |
| 2072 | 2052 | if (!edp_have_panel_power(intel_dp)) |
| 2073 | 2053 | wait_panel_power_cycle(intel_dp); |
| @@ -2087,7 +2067,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) · 13 unmodified lines | ||
| 2087 | 2067 | */ |
| 2088 | 2068 | if (!edp_have_panel_power(intel_dp)) { |
| 2089 | 2069 | DRM_DEBUG_KMS("eDP port %c panel power wasn't enabled\n", |
| 2090 | − port_name(intel_dig_port->port)); | |
| 2070 | + port_name(intel_dig_port->base.port)); | |
| 2091 | 2071 | msleep(intel_dp->panel_power_up_delay); |
| 2092 | 2072 | } |
| 2093 | 2073 | |
| @@ -2113,13 +2093,12 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) · 19 unmodified lines | ||
| 2113 | 2093 | pps_unlock(intel_dp); |
| 2114 | 2094 | |
| 2115 | 2095 | I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n", |
| 2116 | − port_name(dp_to_dig_port(intel_dp)->port)); | |
| 2096 | + port_name(dp_to_dig_port(intel_dp)->base.port)); | |
| 2117 | 2097 | } |
| 2118 | 2098 | |
| 2119 | 2099 | static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) |
| 2120 | 2100 | { |
| 2121 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2122 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2101 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2123 | 2102 | struct intel_digital_port *intel_dig_port = |
| 2124 | 2103 | dp_to_dig_port(intel_dp); |
| 2125 | 2104 | u32 pp; |
| @@ -2133,7 +2112,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) · 7 unmodified lines | ||
| 2133 | 2112 | return; |
| 2134 | 2113 | |
| 2135 | 2114 | DRM_DEBUG_KMS("Turning eDP port %c VDD off\n", |
| 2136 | − port_name(intel_dig_port->port)); | |
| 2115 | + port_name(intel_dig_port->base.port)); | |
| 2137 | 2116 | |
| 2138 | 2117 | pp = ironlake_get_pp_control(intel_dp); |
| 2139 | 2118 | pp &= ~EDP_FORCE_VDD; |
| @@ -2193,7 +2172,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) · 53 unmodified lines | ||
| 2193 | 2172 | return; |
| 2194 | 2173 | |
| 2195 | 2174 | I915_STATE_WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", |
| 2196 | − port_name(dp_to_dig_port(intel_dp)->port)); | |
| 2175 | + port_name(dp_to_dig_port(intel_dp)->base.port)); | |
| 2197 | 2176 | |
| 2198 | 2177 | intel_dp->want_panel_vdd = false; |
| 2199 | 2178 | |
| @@ -2205,8 +2184,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) · 5 unmodified lines | ||
| 2205 | 2184 | |
| 2206 | 2185 | static void edp_panel_on(struct intel_dp *intel_dp) |
| 2207 | 2186 | { |
| 2208 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2209 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2187 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2210 | 2188 | u32 pp; |
| 2211 | 2189 | i915_reg_t pp_ctrl_reg; |
| 2212 | 2190 | |
| @@ -2216,11 +2194,11 @@ static void edp_panel_on(struct intel_dp *intel_dp) · 3 unmodified lines | ||
| 2216 | 2194 | return; |
| 2217 | 2195 | |
| 2218 | 2196 | DRM_DEBUG_KMS("Turn eDP port %c panel power on\n", |
| 2219 | − port_name(dp_to_dig_port(intel_dp)->port)); | |
| 2197 | + port_name(dp_to_dig_port(intel_dp)->base.port)); | |
| 2220 | 2198 | |
| 2221 | 2199 | if (WARN(edp_have_panel_power(intel_dp), |
| 2222 | 2200 | "eDP port %c panel power already on\n", |
| 2223 | − port_name(dp_to_dig_port(intel_dp)->port))) | |
| 2201 | + port_name(dp_to_dig_port(intel_dp)->base.port))) | |
| 2224 | 2202 | return; |
| 2225 | 2203 | |
| 2226 | 2204 | wait_panel_power_cycle(intel_dp); |
| @@ -2264,8 +2242,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp) · 37 unmodified lines | ||
| 2264 | 2242 | |
| 2265 | 2243 | static void edp_panel_off(struct intel_dp *intel_dp) |
| 2266 | 2244 | { |
| 2267 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2268 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2245 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2269 | 2246 | u32 pp; |
| 2270 | 2247 | i915_reg_t pp_ctrl_reg; |
| 2271 | 2248 | |
| @@ -2275,10 +2252,10 @@ static void edp_panel_off(struct intel_dp *intel_dp) · 3 unmodified lines | ||
| 2275 | 2252 | return; |
| 2276 | 2253 | |
| 2277 | 2254 | DRM_DEBUG_KMS("Turn eDP port %c panel power off\n", |
| 2278 | − port_name(dp_to_dig_port(intel_dp)->port)); | |
| 2255 | + port_name(dp_to_dig_port(intel_dp)->base.port)); | |
| 2279 | 2256 | |
| 2280 | 2257 | WARN(!intel_dp->want_panel_vdd, "Need eDP port %c VDD to turn off panel\n", |
| 2281 | − port_name(dp_to_dig_port(intel_dp)->port)); | |
| 2258 | + port_name(dp_to_dig_port(intel_dp)->base.port)); | |
| 2282 | 2259 | |
| 2283 | 2260 | pp = ironlake_get_pp_control(intel_dp); |
| 2284 | 2261 | /* We need to switch off panel power _and_ force vdd, for otherwise some |
| @@ -2313,9 +2290,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) · 28 unmodified lines | ||
| 2313 | 2290 | /* Enable backlight in the panel power control. */ |
| 2314 | 2291 | static void _intel_edp_backlight_on(struct intel_dp *intel_dp) |
| 2315 | 2292 | { |
| 2316 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 2317 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 2318 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2293 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2319 | 2294 | u32 pp; |
| 2320 | 2295 | i915_reg_t pp_ctrl_reg; |
| 2321 | 2296 | |
| @@ -2358,8 +2333,7 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, · 36 unmodified lines | ||
| 2358 | 2333 | /* Disable backlight in the panel power control. */ |
| 2359 | 2334 | static void _intel_edp_backlight_off(struct intel_dp *intel_dp) |
| 2360 | 2335 | { |
| 2361 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2362 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2336 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2363 | 2337 | u32 pp; |
| 2364 | 2338 | i915_reg_t pp_ctrl_reg; |
| 2365 | 2339 | |
| @@ -2430,7 +2404,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state) · 64 unmodified lines | ||
| 2430 | 2404 | |
| 2431 | 2405 | I915_STATE_WARN(cur_state != state, |
| 2432 | 2406 | "DP port %c state assertion failure (expected %s, current %s)\n", |
| 2433 | − port_name(dig_port->port), | |
| 2407 | + port_name(dig_port->base.port), | |
| 2434 | 2408 | onoff(state), onoff(cur_state)); |
| 2435 | 2409 | } |
| 2436 | 2410 | #define assert_dp_port_disabled(d) assert_dp_port((d), false) |
| @@ -2486,10 +2460,10 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp, · 49 unmodified lines | ||
| 2486 | 2460 | udelay(200); |
| 2487 | 2461 | } |
| 2488 | 2462 | |
| 2489 | −static void ironlake_edp_pll_off(struct intel_dp *intel_dp) | |
| 2463 | +static void ironlake_edp_pll_off(struct intel_dp *intel_dp, | |
| 2464 | + const struct intel_crtc_state *old_crtc_state) | |
| 2490 | 2465 | { |
| 2491 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 2492 | − struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); | |
| 2466 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 2493 | 2467 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 2494 | 2468 | |
| 2495 | 2469 | assert_pipe_disabled(dev_priv, crtc->pipe); |
| @@ -2505,6 +2479,21 @@ static void ironlake_edp_pll_off(struct intel_dp *intel_dp) · 9 unmodified lines | ||
| 2505 | 2479 | udelay(200); |
| 2506 | 2480 | } |
| 2507 | 2481 | |
| 2482 | +static bool downstream_hpd_needs_d0(struct intel_dp *intel_dp) | |
| 2483 | +{ | |
| 2484 | + /* | |
| 2485 | + * DPCD 1.2+ should support BRANCH_DEVICE_CTRL, and thus | |
| 2486 | + * be capable of signalling downstream hpd with a long pulse. | |
| 2487 | + * Whether or not that means D3 is safe to use is not clear, | |
| 2488 | + * but let's assume so until proven otherwise. | |
| 2489 | + * | |
| 2490 | + * FIXME should really check all downstream ports... | |
| 2491 | + */ | |
| 2492 | + return intel_dp->dpcd[DP_DPCD_REV] == 0x11 && | |
| 2493 | + intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT && | |
| 2494 | + intel_dp->downstream_ports[0] & DP_DS_PORT_HPD; | |
| 2495 | +} | |
| 2496 | + | |
| 2508 | 2497 | /* If the sink supports it, try to set the power state appropriately */ |
| 2509 | 2498 | void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) |
| 2510 | 2499 | { |
| @@ -2515,6 +2504,9 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) · 4 unmodified lines | ||
| 2515 | 2504 | return; |
| 2516 | 2505 | |
| 2517 | 2506 | if (mode != DRM_MODE_DPMS_ON) { |
| 2507 | + if (downstream_hpd_needs_d0(intel_dp)) | |
| 2508 | + return; | |
| 2509 | + | |
| 2518 | 2510 | ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, |
| 2519 | 2511 | DP_SET_POWER_D3); |
| 2520 | 2512 | } else { |
| @@ -2544,10 +2536,9 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) · 23 unmodified lines | ||
| 2544 | 2536 | static bool intel_dp_get_hw_state(struct intel_encoder *encoder, |
| 2545 | 2537 | enum pipe *pipe) |
| 2546 | 2538 | { |
| 2539 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 2547 | 2540 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2548 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 2549 | − struct drm_device *dev = encoder->base.dev; | |
| 2550 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2541 | + enum port port = encoder->port; | |
| 2551 | 2542 | u32 tmp; |
| 2552 | 2543 | bool ret; |
| 2553 | 2544 | |
| @@ -2596,12 +2587,16 @@ out: · 42 unmodified lines | ||
| 2596 | 2587 | static void intel_dp_get_config(struct intel_encoder *encoder, |
| 2597 | 2588 | struct intel_crtc_state *pipe_config) |
| 2598 | 2589 | { |
| 2590 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 2599 | 2591 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2600 | 2592 | u32 tmp, flags = 0; |
| 2601 | − struct drm_device *dev = encoder->base.dev; | |
| 2602 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2603 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 2604 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 2593 | + enum port port = encoder->port; | |
| 2594 | + struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 2595 | + | |
| 2596 | + if (encoder->type == INTEL_OUTPUT_EDP) | |
| 2597 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP); | |
| 2598 | + else | |
| 2599 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_DP); | |
| 2605 | 2600 | |
| 2606 | 2601 | tmp = I915_READ(intel_dp->output_reg); |
| 2607 | 2602 | |
| @@ -2680,7 +2675,8 @@ static void intel_disable_dp(struct intel_encoder *encoder, · 72 unmodified lines | ||
| 2680 | 2675 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2681 | 2676 | |
| 2682 | 2677 | if (old_crtc_state->has_audio) |
| 2683 | − intel_audio_codec_disable(encoder); | |
| 2678 | + intel_audio_codec_disable(encoder, | |
| 2679 | + old_crtc_state, old_conn_state); | |
| 2684 | 2680 | |
| 2685 | 2681 | /* Make sure the panel is off before trying to change the mode. But also |
| 2686 | 2682 | * ensure that we have vdd while we switch off the panel. */ |
| @@ -2694,12 +2690,10 @@ static void g4x_disable_dp(struct intel_encoder *encoder, · 7 unmodified lines | ||
| 2694 | 2690 | const struct intel_crtc_state *old_crtc_state, |
| 2695 | 2691 | const struct drm_connector_state *old_conn_state) |
| 2696 | 2692 | { |
| 2697 | − struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | |
| 2698 | − | |
| 2699 | 2693 | intel_disable_dp(encoder, old_crtc_state, old_conn_state); |
| 2700 | 2694 | |
| 2701 | 2695 | /* disable the port before the pipe on g4x */ |
| 2702 | − intel_dp_link_down(intel_dp); | |
| 2696 | + intel_dp_link_down(encoder, old_crtc_state); | |
| 2703 | 2697 | } |
| 2704 | 2698 | |
| 2705 | 2699 | static void ilk_disable_dp(struct intel_encoder *encoder, |
| @@ -2725,38 +2719,34 @@ static void ilk_post_disable_dp(struct intel_encoder *encoder, · 19 unmodified lines | ||
| 2725 | 2719 | const struct drm_connector_state *old_conn_state) |
| 2726 | 2720 | { |
| 2727 | 2721 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2728 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 2722 | + enum port port = encoder->port; | |
| 2729 | 2723 | |
| 2730 | − intel_dp_link_down(intel_dp); | |
| 2724 | + intel_dp_link_down(encoder, old_crtc_state); | |
| 2731 | 2725 | |
| 2732 | 2726 | /* Only ilk+ has port A */ |
| 2733 | 2727 | if (port == PORT_A) |
| 2734 | − ironlake_edp_pll_off(intel_dp); | |
| 2728 | + ironlake_edp_pll_off(intel_dp, old_crtc_state); | |
| 2735 | 2729 | } |
| 2736 | 2730 | |
| 2737 | 2731 | static void vlv_post_disable_dp(struct intel_encoder *encoder, |
| 2738 | 2732 | const struct intel_crtc_state *old_crtc_state, |
| 2739 | 2733 | const struct drm_connector_state *old_conn_state) |
| 2740 | 2734 | { |
| 2741 | − struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | |
| 2742 | − | |
| 2743 | − intel_dp_link_down(intel_dp); | |
| 2735 | + intel_dp_link_down(encoder, old_crtc_state); | |
| 2744 | 2736 | } |
| 2745 | 2737 | |
| 2746 | 2738 | static void chv_post_disable_dp(struct intel_encoder *encoder, |
| 2747 | 2739 | const struct intel_crtc_state *old_crtc_state, |
| 2748 | 2740 | const struct drm_connector_state *old_conn_state) |
| 2749 | 2741 | { |
| 2750 | − struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | |
| 2751 | − struct drm_device *dev = encoder->base.dev; | |
| 2752 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2742 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 2753 | 2743 | |
| 2754 | − intel_dp_link_down(intel_dp); | |
| 2744 | + intel_dp_link_down(encoder, old_crtc_state); | |
| 2755 | 2745 | |
| 2756 | 2746 | mutex_lock(&dev_priv->sb_lock); |
| 2757 | 2747 | |
| 2758 | 2748 | /* Assert data lane reset */ |
| 2759 | − chv_data_lane_soft_reset(encoder, true); | |
| 2749 | + chv_data_lane_soft_reset(encoder, old_crtc_state, true); | |
| 2760 | 2750 | |
| 2761 | 2751 | mutex_unlock(&dev_priv->sb_lock); |
| 2762 | 2752 | } |
| @@ -2766,10 +2756,9 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, · 3 unmodified lines | ||
| 2766 | 2756 | uint32_t *DP, |
| 2767 | 2757 | uint8_t dp_train_pat) |
| 2768 | 2758 | { |
| 2759 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2769 | 2760 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 2770 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 2771 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2772 | − enum port port = intel_dig_port->port; | |
| 2761 | + enum port port = intel_dig_port->base.port; | |
| 2773 | 2762 | |
| 2774 | 2763 | if (dp_train_pat & DP_TRAINING_PATTERN_MASK) |
| 2775 | 2764 | DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", |
| @@ -2852,8 +2841,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, · 76 unmodified lines | ||
| 2852 | 2841 | static void intel_dp_enable_port(struct intel_dp *intel_dp, |
| 2853 | 2842 | const struct intel_crtc_state *old_crtc_state) |
| 2854 | 2843 | { |
| 2855 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 2856 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2844 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 2857 | 2845 | |
| 2858 | 2846 | /* enable with pattern 1 (as per spec) */ |
| 2859 | 2847 | |
| @@ -2877,10 +2865,9 @@ static void intel_enable_dp(struct intel_encoder *encoder, · 17 unmodified lines | ||
| 2877 | 2865 | const struct intel_crtc_state *pipe_config, |
| 2878 | 2866 | const struct drm_connector_state *conn_state) |
| 2879 | 2867 | { |
| 2868 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 2880 | 2869 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2881 | − struct drm_device *dev = encoder->base.dev; | |
| 2882 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2883 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 2870 | + struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 2884 | 2871 | uint32_t dp_reg = I915_READ(intel_dp->output_reg); |
| 2885 | 2872 | enum pipe pipe = crtc->pipe; |
| 2886 | 2873 | |
| @@ -2890,7 +2877,7 @@ static void intel_enable_dp(struct intel_encoder *encoder, · 3 unmodified lines | ||
| 2890 | 2877 | pps_lock(intel_dp); |
| 2891 | 2878 | |
| 2892 | 2879 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 2893 | − vlv_init_panel_power_sequencer(intel_dp); | |
| 2880 | + vlv_init_panel_power_sequencer(encoder, pipe_config); | |
| 2894 | 2881 | |
| 2895 | 2882 | intel_dp_enable_port(intel_dp, pipe_config); |
| 2896 | 2883 | |
| @@ -2944,7 +2931,7 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder, · 47 unmodified lines | ||
| 2944 | 2931 | const struct drm_connector_state *conn_state) |
| 2945 | 2932 | { |
| 2946 | 2933 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2947 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 2934 | + enum port port = encoder->port; | |
| 2948 | 2935 | |
| 2949 | 2936 | intel_dp_prepare(encoder, pipe_config); |
| 2950 | 2937 | |
| @@ -2977,22 +2964,21 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) · 26 unmodified lines | ||
| 2977 | 2964 | * from a port. |
| 2978 | 2965 | */ |
| 2979 | 2966 | DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n", |
| 2980 | − pipe_name(pipe), port_name(intel_dig_port->port)); | |
| 2967 | + pipe_name(pipe), port_name(intel_dig_port->base.port)); | |
| 2981 | 2968 | I915_WRITE(pp_on_reg, 0); |
| 2982 | 2969 | POSTING_READ(pp_on_reg); |
| 2983 | 2970 | |
| 2984 | 2971 | intel_dp->pps_pipe = INVALID_PIPE; |
| 2985 | 2972 | } |
| 2986 | 2973 | |
| 2987 | −static void vlv_steal_power_sequencer(struct drm_device *dev, | |
| 2974 | +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, | |
| 2988 | 2975 | enum pipe pipe) |
| 2989 | 2976 | { |
| 2990 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 2991 | 2977 | struct intel_encoder *encoder; |
| 2992 | 2978 | |
| 2993 | 2979 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 2994 | 2980 | |
| 2995 | − for_each_intel_encoder(dev, encoder) { | |
| 2981 | + for_each_intel_encoder(&dev_priv->drm, encoder) { | |
| 2996 | 2982 | struct intel_dp *intel_dp; |
| 2997 | 2983 | enum port port; |
| 2998 | 2984 | |
| @@ -3001,7 +2987,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, · 2 unmodified lines | ||
| 3001 | 2987 | continue; |
| 3002 | 2988 | |
| 3003 | 2989 | intel_dp = enc_to_intel_dp(&encoder->base); |
| 3004 | − port = dp_to_dig_port(intel_dp)->port; | |
| 2990 | + port = dp_to_dig_port(intel_dp)->base.port; | |
| 3005 | 2991 | |
| 3006 | 2992 | WARN(intel_dp->active_pipe == pipe, |
| 3007 | 2993 | "stealing pipe %c power sequencer from active (e)DP port %c\n", |
| @@ -3018,13 +3004,12 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, · 10 unmodified lines | ||
| 3018 | 3004 | } |
| 3019 | 3005 | } |
| 3020 | 3006 | |
| 3021 | −static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) | |
| 3007 | +static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder, | |
| 3008 | + const struct intel_crtc_state *crtc_state) | |
| 3022 | 3009 | { |
| 3023 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 3024 | − struct intel_encoder *encoder = &intel_dig_port->base; | |
| 3025 | − struct drm_device *dev = encoder->base.dev; | |
| 3026 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 3027 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 3010 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 3011 | + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | |
| 3012 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 3028 | 3013 | |
| 3029 | 3014 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 3030 | 3015 | |
| @@ -3044,7 +3029,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) · 13 unmodified lines | ||
| 3044 | 3029 | * We may be stealing the power |
| 3045 | 3030 | * sequencer from another port. |
| 3046 | 3031 | */ |
| 3047 | − vlv_steal_power_sequencer(dev, crtc->pipe); | |
| 3032 | + vlv_steal_power_sequencer(dev_priv, crtc->pipe); | |
| 3048 | 3033 | |
| 3049 | 3034 | intel_dp->active_pipe = crtc->pipe; |
| 3050 | 3035 | |
| @@ -3055,18 +3040,18 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) · 4 unmodified lines | ||
| 3055 | 3040 | intel_dp->pps_pipe = crtc->pipe; |
| 3056 | 3041 | |
| 3057 | 3042 | DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n", |
| 3058 | − pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port)); | |
| 3043 | + pipe_name(intel_dp->pps_pipe), port_name(encoder->port)); | |
| 3059 | 3044 | |
| 3060 | 3045 | /* init power sequencer on this pipe and port */ |
| 3061 | − intel_dp_init_panel_power_sequencer(dev, intel_dp); | |
| 3062 | − intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true); | |
| 3046 | + intel_dp_init_panel_power_sequencer(intel_dp); | |
| 3047 | + intel_dp_init_panel_power_sequencer_registers(intel_dp, true); | |
| 3063 | 3048 | } |
| 3064 | 3049 | |
| 3065 | 3050 | static void vlv_pre_enable_dp(struct intel_encoder *encoder, |
| 3066 | 3051 | const struct intel_crtc_state *pipe_config, |
| 3067 | 3052 | const struct drm_connector_state *conn_state) |
| 3068 | 3053 | { |
| 3069 | − vlv_phy_pre_encoder_enable(encoder); | |
| 3054 | + vlv_phy_pre_encoder_enable(encoder, pipe_config); | |
| 3070 | 3055 | |
| 3071 | 3056 | intel_enable_dp(encoder, pipe_config, conn_state); |
| 3072 | 3057 | } |
| @@ -3077,14 +3062,14 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder, · 4 unmodified lines | ||
| 3077 | 3062 | { |
| 3078 | 3063 | intel_dp_prepare(encoder, pipe_config); |
| 3079 | 3064 | |
| 3080 | − vlv_phy_pre_pll_enable(encoder); | |
| 3065 | + vlv_phy_pre_pll_enable(encoder, pipe_config); | |
| 3081 | 3066 | } |
| 3082 | 3067 | |
| 3083 | 3068 | static void chv_pre_enable_dp(struct intel_encoder *encoder, |
| 3084 | 3069 | const struct intel_crtc_state *pipe_config, |
| 3085 | 3070 | const struct drm_connector_state *conn_state) |
| 3086 | 3071 | { |
| 3087 | − chv_phy_pre_encoder_enable(encoder); | |
| 3072 | + chv_phy_pre_encoder_enable(encoder, pipe_config); | |
| 3088 | 3073 | |
| 3089 | 3074 | intel_enable_dp(encoder, pipe_config, conn_state); |
| 3090 | 3075 | |
| @@ -3098,14 +3083,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder, · 7 unmodified lines | ||
| 3098 | 3083 | { |
| 3099 | 3084 | intel_dp_prepare(encoder, pipe_config); |
| 3100 | 3085 | |
| 3101 | − chv_phy_pre_pll_enable(encoder); | |
| 3086 | + chv_phy_pre_pll_enable(encoder, pipe_config); | |
| 3102 | 3087 | } |
| 3103 | 3088 | |
| 3104 | 3089 | static void chv_dp_post_pll_disable(struct intel_encoder *encoder, |
| 3105 | − const struct intel_crtc_state *pipe_config, | |
| 3106 | − const struct drm_connector_state *conn_state) | |
| 3090 | + const struct intel_crtc_state *old_crtc_state, | |
| 3091 | + const struct drm_connector_state *old_conn_state) | |
| 3107 | 3092 | { |
| 3108 | − chv_phy_post_pll_disable(encoder); | |
| 3093 | + chv_phy_post_pll_disable(encoder, old_crtc_state); | |
| 3109 | 3094 | } |
| 3110 | 3095 | |
| 3111 | 3096 | /* |
| @@ -3153,7 +3138,7 @@ uint8_t · 41 unmodified lines | ||
| 3153 | 3138 | intel_dp_voltage_max(struct intel_dp *intel_dp) |
| 3154 | 3139 | { |
| 3155 | 3140 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
| 3156 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 3141 | + enum port port = dp_to_dig_port(intel_dp)->base.port; | |
| 3157 | 3142 | |
| 3158 | 3143 | if (INTEL_GEN(dev_priv) >= 9) { |
| 3159 | 3144 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; |
| @@ -3172,7 +3157,7 @@ uint8_t · 12 unmodified lines | ||
| 3172 | 3157 | intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) |
| 3173 | 3158 | { |
| 3174 | 3159 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
| 3175 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 3160 | + enum port port = dp_to_dig_port(intel_dp)->base.port; | |
| 3176 | 3161 | |
| 3177 | 3162 | if (INTEL_GEN(dev_priv) >= 9) { |
| 3178 | 3163 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| @@ -3505,10 +3490,9 @@ gen7_edp_signal_levels(uint8_t train_set) · 326 unmodified lines | ||
| 3505 | 3490 | void |
| 3506 | 3491 | intel_dp_set_signal_levels(struct intel_dp *intel_dp) |
| 3507 | 3492 | { |
| 3493 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 3508 | 3494 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 3509 | − enum port port = intel_dig_port->port; | |
| 3510 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 3511 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 3495 | + enum port port = intel_dig_port->base.port; | |
| 3512 | 3496 | uint32_t signal_levels, mask = 0; |
| 3513 | 3497 | uint8_t train_set = intel_dp->train_set[0]; |
| 3514 | 3498 | |
| @@ -3563,10 +3547,9 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, · 48 unmodified lines | ||
| 3563 | 3547 | |
| 3564 | 3548 | void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) |
| 3565 | 3549 | { |
| 3550 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 3566 | 3551 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 3567 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 3568 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 3569 | − enum port port = intel_dig_port->port; | |
| 3552 | + enum port port = intel_dig_port->base.port; | |
| 3570 | 3553 | uint32_t val; |
| 3571 | 3554 | |
| 3572 | 3555 | if (!HAS_DDI(dev_priv)) |
| @@ -3595,13 +3578,13 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) · 22 unmodified lines | ||
| 3595 | 3578 | } |
| 3596 | 3579 | |
| 3597 | 3580 | static void |
| 3598 | −intel_dp_link_down(struct intel_dp *intel_dp) | |
| 3581 | +intel_dp_link_down(struct intel_encoder *encoder, | |
| 3582 | + const struct intel_crtc_state *old_crtc_state) | |
| 3599 | 3583 | { |
| 3600 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 3601 | − struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); | |
| 3602 | − enum port port = intel_dig_port->port; | |
| 3603 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 3604 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 3584 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 3585 | + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | |
| 3586 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 3587 | + enum port port = encoder->port; | |
| 3605 | 3588 | uint32_t DP = intel_dp->DP; |
| 3606 | 3589 | |
| 3607 | 3590 | if (WARN_ON(HAS_DDI(dev_priv))) |
| @@ -3747,11 +3730,11 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) · 139 unmodified lines | ||
| 3747 | 3730 | if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, |
| 3748 | 3731 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == |
| 3749 | 3732 | sizeof(intel_dp->edp_dpcd)) |
| 3750 | − DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd), | |
| 3733 | + DRM_DEBUG_KMS("eDP DPCD: %*ph\n", (int) sizeof(intel_dp->edp_dpcd), | |
| 3751 | 3734 | intel_dp->edp_dpcd); |
| 3752 | 3735 | |
| 3753 | − /* Intermediate frequency support */ | |
| 3754 | − if (intel_dp->edp_dpcd[0] >= 0x03) { /* eDp v1.4 or higher */ | |
| 3736 | + /* Read the eDP 1.4+ supported link rates. */ | |
| 3737 | + if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { | |
| 3755 | 3738 | __le16 sink_rates[DP_MAX_SUPPORTED_RATES]; |
| 3756 | 3739 | int i; |
| 3757 | 3740 | |
| @@ -3775,6 +3758,10 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) · 17 unmodified lines | ||
| 3775 | 3758 | intel_dp->num_sink_rates = i; |
| 3776 | 3759 | } |
| 3777 | 3760 | |
| 3761 | + /* | |
| 3762 | + * Use DP_LINK_RATE_SET if DP_SUPPORTED_LINK_RATES are available, | |
| 3763 | + * default to DP_MAX_LINK_RATE and DP_LINK_BW_SET otherwise. | |
| 3764 | + */ | |
| 3778 | 3765 | if (intel_dp->num_sink_rates) |
| 3779 | 3766 | intel_dp->use_rate_select = true; |
| 3780 | 3767 | else |
| @@ -3874,11 +3861,12 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) · 93 unmodified lines | ||
| 3874 | 3861 | intel_dp->is_mst); |
| 3875 | 3862 | } |
| 3876 | 3863 | |
| 3877 | −static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) | |
| 3864 | +static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp, | |
| 3865 | + struct intel_crtc_state *crtc_state, bool disable_wa) | |
| 3878 | 3866 | { |
| 3879 | 3867 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 3880 | 3868 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 3881 | − struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); | |
| 3869 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 3882 | 3870 | u8 buf; |
| 3883 | 3871 | int ret = 0; |
| 3884 | 3872 | int count = 0; |
| @@ -3914,15 +3902,17 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) · 29 unmodified lines | ||
| 3914 | 3902 | } |
| 3915 | 3903 | |
| 3916 | 3904 | out: |
| 3917 | − hsw_enable_ips(intel_crtc); | |
| 3905 | + if (disable_wa) | |
| 3906 | + hsw_enable_ips(crtc_state); | |
| 3918 | 3907 | return ret; |
| 3919 | 3908 | } |
| 3920 | 3909 | |
| 3921 | −static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) | |
| 3910 | +static int intel_dp_sink_crc_start(struct intel_dp *intel_dp, | |
| 3911 | + struct intel_crtc_state *crtc_state) | |
| 3922 | 3912 | { |
| 3923 | 3913 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 3924 | 3914 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 3925 | − struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); | |
| 3915 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 3926 | 3916 | u8 buf; |
| 3927 | 3917 | int ret; |
| 3928 | 3918 | |
| @@ -3936,16 +3926,16 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) · 7 unmodified lines | ||
| 3936 | 3926 | return -EIO; |
| 3937 | 3927 | |
| 3938 | 3928 | if (buf & DP_TEST_SINK_START) { |
| 3939 | − ret = intel_dp_sink_crc_stop(intel_dp); | |
| 3929 | + ret = intel_dp_sink_crc_stop(intel_dp, crtc_state, false); | |
| 3940 | 3930 | if (ret) |
| 3941 | 3931 | return ret; |
| 3942 | 3932 | } |
| 3943 | 3933 | |
| 3944 | − hsw_disable_ips(intel_crtc); | |
| 3934 | + hsw_disable_ips(crtc_state); | |
| 3945 | 3935 | |
| 3946 | 3936 | if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, |
| 3947 | 3937 | buf | DP_TEST_SINK_START) < 0) { |
| 3948 | − hsw_enable_ips(intel_crtc); | |
| 3938 | + hsw_enable_ips(crtc_state); | |
| 3949 | 3939 | return -EIO; |
| 3950 | 3940 | } |
| 3951 | 3941 | |
| @@ -3953,16 +3943,16 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) · 1 unmodified line | ||
| 3953 | 3943 | return 0; |
| 3954 | 3944 | } |
| 3955 | 3945 | |
| 3956 | −int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) | |
| 3946 | +int intel_dp_sink_crc(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, u8 *crc) | |
| 3957 | 3947 | { |
| 3958 | 3948 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 3959 | 3949 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 3960 | − struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); | |
| 3950 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 3961 | 3951 | u8 buf; |
| 3962 | 3952 | int count, ret; |
| 3963 | 3953 | int attempts = 6; |
| 3964 | 3954 | |
| 3965 | − ret = intel_dp_sink_crc_start(intel_dp); | |
| 3955 | + ret = intel_dp_sink_crc_start(intel_dp, crtc_state); | |
| 3966 | 3956 | if (ret) |
| 3967 | 3957 | return ret; |
| 3968 | 3958 | |
| @@ -3990,7 +3980,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) · 21 unmodified lines | ||
| 3990 | 3980 | } |
| 3991 | 3981 | |
| 3992 | 3982 | stop: |
| 3993 | − intel_dp_sink_crc_stop(intel_dp); | |
| 3983 | + intel_dp_sink_crc_stop(intel_dp, crtc_state, true); | |
| 3994 | 3984 | return ret; |
| 3995 | 3985 | } |
| 3996 | 3986 | |
| @@ -4285,11 +4275,11 @@ intel_dp_retrain_link(struct intel_dp *intel_dp) · 288 unmodified lines | ||
| 4285 | 4275 | static void |
| 4286 | 4276 | intel_dp_check_link_status(struct intel_dp *intel_dp) |
| 4287 | 4277 | { |
| 4278 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 4288 | 4279 | struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; |
| 4289 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 4290 | 4280 | u8 link_status[DP_LINK_STATUS_SIZE]; |
| 4291 | 4281 | |
| 4292 | − WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); | |
| 4282 | + WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); | |
| 4293 | 4283 | |
| 4294 | 4284 | if (!intel_dp_get_link_status(intel_dp, link_status)) { |
| 4295 | 4285 | DRM_ERROR("Failed to get link status\n"); |
| @@ -4335,8 +4325,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) · 39 unmodified lines | ||
| 4335 | 4325 | static bool |
| 4336 | 4326 | intel_dp_short_pulse(struct intel_dp *intel_dp) |
| 4337 | 4327 | { |
| 4338 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 4339 | − struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; | |
| 4328 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 4340 | 4329 | u8 sink_irq_vector = 0; |
| 4341 | 4330 | u8 old_sink_count = intel_dp->sink_count; |
| 4342 | 4331 | bool ret; |
| @@ -4375,13 +4364,13 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) · 32 unmodified lines | ||
| 4375 | 4364 | DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); |
| 4376 | 4365 | } |
| 4377 | 4366 | |
| 4378 | − drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | |
| 4367 | + drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL); | |
| 4379 | 4368 | intel_dp_check_link_status(intel_dp); |
| 4380 | − drm_modeset_unlock(&dev->mode_config.connection_mutex); | |
| 4369 | + drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); | |
| 4381 | 4370 | if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { |
| 4382 | 4371 | DRM_DEBUG_KMS("Link Training Compliance Test requested\n"); |
| 4383 | 4372 | /* Send a Hotplug Uevent to userspace to start modeset */ |
| 4384 | − drm_kms_helper_hotplug_event(intel_encoder->base.dev); | |
| 4373 | + drm_kms_helper_hotplug_event(&dev_priv->drm); | |
| 4385 | 4374 | } |
| 4386 | 4375 | |
| 4387 | 4376 | return true; |
| @@ -4445,8 +4434,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) · 57 unmodified lines | ||
| 4445 | 4434 | static enum drm_connector_status |
| 4446 | 4435 | edp_detect(struct intel_dp *intel_dp) |
| 4447 | 4436 | { |
| 4448 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 4449 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 4437 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 4450 | 4438 | enum drm_connector_status status; |
| 4451 | 4439 | |
| 4452 | 4440 | status = intel_panel_detect(dev_priv); |
| @@ -4461,7 +4449,7 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, · 8 unmodified lines | ||
| 4461 | 4449 | { |
| 4462 | 4450 | u32 bit; |
| 4463 | 4451 | |
| 4464 | − switch (port->port) { | |
| 4452 | + switch (port->base.port) { | |
| 4465 | 4453 | case PORT_B: |
| 4466 | 4454 | bit = SDE_PORTB_HOTPLUG; |
| 4467 | 4455 | break; |
| @@ -4472,7 +4460,7 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 4472 | 4460 | bit = SDE_PORTD_HOTPLUG; |
| 4473 | 4461 | break; |
| 4474 | 4462 | default: |
| 4475 | − MISSING_CASE(port->port); | |
| 4463 | + MISSING_CASE(port->base.port); | |
| 4476 | 4464 | return false; |
| 4477 | 4465 | } |
| 4478 | 4466 | |
| @@ -4484,7 +4472,7 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 4484 | 4472 | { |
| 4485 | 4473 | u32 bit; |
| 4486 | 4474 | |
| 4487 | − switch (port->port) { | |
| 4475 | + switch (port->base.port) { | |
| 4488 | 4476 | case PORT_B: |
| 4489 | 4477 | bit = SDE_PORTB_HOTPLUG_CPT; |
| 4490 | 4478 | break; |
| @@ -4495,7 +4483,7 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 4495 | 4483 | bit = SDE_PORTD_HOTPLUG_CPT; |
| 4496 | 4484 | break; |
| 4497 | 4485 | default: |
| 4498 | − MISSING_CASE(port->port); | |
| 4486 | + MISSING_CASE(port->base.port); | |
| 4499 | 4487 | return false; |
| 4500 | 4488 | } |
| 4501 | 4489 | |
| @@ -4507,7 +4495,7 @@ static bool spt_digital_port_connected(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 4507 | 4495 | { |
| 4508 | 4496 | u32 bit; |
| 4509 | 4497 | |
| 4510 | − switch (port->port) { | |
| 4498 | + switch (port->base.port) { | |
| 4511 | 4499 | case PORT_A: |
| 4512 | 4500 | bit = SDE_PORTA_HOTPLUG_SPT; |
| 4513 | 4501 | break; |
| @@ -4526,7 +4514,7 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, · 12 unmodified lines | ||
| 4526 | 4514 | { |
| 4527 | 4515 | u32 bit; |
| 4528 | 4516 | |
| 4529 | − switch (port->port) { | |
| 4517 | + switch (port->base.port) { | |
| 4530 | 4518 | case PORT_B: |
| 4531 | 4519 | bit = PORTB_HOTPLUG_LIVE_STATUS_G4X; |
| 4532 | 4520 | break; |
| @@ -4537,7 +4525,7 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 4537 | 4525 | bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; |
| 4538 | 4526 | break; |
| 4539 | 4527 | default: |
| 4540 | − MISSING_CASE(port->port); | |
| 4528 | + MISSING_CASE(port->base.port); | |
| 4541 | 4529 | return false; |
| 4542 | 4530 | } |
| 4543 | 4531 | |
| @@ -4549,7 +4537,7 @@ static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 4549 | 4537 | { |
| 4550 | 4538 | u32 bit; |
| 4551 | 4539 | |
| 4552 | − switch (port->port) { | |
| 4540 | + switch (port->base.port) { | |
| 4553 | 4541 | case PORT_B: |
| 4554 | 4542 | bit = PORTB_HOTPLUG_LIVE_STATUS_GM45; |
| 4555 | 4543 | break; |
| @@ -4560,7 +4548,7 @@ static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 4560 | 4548 | bit = PORTD_HOTPLUG_LIVE_STATUS_GM45; |
| 4561 | 4549 | break; |
| 4562 | 4550 | default: |
| 4563 | − MISSING_CASE(port->port); | |
| 4551 | + MISSING_CASE(port->base.port); | |
| 4564 | 4552 | return false; |
| 4565 | 4553 | } |
| 4566 | 4554 | |
| @@ -4570,7 +4558,7 @@ static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, · 3 unmodified lines | ||
| 4570 | 4558 | static bool ilk_digital_port_connected(struct drm_i915_private *dev_priv, |
| 4571 | 4559 | struct intel_digital_port *port) |
| 4572 | 4560 | { |
| 4573 | − if (port->port == PORT_A) | |
| 4561 | + if (port->base.port == PORT_A) | |
| 4574 | 4562 | return I915_READ(DEISR) & DE_DP_A_HOTPLUG; |
| 4575 | 4563 | else |
| 4576 | 4564 | return ibx_digital_port_connected(dev_priv, port); |
| @@ -4579,7 +4567,7 @@ static bool ilk_digital_port_connected(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 4579 | 4567 | static bool snb_digital_port_connected(struct drm_i915_private *dev_priv, |
| 4580 | 4568 | struct intel_digital_port *port) |
| 4581 | 4569 | { |
| 4582 | − if (port->port == PORT_A) | |
| 4570 | + if (port->base.port == PORT_A) | |
| 4583 | 4571 | return I915_READ(DEISR) & DE_DP_A_HOTPLUG; |
| 4584 | 4572 | else |
| 4585 | 4573 | return cpt_digital_port_connected(dev_priv, port); |
| @@ -4588,7 +4576,7 @@ static bool snb_digital_port_connected(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 4588 | 4576 | static bool ivb_digital_port_connected(struct drm_i915_private *dev_priv, |
| 4589 | 4577 | struct intel_digital_port *port) |
| 4590 | 4578 | { |
| 4591 | − if (port->port == PORT_A) | |
| 4579 | + if (port->base.port == PORT_A) | |
| 4592 | 4580 | return I915_READ(DEISR) & DE_DP_A_HOTPLUG_IVB; |
| 4593 | 4581 | else |
| 4594 | 4582 | return cpt_digital_port_connected(dev_priv, port); |
| @@ -4597,7 +4585,7 @@ static bool ivb_digital_port_connected(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 4597 | 4585 | static bool bdw_digital_port_connected(struct drm_i915_private *dev_priv, |
| 4598 | 4586 | struct intel_digital_port *port) |
| 4599 | 4587 | { |
| 4600 | − if (port->port == PORT_A) | |
| 4588 | + if (port->base.port == PORT_A) | |
| 4601 | 4589 | return I915_READ(GEN8_DE_PORT_ISR) & GEN8_PORT_DP_A_HOTPLUG; |
| 4602 | 4590 | else |
| 4603 | 4591 | return cpt_digital_port_connected(dev_priv, port); |
| @@ -4702,24 +4690,21 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) · 98 unmodified lines | ||
| 4702 | 4690 | } |
| 4703 | 4691 | |
| 4704 | 4692 | static int |
| 4705 | −intel_dp_long_pulse(struct intel_connector *intel_connector) | |
| 4693 | +intel_dp_long_pulse(struct intel_connector *connector) | |
| 4706 | 4694 | { |
| 4707 | − struct drm_connector *connector = &intel_connector->base; | |
| 4708 | − struct intel_dp *intel_dp = intel_attached_dp(connector); | |
| 4709 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 4710 | − struct intel_encoder *intel_encoder = &intel_dig_port->base; | |
| 4711 | − struct drm_device *dev = connector->dev; | |
| 4695 | + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | |
| 4696 | + struct intel_dp *intel_dp = intel_attached_dp(&connector->base); | |
| 4712 | 4697 | enum drm_connector_status status; |
| 4713 | 4698 | u8 sink_irq_vector = 0; |
| 4714 | 4699 | |
| 4715 | − WARN_ON(!drm_modeset_is_locked(&connector->dev->mode_config.connection_mutex)); | |
| 4700 | + WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); | |
| 4716 | 4701 | |
| 4717 | − intel_display_power_get(to_i915(dev), intel_dp->aux_power_domain); | |
| 4702 | + intel_display_power_get(dev_priv, intel_dp->aux_power_domain); | |
| 4718 | 4703 | |
| 4719 | 4704 | /* Can't disconnect eDP, but you can close the lid... */ |
| 4720 | 4705 | if (intel_dp_is_edp(intel_dp)) |
| 4721 | 4706 | status = edp_detect(intel_dp); |
| 4722 | − else if (intel_digital_port_connected(to_i915(dev), | |
| 4707 | + else if (intel_digital_port_connected(dev_priv, | |
| 4723 | 4708 | dp_to_dig_port(intel_dp))) |
| 4724 | 4709 | status = intel_dp_detect_dpcd(intel_dp); |
| 4725 | 4710 | else |
| @@ -4740,9 +4725,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) · 14 unmodified lines | ||
| 4740 | 4725 | goto out; |
| 4741 | 4726 | } |
| 4742 | 4727 | |
| 4743 | − if (intel_encoder->type != INTEL_OUTPUT_EDP) | |
| 4744 | − intel_encoder->type = INTEL_OUTPUT_DP; | |
| 4745 | − | |
| 4746 | 4728 | if (intel_dp->reset_link_params) { |
| 4747 | 4729 | /* Initial max link lane count */ |
| 4748 | 4730 | intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); |
| @@ -4793,7 +4775,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) · 44 unmodified lines | ||
| 4793 | 4775 | intel_dp->aux.i2c_defer_count = 0; |
| 4794 | 4776 | |
| 4795 | 4777 | intel_dp_set_edid(intel_dp); |
| 4796 | − if (intel_dp_is_edp(intel_dp) || intel_connector->detect_edid) | |
| 4778 | + if (intel_dp_is_edp(intel_dp) || connector->detect_edid) | |
| 4797 | 4779 | status = connector_status_connected; |
| 4798 | 4780 | intel_dp->detect_done = true; |
| 4799 | 4781 | |
| @@ -4816,7 +4798,7 @@ out: · 16 unmodified lines | ||
| 4816 | 4798 | if (status != connector_status_connected && !intel_dp->is_mst) |
| 4817 | 4799 | intel_dp_unset_edid(intel_dp); |
| 4818 | 4800 | |
| 4819 | − intel_display_power_put(to_i915(dev), intel_dp->aux_power_domain); | |
| 4801 | + intel_display_power_put(dev_priv, intel_dp->aux_power_domain); | |
| 4820 | 4802 | return status; |
| 4821 | 4803 | } |
| 4822 | 4804 | |
| @@ -4859,9 +4841,6 @@ intel_dp_force(struct drm_connector *connector) · 36 unmodified lines | ||
| 4859 | 4841 | intel_dp_set_edid(intel_dp); |
| 4860 | 4842 | |
| 4861 | 4843 | intel_display_power_put(dev_priv, intel_dp->aux_power_domain); |
| 4862 | − | |
| 4863 | − if (intel_encoder->type != INTEL_OUTPUT_EDP) | |
| 4864 | − intel_encoder->type = INTEL_OUTPUT_DP; | |
| 4865 | 4844 | } |
| 4866 | 4845 | |
| 4867 | 4846 | static int intel_dp_get_modes(struct drm_connector *connector) |
| @@ -4986,9 +4965,7 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) · 118 unmodified lines | ||
| 4986 | 4965 | |
| 4987 | 4966 | static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) |
| 4988 | 4967 | { |
| 4989 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 4990 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 4991 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 4968 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 4992 | 4969 | |
| 4993 | 4970 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 4994 | 4971 | |
| @@ -5041,7 +5018,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder) · 46 unmodified lines | ||
| 5041 | 5018 | |
| 5042 | 5019 | if (intel_dp_is_edp(intel_dp)) { |
| 5043 | 5020 | /* Reinit the power sequencer, in case BIOS did something with it. */ |
| 5044 | − intel_dp_pps_init(encoder->dev, intel_dp); | |
| 5021 | + intel_dp_pps_init(intel_dp); | |
| 5045 | 5022 | intel_edp_panel_vdd_sanitize(intel_dp); |
| 5046 | 5023 | } |
| 5047 | 5024 | |
| @@ -5076,14 +5053,9 @@ enum irqreturn · 28 unmodified lines | ||
| 5076 | 5053 | intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) |
| 5077 | 5054 | { |
| 5078 | 5055 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
| 5079 | − struct drm_device *dev = intel_dig_port->base.base.dev; | |
| 5080 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5056 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5081 | 5057 | enum irqreturn ret = IRQ_NONE; |
| 5082 | 5058 | |
| 5083 | − if (intel_dig_port->base.type != INTEL_OUTPUT_EDP && | |
| 5084 | − intel_dig_port->base.type != INTEL_OUTPUT_HDMI) | |
| 5085 | − intel_dig_port->base.type = INTEL_OUTPUT_DP; | |
| 5086 | − | |
| 5087 | 5059 | if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) { |
| 5088 | 5060 | /* |
| 5089 | 5061 | * vdd off can generate a long pulse on eDP which |
| @@ -5092,12 +5064,12 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) · 2 unmodified lines | ||
| 5092 | 5064 | * "vdd off -> long hpd -> vdd on -> detect -> vdd off -> ..." |
| 5093 | 5065 | */ |
| 5094 | 5066 | DRM_DEBUG_KMS("ignoring long hpd on eDP port %c\n", |
| 5095 | − port_name(intel_dig_port->port)); | |
| 5067 | + port_name(intel_dig_port->base.port)); | |
| 5096 | 5068 | return IRQ_HANDLED; |
| 5097 | 5069 | } |
| 5098 | 5070 | |
| 5099 | 5071 | DRM_DEBUG_KMS("got hpd irq on port %c - %s\n", |
| 5100 | − port_name(intel_dig_port->port), | |
| 5072 | + port_name(intel_dig_port->base.port), | |
| 5101 | 5073 | long_hpd ? "long" : "short"); |
| 5102 | 5074 | |
| 5103 | 5075 | if (long_hpd) { |
| @@ -5185,13 +5157,13 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp) · 81 unmodified lines | ||
| 5185 | 5157 | } |
| 5186 | 5158 | |
| 5187 | 5159 | static void |
| 5188 | −intel_pps_readout_hw_state(struct drm_i915_private *dev_priv, | |
| 5189 | − struct intel_dp *intel_dp, struct edp_power_seq *seq) | |
| 5160 | +intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq) | |
| 5190 | 5161 | { |
| 5162 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5191 | 5163 | u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0; |
| 5192 | 5164 | struct pps_registers regs; |
| 5193 | 5165 | |
| 5194 | − intel_pps_get_registers(dev_priv, intel_dp, ®s); | |
| 5166 | + intel_pps_get_registers(intel_dp, ®s); | |
| 5195 | 5167 | |
| 5196 | 5168 | /* Workaround: Need to write PP_CONTROL with the unlock key as |
| 5197 | 5169 | * the very first thing. */ |
| @@ -5235,13 +5207,12 @@ intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq) · 37 unmodified lines | ||
| 5235 | 5207 | } |
| 5236 | 5208 | |
| 5237 | 5209 | static void |
| 5238 | −intel_pps_verify_state(struct drm_i915_private *dev_priv, | |
| 5239 | − struct intel_dp *intel_dp) | |
| 5210 | +intel_pps_verify_state(struct intel_dp *intel_dp) | |
| 5240 | 5211 | { |
| 5241 | 5212 | struct edp_power_seq hw; |
| 5242 | 5213 | struct edp_power_seq *sw = &intel_dp->pps_delays; |
| 5243 | 5214 | |
| 5244 | − intel_pps_readout_hw_state(dev_priv, intel_dp, &hw); | |
| 5215 | + intel_pps_readout_hw_state(intel_dp, &hw); | |
| 5245 | 5216 | |
| 5246 | 5217 | if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 || |
| 5247 | 5218 | hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) { |
| @@ -5252,10 +5223,9 @@ intel_pps_verify_state(struct drm_i915_private *dev_priv, · 4 unmodified lines | ||
| 5252 | 5223 | } |
| 5253 | 5224 | |
| 5254 | 5225 | static void |
| 5255 | −intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |
| 5256 | − struct intel_dp *intel_dp) | |
| 5226 | +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp) | |
| 5257 | 5227 | { |
| 5258 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5228 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5259 | 5229 | struct edp_power_seq cur, vbt, spec, |
| 5260 | 5230 | *final = &intel_dp->pps_delays; |
| 5261 | 5231 | |
| @@ -5265,7 +5235,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, · 3 unmodified lines | ||
| 5265 | 5235 | if (final->t11_t12 != 0) |
| 5266 | 5236 | return; |
| 5267 | 5237 | |
| 5268 | − intel_pps_readout_hw_state(dev_priv, intel_dp, &cur); | |
| 5238 | + intel_pps_readout_hw_state(intel_dp, &cur); | |
| 5269 | 5239 | |
| 5270 | 5240 | intel_pps_dump_state("cur", &cur); |
| 5271 | 5241 | |
| @@ -5339,20 +5309,19 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, · 67 unmodified lines | ||
| 5339 | 5309 | } |
| 5340 | 5310 | |
| 5341 | 5311 | static void |
| 5342 | −intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |
| 5343 | − struct intel_dp *intel_dp, | |
| 5312 | +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp, | |
| 5344 | 5313 | bool force_disable_vdd) |
| 5345 | 5314 | { |
| 5346 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5315 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5347 | 5316 | u32 pp_on, pp_off, pp_div, port_sel = 0; |
| 5348 | 5317 | int div = dev_priv->rawclk_freq / 1000; |
| 5349 | 5318 | struct pps_registers regs; |
| 5350 | − enum port port = dp_to_dig_port(intel_dp)->port; | |
| 5319 | + enum port port = dp_to_dig_port(intel_dp)->base.port; | |
| 5351 | 5320 | const struct edp_power_seq *seq = &intel_dp->pps_delays; |
| 5352 | 5321 | |
| 5353 | 5322 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 5354 | 5323 | |
| 5355 | − intel_pps_get_registers(dev_priv, intel_dp, ®s); | |
| 5324 | + intel_pps_get_registers(intel_dp, ®s); | |
| 5356 | 5325 | |
| 5357 | 5326 | /* |
| 5358 | 5327 | * On some VLV machines the BIOS can leave the VDD |
| @@ -5424,16 +5393,15 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, · 65 unmodified lines | ||
| 5424 | 5393 | I915_READ(regs.pp_div)); |
| 5425 | 5394 | } |
| 5426 | 5395 | |
| 5427 | −static void intel_dp_pps_init(struct drm_device *dev, | |
| 5428 | − struct intel_dp *intel_dp) | |
| 5396 | +static void intel_dp_pps_init(struct intel_dp *intel_dp) | |
| 5429 | 5397 | { |
| 5430 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5398 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5431 | 5399 | |
| 5432 | 5400 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 5433 | 5401 | vlv_initial_power_sequencer_setup(intel_dp); |
| 5434 | 5402 | } else { |
| 5435 | − intel_dp_init_panel_power_sequencer(dev, intel_dp); | |
| 5436 | − intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false); | |
| 5403 | + intel_dp_init_panel_power_sequencer(intel_dp); | |
| 5404 | + intel_dp_init_panel_power_sequencer_registers(intel_dp, false); | |
| 5437 | 5405 | } |
| 5438 | 5406 | } |
| 5439 | 5407 | |
| @@ -5472,7 +5440,6 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, · 32 unmodified lines | ||
| 5472 | 5440 | |
| 5473 | 5441 | dig_port = dp_to_dig_port(intel_dp); |
| 5474 | 5442 | encoder = &dig_port->base; |
| 5475 | − intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 5476 | 5443 | |
| 5477 | 5444 | if (!intel_crtc) { |
| 5478 | 5445 | DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n"); |
| @@ -5545,8 +5512,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, · 66 unmodified lines | ||
| 5545 | 5512 | void intel_edp_drrs_enable(struct intel_dp *intel_dp, |
| 5546 | 5513 | const struct intel_crtc_state *crtc_state) |
| 5547 | 5514 | { |
| 5548 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 5549 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5515 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5550 | 5516 | |
| 5551 | 5517 | if (!crtc_state->has_drrs) { |
| 5552 | 5518 | DRM_DEBUG_KMS("Panel doesn't support DRRS\n"); |
| @@ -5581,8 +5547,7 @@ unlock: · 28 unmodified lines | ||
| 5581 | 5547 | void intel_edp_drrs_disable(struct intel_dp *intel_dp, |
| 5582 | 5548 | const struct intel_crtc_state *old_crtc_state) |
| 5583 | 5549 | { |
| 5584 | − struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 5585 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5550 | + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | |
| 5586 | 5551 | |
| 5587 | 5552 | if (!old_crtc_state->has_drrs) |
| 5588 | 5553 | return; |
| @@ -5765,7 +5730,7 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, · 176 unmodified lines | ||
| 5765 | 5730 | |
| 5766 | 5731 | /** |
| 5767 | 5732 | * intel_dp_drrs_init - Init basic DRRS work and mutex. |
| 5768 | − * @intel_connector: eDP connector | |
| 5733 | + * @connector: eDP connector | |
| 5769 | 5734 | * @fixed_mode: preferred mode of panel |
| 5770 | 5735 | * |
| 5771 | 5736 | * This function is called only once at driver load to initialize basic |
| @@ -5777,12 +5742,10 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 5777 | 5742 | * from VBT setting). |
| 5778 | 5743 | */ |
| 5779 | 5744 | static struct drm_display_mode * |
| 5780 | −intel_dp_drrs_init(struct intel_connector *intel_connector, | |
| 5781 | − struct drm_display_mode *fixed_mode) | |
| 5745 | +intel_dp_drrs_init(struct intel_connector *connector, | |
| 5746 | + struct drm_display_mode *fixed_mode) | |
| 5782 | 5747 | { |
| 5783 | − struct drm_connector *connector = &intel_connector->base; | |
| 5784 | − struct drm_device *dev = connector->dev; | |
| 5785 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 5748 | + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | |
| 5786 | 5749 | struct drm_display_mode *downclock_mode = NULL; |
| 5787 | 5750 | |
| 5788 | 5751 | INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work); |
| @@ -5798,8 +5761,8 @@ intel_dp_drrs_init(struct intel_connector *intel_connector, · 9 unmodified lines | ||
| 5798 | 5761 | return NULL; |
| 5799 | 5762 | } |
| 5800 | 5763 | |
| 5801 | − downclock_mode = intel_find_panel_downclock | |
| 5802 | − (dev_priv, fixed_mode, connector); | |
| 5764 | + downclock_mode = intel_find_panel_downclock(dev_priv, fixed_mode, | |
| 5765 | + &connector->base); | |
| 5803 | 5766 | |
| 5804 | 5767 | if (!downclock_mode) { |
| 5805 | 5768 | DRM_DEBUG_KMS("Downclock mode is not found. DRRS not supported\n"); |
| @@ -5816,11 +5779,9 @@ intel_dp_drrs_init(struct intel_connector *intel_connector, · 10 unmodified lines | ||
| 5816 | 5779 | static bool intel_edp_init_connector(struct intel_dp *intel_dp, |
| 5817 | 5780 | struct intel_connector *intel_connector) |
| 5818 | 5781 | { |
| 5819 | − struct drm_connector *connector = &intel_connector->base; | |
| 5820 | − struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | |
| 5821 | − struct intel_encoder *intel_encoder = &intel_dig_port->base; | |
| 5822 | − struct drm_device *dev = intel_encoder->base.dev; | |
| 5782 | + struct drm_device *dev = intel_dp_to_dev(intel_dp); | |
| 5823 | 5783 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 5784 | + struct drm_connector *connector = &intel_connector->base; | |
| 5824 | 5785 | struct drm_display_mode *fixed_mode = NULL; |
| 5825 | 5786 | struct drm_display_mode *alt_fixed_mode = NULL; |
| 5826 | 5787 | struct drm_display_mode *downclock_mode = NULL; |
| @@ -5838,7 +5799,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, · 11 unmodified lines | ||
| 5838 | 5799 | * eDP and LVDS bail out early in this case to prevent interfering |
| 5839 | 5800 | * with an already powered-on LVDS power sequencer. |
| 5840 | 5801 | */ |
| 5841 | − if (intel_get_lvds_encoder(dev)) { | |
| 5802 | + if (intel_get_lvds_encoder(&dev_priv->drm)) { | |
| 5842 | 5803 | WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))); |
| 5843 | 5804 | DRM_INFO("LVDS was detected, not registering eDP\n"); |
| 5844 | 5805 | |
| @@ -5848,7 +5809,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, · 3 unmodified lines | ||
| 5848 | 5809 | pps_lock(intel_dp); |
| 5849 | 5810 | |
| 5850 | 5811 | intel_dp_init_panel_power_timestamps(intel_dp); |
| 5851 | − intel_dp_pps_init(dev, intel_dp); | |
| 5812 | + intel_dp_pps_init(intel_dp); | |
| 5852 | 5813 | intel_edp_panel_vdd_sanitize(intel_dp); |
| 5853 | 5814 | |
| 5854 | 5815 | pps_unlock(intel_dp); |
| @@ -5948,9 +5909,9 @@ intel_dp_init_connector_port_info(struct intel_digital_port *intel_dig_port) · 93 unmodified lines | ||
| 5948 | 5909 | struct intel_encoder *encoder = &intel_dig_port->base; |
| 5949 | 5910 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
| 5950 | 5911 | |
| 5951 | − encoder->hpd_pin = intel_hpd_pin(intel_dig_port->port); | |
| 5912 | + encoder->hpd_pin = intel_hpd_pin(encoder->port); | |
| 5952 | 5913 | |
| 5953 | − switch (intel_dig_port->port) { | |
| 5914 | + switch (encoder->port) { | |
| 5954 | 5915 | case PORT_A: |
| 5955 | 5916 | intel_dp->aux_power_domain = POWER_DOMAIN_AUX_A; |
| 5956 | 5917 | break; |
| @@ -5968,7 +5929,7 @@ intel_dp_init_connector_port_info(struct intel_digital_port *intel_dig_port) · 11 unmodified lines | ||
| 5968 | 5929 | intel_dp->aux_power_domain = POWER_DOMAIN_AUX_D; |
| 5969 | 5930 | break; |
| 5970 | 5931 | default: |
| 5971 | − MISSING_CASE(intel_dig_port->port); | |
| 5932 | + MISSING_CASE(encoder->port); | |
| 5972 | 5933 | } |
| 5973 | 5934 | } |
| 5974 | 5935 | |
| @@ -6004,7 +5965,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, · 29 unmodified lines | ||
| 6004 | 5965 | struct intel_encoder *intel_encoder = &intel_dig_port->base; |
| 6005 | 5966 | struct drm_device *dev = intel_encoder->base.dev; |
| 6006 | 5967 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 6007 | − enum port port = intel_dig_port->port; | |
| 5968 | + enum port port = intel_encoder->port; | |
| 6008 | 5969 | int type; |
| 6009 | 5970 | |
| 6010 | 5971 | /* Initialize the work for modeset in case of link train failure */ |
| @@ -6174,7 +6135,6 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, · 163 unmodified lines | ||
| 6174 | 6135 | intel_encoder->disable = g4x_disable_dp; |
| 6175 | 6136 | } |
| 6176 | 6137 | |
| 6177 | − intel_dig_port->port = port; | |
| 6178 | 6138 | intel_dig_port->dp.output_reg = output_reg; |
| 6179 | 6139 | intel_dig_port->max_lanes = 4; |
| 6180 | 6140 | |
| @@ -34,6 +34,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, · 33 unmodified lines | ||
| 34 | 34 | struct intel_crtc_state *pipe_config, |
| 35 | 35 | struct drm_connector_state *conn_state) |
| 36 | 36 | { |
| 37 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 37 | 38 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); |
| 38 | 39 | struct intel_digital_port *intel_dig_port = intel_mst->primary; |
| 39 | 40 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
| @@ -87,6 +88,12 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, · 47 unmodified lines | ||
| 87 | 88 | |
| 88 | 89 | pipe_config->dp_m_n.tu = slots; |
| 89 | 90 | |
| 91 | + if (IS_GEN9_LP(dev_priv)) | |
| 92 | + pipe_config->lane_lat_optim_mask = | |
| 93 | + bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); | |
| 94 | + | |
| 95 | + intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); | |
| 96 | + | |
| 90 | 97 | return true; |
| 91 | 98 | } |
| 92 | 99 | |
| @@ -142,7 +149,8 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, · 49 unmodified lines | ||
| 142 | 149 | DRM_ERROR("failed to update payload %d\n", ret); |
| 143 | 150 | } |
| 144 | 151 | if (old_crtc_state->has_audio) |
| 145 | − intel_audio_codec_disable(encoder); | |
| 152 | + intel_audio_codec_disable(encoder, | |
| 153 | + old_crtc_state, old_conn_state); | |
| 146 | 154 | } |
| 147 | 155 | |
| 148 | 156 | static void intel_mst_post_disable_dp(struct intel_encoder *encoder, |
| @@ -172,13 +180,27 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, · 23 unmodified lines | ||
| 172 | 180 | intel_dp->active_mst_links--; |
| 173 | 181 | |
| 174 | 182 | intel_mst->connector = NULL; |
| 175 | − if (intel_dp->active_mst_links == 0) { | |
| 183 | + if (intel_dp->active_mst_links == 0) | |
| 176 | 184 | intel_dig_port->base.post_disable(&intel_dig_port->base, |
| 177 | − NULL, NULL); | |
| 178 | − } | |
| 185 | + old_crtc_state, NULL); | |
| 186 | + | |
| 179 | 187 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); |
| 180 | 188 | } |
| 181 | 189 | |
| 190 | +static void intel_mst_pre_pll_enable_dp(struct intel_encoder *encoder, | |
| 191 | + const struct intel_crtc_state *pipe_config, | |
| 192 | + const struct drm_connector_state *conn_state) | |
| 193 | +{ | |
| 194 | + struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); | |
| 195 | + struct intel_digital_port *intel_dig_port = intel_mst->primary; | |
| 196 | + struct intel_dp *intel_dp = &intel_dig_port->dp; | |
| 197 | + | |
| 198 | + if (intel_dp->active_mst_links == 0 && | |
| 199 | + intel_dig_port->base.pre_pll_enable) | |
| 200 | + intel_dig_port->base.pre_pll_enable(&intel_dig_port->base, | |
| 201 | + pipe_config, NULL); | |
| 202 | +} | |
| 203 | + | |
| 182 | 204 | static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, |
| 183 | 205 | const struct intel_crtc_state *pipe_config, |
| 184 | 206 | const struct drm_connector_state *conn_state) |
| @@ -187,7 +209,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, · 2 unmodified lines | ||
| 187 | 209 | struct intel_digital_port *intel_dig_port = intel_mst->primary; |
| 188 | 210 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
| 189 | 211 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 190 | − enum port port = intel_dig_port->port; | |
| 212 | + enum port port = intel_dig_port->base.port; | |
| 191 | 213 | struct intel_connector *connector = |
| 192 | 214 | to_intel_connector(conn_state->connector); |
| 193 | 215 | int ret; |
| @@ -231,7 +253,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, · 37 unmodified lines | ||
| 231 | 253 | struct intel_digital_port *intel_dig_port = intel_mst->primary; |
| 232 | 254 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
| 233 | 255 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 234 | − enum port port = intel_dig_port->port; | |
| 256 | + enum port port = intel_dig_port->base.port; | |
| 235 | 257 | int ret; |
| 236 | 258 | |
| 237 | 259 | DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); |
| @@ -265,48 +287,8 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, · 27 unmodified lines | ||
| 265 | 287 | { |
| 266 | 288 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); |
| 267 | 289 | struct intel_digital_port *intel_dig_port = intel_mst->primary; |
| 268 | − struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 269 | − struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 270 | − enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; | |
| 271 | − u32 temp, flags = 0; | |
| 272 | − | |
| 273 | − pipe_config->has_audio = | |
| 274 | − intel_ddi_is_audio_enabled(dev_priv, crtc); | |
| 275 | − | |
| 276 | − temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); | |
| 277 | − if (temp & TRANS_DDI_PHSYNC) | |
| 278 | − flags |= DRM_MODE_FLAG_PHSYNC; | |
| 279 | − else | |
| 280 | − flags |= DRM_MODE_FLAG_NHSYNC; | |
| 281 | − if (temp & TRANS_DDI_PVSYNC) | |
| 282 | − flags |= DRM_MODE_FLAG_PVSYNC; | |
| 283 | − else | |
| 284 | − flags |= DRM_MODE_FLAG_NVSYNC; | |
| 285 | − | |
| 286 | − switch (temp & TRANS_DDI_BPC_MASK) { | |
| 287 | − case TRANS_DDI_BPC_6: | |
| 288 | − pipe_config->pipe_bpp = 18; | |
| 289 | − break; | |
| 290 | − case TRANS_DDI_BPC_8: | |
| 291 | − pipe_config->pipe_bpp = 24; | |
| 292 | − break; | |
| 293 | − case TRANS_DDI_BPC_10: | |
| 294 | − pipe_config->pipe_bpp = 30; | |
| 295 | − break; | |
| 296 | − case TRANS_DDI_BPC_12: | |
| 297 | − pipe_config->pipe_bpp = 36; | |
| 298 | − break; | |
| 299 | − default: | |
| 300 | − break; | |
| 301 | − } | |
| 302 | − pipe_config->base.adjusted_mode.flags |= flags; | |
| 303 | − | |
| 304 | − pipe_config->lane_count = | |
| 305 | − ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; | |
| 306 | − | |
| 307 | − intel_dp_get_m_n(crtc, pipe_config); | |
| 308 | 290 | |
| 309 | − intel_ddi_clock_get(&intel_dig_port->base, pipe_config); | |
| 291 | + intel_ddi_get_config(&intel_dig_port->base, pipe_config); | |
| 310 | 292 | } |
| 311 | 293 | |
| 312 | 294 | static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) |
| @@ -570,13 +552,14 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum · 257 unmodified lines | ||
| 570 | 552 | |
| 571 | 553 | intel_encoder->type = INTEL_OUTPUT_DP_MST; |
| 572 | 554 | intel_encoder->power_domain = intel_dig_port->base.power_domain; |
| 573 | − intel_encoder->port = intel_dig_port->port; | |
| 555 | + intel_encoder->port = intel_dig_port->base.port; | |
| 574 | 556 | intel_encoder->crtc_mask = 0x7; |
| 575 | 557 | intel_encoder->cloneable = 0; |
| 576 | 558 | |
| 577 | 559 | intel_encoder->compute_config = intel_dp_mst_compute_config; |
| 578 | 560 | intel_encoder->disable = intel_mst_disable_dp; |
| 579 | 561 | intel_encoder->post_disable = intel_mst_post_disable_dp; |
| 562 | + intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; | |
| 580 | 563 | intel_encoder->pre_enable = intel_mst_pre_enable_dp; |
| 581 | 564 | intel_encoder->enable = intel_mst_enable_dp; |
| 582 | 565 | intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state; |
| @@ -466,21 +466,21 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) · 465 unmodified lines | ||
| 466 | 466 | |
| 467 | 467 | lockdep_assert_held(&dev_priv->power_domains.lock); |
| 468 | 468 | |
| 469 | − if (rcomp_phy != -1) { | |
| 469 | + was_enabled = true; | |
| 470 | + if (rcomp_phy != -1) | |
| 470 | 471 | was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy); |
| 471 | 472 | |
| 472 | − /* | |
| 473 | − * We need to copy the GRC calibration value from rcomp_phy, | |
| 474 | − * so make sure it's powered up. | |
| 475 | − */ | |
| 476 | − if (!was_enabled) | |
| 477 | − _bxt_ddi_phy_init(dev_priv, rcomp_phy); | |
| 478 | − } | |
| 473 | + /* | |
| 474 | + * We need to copy the GRC calibration value from rcomp_phy, | |
| 475 | + * so make sure it's powered up. | |
| 476 | + */ | |
| 477 | + if (!was_enabled) | |
| 478 | + _bxt_ddi_phy_init(dev_priv, rcomp_phy); | |
| 479 | 479 | |
| 480 | 480 | _bxt_ddi_phy_init(dev_priv, phy); |
| 481 | 481 | |
| 482 | − if (rcomp_phy != -1 && !was_enabled) | |
| 483 | − bxt_ddi_phy_uninit(dev_priv, phy_info->rcomp_phy); | |
| 482 | + if (!was_enabled) | |
| 483 | + bxt_ddi_phy_uninit(dev_priv, rcomp_phy); | |
| 484 | 484 | } |
| 485 | 485 | |
| 486 | 486 | static bool __printf(6, 7) |
| @@ -567,8 +567,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, · 80 unmodified lines | ||
| 567 | 567 | } |
| 568 | 568 | |
| 569 | 569 | uint8_t |
| 570 | −bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, | |
| 571 | − uint8_t lane_count) | |
| 570 | +bxt_ddi_phy_calc_lane_lat_optim_mask(uint8_t lane_count) | |
| 572 | 571 | { |
| 573 | 572 | switch (lane_count) { |
| 574 | 573 | case 1: |
| @@ -587,9 +586,8 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, · 12 unmodified lines | ||
| 587 | 586 | void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, |
| 588 | 587 | uint8_t lane_lat_optim_mask) |
| 589 | 588 | { |
| 590 | − struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | |
| 591 | − struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); | |
| 592 | − enum port port = dport->port; | |
| 589 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 590 | + enum port port = encoder->port; | |
| 593 | 591 | enum dpio_phy phy; |
| 594 | 592 | enum dpio_channel ch; |
| 595 | 593 | int lane; |
| @@ -614,9 +612,8 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, · 18 unmodified lines | ||
| 614 | 612 | uint8_t |
| 615 | 613 | bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) |
| 616 | 614 | { |
| 617 | − struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | |
| 618 | − struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); | |
| 619 | − enum port port = dport->port; | |
| 615 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 616 | + enum port port = encoder->port; | |
| 620 | 617 | enum dpio_phy phy; |
| 621 | 618 | enum dpio_channel ch; |
| 622 | 619 | int lane; |
| @@ -642,7 +639,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, · 19 unmodified lines | ||
| 642 | 639 | { |
| 643 | 640 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 644 | 641 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 645 | − struct intel_crtc *intel_crtc = to_intel_crtc(dport->base.base.crtc); | |
| 642 | + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 646 | 643 | enum dpio_channel ch = vlv_dport_to_channel(dport); |
| 647 | 644 | enum pipe pipe = intel_crtc->pipe; |
| 648 | 645 | u32 val; |
| @@ -734,11 +731,12 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, · 85 unmodified lines | ||
| 734 | 731 | } |
| 735 | 732 | |
| 736 | 733 | void chv_data_lane_soft_reset(struct intel_encoder *encoder, |
| 734 | + const struct intel_crtc_state *crtc_state, | |
| 737 | 735 | bool reset) |
| 738 | 736 | { |
| 739 | 737 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 740 | 738 | enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); |
| 741 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 739 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 742 | 740 | enum pipe pipe = crtc->pipe; |
| 743 | 741 | uint32_t val; |
| 744 | 742 | |
| @@ -777,17 +775,16 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, · 32 unmodified lines | ||
| 777 | 775 | } |
| 778 | 776 | } |
| 779 | 777 | |
| 780 | −void chv_phy_pre_pll_enable(struct intel_encoder *encoder) | |
| 778 | +void chv_phy_pre_pll_enable(struct intel_encoder *encoder, | |
| 779 | + const struct intel_crtc_state *crtc_state) | |
| 781 | 780 | { |
| 782 | 781 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 783 | − struct drm_device *dev = encoder->base.dev; | |
| 784 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 785 | − struct intel_crtc *intel_crtc = | |
| 786 | − to_intel_crtc(encoder->base.crtc); | |
| 782 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 783 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 787 | 784 | enum dpio_channel ch = vlv_dport_to_channel(dport); |
| 788 | − enum pipe pipe = intel_crtc->pipe; | |
| 785 | + enum pipe pipe = crtc->pipe; | |
| 789 | 786 | unsigned int lane_mask = |
| 790 | − intel_dp_unused_lane_mask(intel_crtc->config->lane_count); | |
| 787 | + intel_dp_unused_lane_mask(crtc_state->lane_count); | |
| 791 | 788 | u32 val; |
| 792 | 789 | |
| 793 | 790 | /* |
| @@ -803,7 +800,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder) · 9 unmodified lines | ||
| 803 | 800 | mutex_lock(&dev_priv->sb_lock); |
| 804 | 801 | |
| 805 | 802 | /* Assert data lane reset */ |
| 806 | − chv_data_lane_soft_reset(encoder, true); | |
| 803 | + chv_data_lane_soft_reset(encoder, crtc_state, true); | |
| 807 | 804 | |
| 808 | 805 | /* program left/right clock distribution */ |
| 809 | 806 | if (pipe != PIPE_B) { |
| @@ -833,7 +830,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder) · 23 unmodified lines | ||
| 833 | 830 | val |= CHV_PCS_USEDCLKCHANNEL; |
| 834 | 831 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val); |
| 835 | 832 | |
| 836 | − if (intel_crtc->config->lane_count > 2) { | |
| 833 | + if (crtc_state->lane_count > 2) { | |
| 837 | 834 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch)); |
| 838 | 835 | val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; |
| 839 | 836 | if (pipe != PIPE_B) |
| @@ -858,16 +855,15 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder) · 18 unmodified lines | ||
| 858 | 855 | mutex_unlock(&dev_priv->sb_lock); |
| 859 | 856 | } |
| 860 | 857 | |
| 861 | −void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) | |
| 858 | +void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, | |
| 859 | + const struct intel_crtc_state *crtc_state) | |
| 862 | 860 | { |
| 863 | 861 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 864 | 862 | struct intel_digital_port *dport = dp_to_dig_port(intel_dp); |
| 865 | − struct drm_device *dev = encoder->base.dev; | |
| 866 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 867 | − struct intel_crtc *intel_crtc = | |
| 868 | − to_intel_crtc(encoder->base.crtc); | |
| 863 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 864 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 869 | 865 | enum dpio_channel ch = vlv_dport_to_channel(dport); |
| 870 | − int pipe = intel_crtc->pipe; | |
| 866 | + enum pipe pipe = crtc->pipe; | |
| 871 | 867 | int data, i, stagger; |
| 872 | 868 | u32 val; |
| 873 | 869 | |
| @@ -878,16 +874,16 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 4 unmodified lines | ||
| 878 | 874 | val &= ~DPIO_LANEDESKEW_STRAP_OVRD; |
| 879 | 875 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); |
| 880 | 876 | |
| 881 | − if (intel_crtc->config->lane_count > 2) { | |
| 877 | + if (crtc_state->lane_count > 2) { | |
| 882 | 878 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); |
| 883 | 879 | val &= ~DPIO_LANEDESKEW_STRAP_OVRD; |
| 884 | 880 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); |
| 885 | 881 | } |
| 886 | 882 | |
| 887 | 883 | /* Program Tx lane latency optimal setting*/ |
| 888 | − for (i = 0; i < intel_crtc->config->lane_count; i++) { | |
| 884 | + for (i = 0; i < crtc_state->lane_count; i++) { | |
| 889 | 885 | /* Set the upar bit */ |
| 890 | − if (intel_crtc->config->lane_count == 1) | |
| 886 | + if (crtc_state->lane_count == 1) | |
| 891 | 887 | data = 0x0; |
| 892 | 888 | else |
| 893 | 889 | data = (i == 1) ? 0x0 : 0x1; |
| @@ -896,13 +892,13 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 2 unmodified lines | ||
| 896 | 892 | } |
| 897 | 893 | |
| 898 | 894 | /* Data lane stagger programming */ |
| 899 | − if (intel_crtc->config->port_clock > 270000) | |
| 895 | + if (crtc_state->port_clock > 270000) | |
| 900 | 896 | stagger = 0x18; |
| 901 | − else if (intel_crtc->config->port_clock > 135000) | |
| 897 | + else if (crtc_state->port_clock > 135000) | |
| 902 | 898 | stagger = 0xd; |
| 903 | − else if (intel_crtc->config->port_clock > 67500) | |
| 899 | + else if (crtc_state->port_clock > 67500) | |
| 904 | 900 | stagger = 0x7; |
| 905 | − else if (intel_crtc->config->port_clock > 33750) | |
| 901 | + else if (crtc_state->port_clock > 33750) | |
| 906 | 902 | stagger = 0x4; |
| 907 | 903 | else |
| 908 | 904 | stagger = 0x2; |
| @@ -911,7 +907,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 2 unmodified lines | ||
| 911 | 907 | val |= DPIO_TX2_STAGGER_MASK(0x1f); |
| 912 | 908 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); |
| 913 | 909 | |
| 914 | − if (intel_crtc->config->lane_count > 2) { | |
| 910 | + if (crtc_state->lane_count > 2) { | |
| 915 | 911 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); |
| 916 | 912 | val |= DPIO_TX2_STAGGER_MASK(0x1f); |
| 917 | 913 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); |
| @@ -924,7 +920,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 6 unmodified lines | ||
| 924 | 920 | DPIO_TX1_STAGGER_MULT(6) | |
| 925 | 921 | DPIO_TX2_STAGGER_MULT(0)); |
| 926 | 922 | |
| 927 | − if (intel_crtc->config->lane_count > 2) { | |
| 923 | + if (crtc_state->lane_count > 2) { | |
| 928 | 924 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), |
| 929 | 925 | DPIO_LANESTAGGER_STRAP(stagger) | |
| 930 | 926 | DPIO_LANESTAGGER_STRAP_OVRD | |
| @@ -934,7 +930,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 3 unmodified lines | ||
| 934 | 930 | } |
| 935 | 931 | |
| 936 | 932 | /* Deassert data lane reset */ |
| 937 | − chv_data_lane_soft_reset(encoder, false); | |
| 933 | + chv_data_lane_soft_reset(encoder, crtc_state, false); | |
| 938 | 934 | |
| 939 | 935 | mutex_unlock(&dev_priv->sb_lock); |
| 940 | 936 | } |
| @@ -950,10 +946,11 @@ void chv_phy_release_cl2_override(struct intel_encoder *encoder) · 9 unmodified lines | ||
| 950 | 946 | } |
| 951 | 947 | } |
| 952 | 948 | |
| 953 | −void chv_phy_post_pll_disable(struct intel_encoder *encoder) | |
| 949 | +void chv_phy_post_pll_disable(struct intel_encoder *encoder, | |
| 950 | + const struct intel_crtc_state *old_crtc_state) | |
| 954 | 951 | { |
| 955 | 952 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 956 | − enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; | |
| 953 | + enum pipe pipe = to_intel_crtc(old_crtc_state->base.crtc)->pipe; | |
| 957 | 954 | u32 val; |
| 958 | 955 | |
| 959 | 956 | mutex_lock(&dev_priv->sb_lock); |
| @@ -991,7 +988,7 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, · 31 unmodified lines | ||
| 991 | 988 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
| 992 | 989 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 993 | 990 | enum dpio_channel port = vlv_dport_to_channel(dport); |
| 994 | − int pipe = intel_crtc->pipe; | |
| 991 | + enum pipe pipe = intel_crtc->pipe; | |
| 995 | 992 | |
| 996 | 993 | mutex_lock(&dev_priv->sb_lock); |
| 997 | 994 | vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000); |
| @@ -1009,15 +1006,14 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, · 11 unmodified lines | ||
| 1009 | 1006 | mutex_unlock(&dev_priv->sb_lock); |
| 1010 | 1007 | } |
| 1011 | 1008 | |
| 1012 | −void vlv_phy_pre_pll_enable(struct intel_encoder *encoder) | |
| 1009 | +void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, | |
| 1010 | + const struct intel_crtc_state *crtc_state) | |
| 1013 | 1011 | { |
| 1014 | 1012 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 1015 | − struct drm_device *dev = encoder->base.dev; | |
| 1016 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1017 | − struct intel_crtc *intel_crtc = | |
| 1018 | − to_intel_crtc(encoder->base.crtc); | |
| 1013 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1014 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 1019 | 1015 | enum dpio_channel port = vlv_dport_to_channel(dport); |
| 1020 | − int pipe = intel_crtc->pipe; | |
| 1016 | + enum pipe pipe = crtc->pipe; | |
| 1021 | 1017 | |
| 1022 | 1018 | /* Program Tx lane resets to default */ |
| 1023 | 1019 | mutex_lock(&dev_priv->sb_lock); |
| @@ -1037,15 +1033,15 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder) · 13 unmodified lines | ||
| 1037 | 1033 | mutex_unlock(&dev_priv->sb_lock); |
| 1038 | 1034 | } |
| 1039 | 1035 | |
| 1040 | −void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder) | |
| 1036 | +void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, | |
| 1037 | + const struct intel_crtc_state *crtc_state) | |
| 1041 | 1038 | { |
| 1042 | 1039 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 1043 | 1040 | struct intel_digital_port *dport = dp_to_dig_port(intel_dp); |
| 1044 | − struct drm_device *dev = encoder->base.dev; | |
| 1045 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1046 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 1041 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1042 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 1047 | 1043 | enum dpio_channel port = vlv_dport_to_channel(dport); |
| 1048 | − int pipe = intel_crtc->pipe; | |
| 1044 | + enum pipe pipe = crtc->pipe; | |
| 1049 | 1045 | u32 val; |
| 1050 | 1046 | |
| 1051 | 1047 | mutex_lock(&dev_priv->sb_lock); |
| @@ -1067,14 +1063,14 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder) · 15 unmodified lines | ||
| 1067 | 1063 | mutex_unlock(&dev_priv->sb_lock); |
| 1068 | 1064 | } |
| 1069 | 1065 | |
| 1070 | −void vlv_phy_reset_lanes(struct intel_encoder *encoder) | |
| 1066 | +void vlv_phy_reset_lanes(struct intel_encoder *encoder, | |
| 1067 | + const struct intel_crtc_state *old_crtc_state) | |
| 1071 | 1068 | { |
| 1072 | 1069 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 1073 | 1070 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1074 | − struct intel_crtc *intel_crtc = | |
| 1075 | − to_intel_crtc(encoder->base.crtc); | |
| 1071 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 1076 | 1072 | enum dpio_channel port = vlv_dport_to_channel(dport); |
| 1077 | − int pipe = intel_crtc->pipe; | |
| 1073 | + enum pipe pipe = crtc->pipe; | |
| 1078 | 1074 | |
| 1079 | 1075 | mutex_lock(&dev_priv->sb_lock); |
| 1080 | 1076 | vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000); |
| @@ -813,15 +813,11 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 812 unmodified lines | ||
| 813 | 813 | memset(&crtc_state->dpll_hw_state, 0, |
| 814 | 814 | sizeof(crtc_state->dpll_hw_state)); |
| 815 | 815 | |
| 816 | − if (encoder->type == INTEL_OUTPUT_HDMI) { | |
| 816 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { | |
| 817 | 817 | pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state); |
| 818 | − | |
| 819 | − } else if (encoder->type == INTEL_OUTPUT_DP || | |
| 820 | − encoder->type == INTEL_OUTPUT_DP_MST || | |
| 821 | − encoder->type == INTEL_OUTPUT_EDP) { | |
| 818 | + } else if (intel_crtc_has_dp_encoder(crtc_state)) { | |
| 822 | 819 | pll = hsw_ddi_dp_get_dpll(encoder, clock); |
| 823 | − | |
| 824 | − } else if (encoder->type == INTEL_OUTPUT_ANALOG) { | |
| 820 | + } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) { | |
| 825 | 821 | if (WARN_ON(crtc_state->port_clock / 2 != 135000)) |
| 826 | 822 | return NULL; |
| 827 | 823 | |
| @@ -1369,15 +1365,13 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 541 unmodified lines | ||
| 1369 | 1365 | |
| 1370 | 1366 | memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); |
| 1371 | 1367 | |
| 1372 | − if (encoder->type == INTEL_OUTPUT_HDMI) { | |
| 1368 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { | |
| 1373 | 1369 | bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock); |
| 1374 | 1370 | if (!bret) { |
| 1375 | 1371 | DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n"); |
| 1376 | 1372 | return NULL; |
| 1377 | 1373 | } |
| 1378 | − } else if (encoder->type == INTEL_OUTPUT_DP || | |
| 1379 | − encoder->type == INTEL_OUTPUT_DP_MST || | |
| 1380 | − encoder->type == INTEL_OUTPUT_EDP) { | |
| 1374 | + } else if (intel_crtc_has_dp_encoder(crtc_state)) { | |
| 1381 | 1375 | bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state); |
| 1382 | 1376 | if (!bret) { |
| 1383 | 1377 | DRM_DEBUG_KMS("Could not set DP dpll HW state.\n"); |
| @@ -1388,7 +1382,7 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 4 unmodified lines | ||
| 1388 | 1382 | return NULL; |
| 1389 | 1383 | } |
| 1390 | 1384 | |
| 1391 | − if (encoder->type == INTEL_OUTPUT_EDP) | |
| 1385 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) | |
| 1392 | 1386 | pll = intel_find_shared_dpll(crtc, crtc_state, |
| 1393 | 1387 | DPLL_ID_SKL_DPLL0, |
| 1394 | 1388 | DPLL_ID_SKL_DPLL0); |
| @@ -1808,18 +1802,15 @@ bxt_get_dpll(struct intel_crtc *crtc, · 413 unmodified lines | ||
| 1808 | 1802 | { |
| 1809 | 1803 | struct intel_dpll_hw_state dpll_hw_state = { }; |
| 1810 | 1804 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1811 | − struct intel_digital_port *intel_dig_port; | |
| 1812 | 1805 | struct intel_shared_dpll *pll; |
| 1813 | 1806 | int i, clock = crtc_state->port_clock; |
| 1814 | 1807 | |
| 1815 | − if (encoder->type == INTEL_OUTPUT_HDMI && | |
| 1808 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && | |
| 1816 | 1809 | !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock, |
| 1817 | 1810 | &dpll_hw_state)) |
| 1818 | 1811 | return NULL; |
| 1819 | 1812 | |
| 1820 | − if ((encoder->type == INTEL_OUTPUT_DP || | |
| 1821 | − encoder->type == INTEL_OUTPUT_EDP || | |
| 1822 | − encoder->type == INTEL_OUTPUT_DP_MST) && | |
| 1813 | + if (intel_crtc_has_dp_encoder(crtc_state) && | |
| 1823 | 1814 | !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state)) |
| 1824 | 1815 | return NULL; |
| 1825 | 1816 | |
| @@ -1828,15 +1819,8 @@ bxt_get_dpll(struct intel_crtc *crtc, · 2 unmodified lines | ||
| 1828 | 1819 | |
| 1829 | 1820 | crtc_state->dpll_hw_state = dpll_hw_state; |
| 1830 | 1821 | |
| 1831 | − if (encoder->type == INTEL_OUTPUT_DP_MST) { | |
| 1832 | − struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); | |
| 1833 | − | |
| 1834 | − intel_dig_port = intel_mst->primary; | |
| 1835 | − } else | |
| 1836 | − intel_dig_port = enc_to_dig_port(&encoder->base); | |
| 1837 | − | |
| 1838 | 1822 | /* 1:1 mapping between ports and PLLs */ |
| 1839 | − i = (enum intel_dpll_id) intel_dig_port->port; | |
| 1823 | + i = (enum intel_dpll_id) encoder->port; | |
| 1840 | 1824 | pll = intel_get_shared_dpll_by_id(dev_priv, i); |
| 1841 | 1825 | |
| 1842 | 1826 | DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", |
| @@ -2008,8 +1992,8 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, · 165 unmodified lines | ||
| 2008 | 1992 | * requirement, follow the Display Voltage Frequency Switching |
| 2009 | 1993 | * Sequence Before Frequency Change |
| 2010 | 1994 | * |
| 2011 | − * FIXME: (DVFS) is used to adjust the display voltage to match the | |
| 2012 | − * display clock frequencies | |
| 1995 | + * Note: DVFS is actually handled via the cdclk code paths, | |
| 1996 | + * hence we do nothing here. | |
| 2013 | 1997 | */ |
| 2014 | 1998 | |
| 2015 | 1999 | /* 6. Enable DPLL in DPLL_ENABLE. */ |
| @@ -2030,8 +2014,8 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, · 14 unmodified lines | ||
| 2030 | 2014 | * requirement, follow the Display Voltage Frequency Switching |
| 2031 | 2015 | * Sequence After Frequency Change |
| 2032 | 2016 | * |
| 2033 | − * FIXME: (DVFS) is used to adjust the display voltage to match the | |
| 2034 | − * display clock frequencies | |
| 2017 | + * Note: DVFS is actually handled via the cdclk code paths, | |
| 2018 | + * hence we do nothing here. | |
| 2035 | 2019 | */ |
| 2036 | 2020 | |
| 2037 | 2021 | /* |
| @@ -2055,8 +2039,8 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, · 17 unmodified lines | ||
| 2055 | 2039 | * requirement, follow the Display Voltage Frequency Switching |
| 2056 | 2040 | * Sequence Before Frequency Change |
| 2057 | 2041 | * |
| 2058 | − * FIXME: (DVFS) is used to adjust the display voltage to match the | |
| 2059 | − * display clock frequencies | |
| 2042 | + * Note: DVFS is actually handled via the cdclk code paths, | |
| 2043 | + * hence we do nothing here. | |
| 2060 | 2044 | */ |
| 2061 | 2045 | |
| 2062 | 2046 | /* 3. Disable DPLL through DPLL_ENABLE. */ |
| @@ -2077,8 +2061,8 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv, · 14 unmodified lines | ||
| 2077 | 2061 | * requirement, follow the Display Voltage Frequency Switching |
| 2078 | 2062 | * Sequence After Frequency Change |
| 2079 | 2063 | * |
| 2080 | − * FIXME: (DVFS) is used to adjust the display voltage to match the | |
| 2081 | − * display clock frequencies | |
| 2064 | + * Note: DVFS is actually handled via the cdclk code paths, | |
| 2065 | + * hence we do nothing here. | |
| 2082 | 2066 | */ |
| 2083 | 2067 | |
| 2084 | 2068 | /* 6. Disable DPLL power in DPLL_ENABLE. */ |
| @@ -2126,10 +2110,8 @@ out: · 41 unmodified lines | ||
| 2126 | 2110 | return ret; |
| 2127 | 2111 | } |
| 2128 | 2112 | |
| 2129 | −static void cnl_wrpll_get_multipliers(unsigned int bestdiv, | |
| 2130 | − unsigned int *pdiv, | |
| 2131 | − unsigned int *qdiv, | |
| 2132 | − unsigned int *kdiv) | |
| 2113 | +static void cnl_wrpll_get_multipliers(int bestdiv, int *pdiv, | |
| 2114 | + int *qdiv, int *kdiv) | |
| 2133 | 2115 | { |
| 2134 | 2116 | /* even dividers */ |
| 2135 | 2117 | if (bestdiv % 2 == 0) { |
| @@ -2167,10 +2149,12 @@ static void cnl_wrpll_get_multipliers(unsigned int bestdiv, · 31 unmodified lines | ||
| 2167 | 2149 | } |
| 2168 | 2150 | } |
| 2169 | 2151 | |
| 2170 | −static void cnl_wrpll_params_populate(struct skl_wrpll_params *params, uint32_t dco_freq, | |
| 2171 | − uint32_t ref_freq, uint32_t pdiv, uint32_t qdiv, | |
| 2172 | − uint32_t kdiv) | |
| 2152 | +static void cnl_wrpll_params_populate(struct skl_wrpll_params *params, | |
| 2153 | + u32 dco_freq, u32 ref_freq, | |
| 2154 | + int pdiv, int qdiv, int kdiv) | |
| 2173 | 2155 | { |
| 2156 | + u32 dco; | |
| 2157 | + | |
| 2174 | 2158 | switch (kdiv) { |
| 2175 | 2159 | case 1: |
| 2176 | 2160 | params->kdiv = 1; |
| @@ -2202,39 +2186,35 @@ static void cnl_wrpll_params_populate(struct skl_wrpll_params *params, uint32_t · 25 unmodified lines | ||
| 2202 | 2186 | WARN(1, "Incorrect PDiv\n"); |
| 2203 | 2187 | } |
| 2204 | 2188 | |
| 2205 | − if (kdiv != 2) | |
| 2206 | − qdiv = 1; | |
| 2189 | + WARN_ON(kdiv != 2 && qdiv != 1); | |
| 2207 | 2190 | |
| 2208 | 2191 | params->qdiv_ratio = qdiv; |
| 2209 | 2192 | params->qdiv_mode = (qdiv == 1) ? 0 : 1; |
| 2210 | 2193 | |
| 2211 | − params->dco_integer = div_u64(dco_freq, ref_freq); | |
| 2212 | − params->dco_fraction = div_u64((div_u64((uint64_t)dco_freq<<15, (uint64_t)ref_freq) - | |
| 2213 | − ((uint64_t)params->dco_integer<<15)) * 0x8000, 0x8000); | |
| 2194 | + dco = div_u64((u64)dco_freq << 15, ref_freq); | |
| 2195 | + | |
| 2196 | + params->dco_integer = dco >> 15; | |
| 2197 | + params->dco_fraction = dco & 0x7fff; | |
| 2214 | 2198 | } |
| 2215 | 2199 | |
| 2216 | 2200 | static bool |
| 2217 | −cnl_ddi_calculate_wrpll(int clock /* in Hz */, | |
| 2201 | +cnl_ddi_calculate_wrpll(int clock, | |
| 2218 | 2202 | struct drm_i915_private *dev_priv, |
| 2219 | 2203 | struct skl_wrpll_params *wrpll_params) |
| 2220 | 2204 | { |
| 2221 | − uint64_t afe_clock = clock * 5 / KHz(1); /* clocks in kHz */ | |
| 2222 | − unsigned int dco_min = 7998 * KHz(1); | |
| 2223 | − unsigned int dco_max = 10000 * KHz(1); | |
| 2224 | − unsigned int dco_mid = (dco_min + dco_max) / 2; | |
| 2225 | − | |
| 2205 | + u32 afe_clock = clock * 5; | |
| 2206 | + u32 dco_min = 7998000; | |
| 2207 | + u32 dco_max = 10000000; | |
| 2208 | + u32 dco_mid = (dco_min + dco_max) / 2; | |
| 2226 | 2209 | static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16, |
| 2227 | 2210 | 18, 20, 24, 28, 30, 32, 36, 40, |
| 2228 | 2211 | 42, 44, 48, 50, 52, 54, 56, 60, |
| 2229 | 2212 | 64, 66, 68, 70, 72, 76, 78, 80, |
| 2230 | 2213 | 84, 88, 90, 92, 96, 98, 100, 102, |
| 2231 | 2214 | 3, 5, 7, 9, 15, 21 }; |
| 2232 | − unsigned int d, dco; | |
| 2233 | − unsigned int dco_centrality = 0; | |
| 2234 | − unsigned int best_dco_centrality = 999999; | |
| 2235 | − unsigned int best_div = 0; | |
| 2236 | − unsigned int best_dco = 0; | |
| 2237 | − unsigned int pdiv = 0, qdiv = 0, kdiv = 0; | |
| 2215 | + u32 dco, best_dco = 0, dco_centrality = 0; | |
| 2216 | + u32 best_dco_centrality = U32_MAX; /* Spec meaning of 999999 MHz */ | |
| 2217 | + int d, best_div = 0, pdiv = 0, qdiv = 0, kdiv = 0; | |
| 2238 | 2218 | |
| 2239 | 2219 | for (d = 0; d < ARRAY_SIZE(dividers); d++) { |
| 2240 | 2220 | dco = afe_clock * dividers[d]; |
| @@ -2271,7 +2251,7 @@ static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc, · 30 unmodified lines | ||
| 2271 | 2251 | |
| 2272 | 2252 | cfgcr0 = DPLL_CFGCR0_HDMI_MODE; |
| 2273 | 2253 | |
| 2274 | − if (!cnl_ddi_calculate_wrpll(clock * 1000, dev_priv, &wrpll_params)) | |
| 2254 | + if (!cnl_ddi_calculate_wrpll(clock, dev_priv, &wrpll_params)) | |
| 2275 | 2255 | return false; |
| 2276 | 2256 | |
| 2277 | 2257 | cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION(wrpll_params.dco_fraction) | |
| @@ -2281,7 +2261,6 @@ static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc, · 3 unmodified lines | ||
| 2281 | 2261 | DPLL_CFGCR1_QDIV_MODE(wrpll_params.qdiv_mode) | |
| 2282 | 2262 | DPLL_CFGCR1_KDIV(wrpll_params.kdiv) | |
| 2283 | 2263 | DPLL_CFGCR1_PDIV(wrpll_params.pdiv) | |
| 2284 | − wrpll_params.central_freq | | |
| 2285 | 2264 | DPLL_CFGCR1_CENTRAL_FREQ; |
| 2286 | 2265 | |
| 2287 | 2266 | memset(&crtc_state->dpll_hw_state, 0, |
| @@ -2345,15 +2324,13 @@ cnl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 57 unmodified lines | ||
| 2345 | 2324 | |
| 2346 | 2325 | memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); |
| 2347 | 2326 | |
| 2348 | − if (encoder->type == INTEL_OUTPUT_HDMI) { | |
| 2327 | + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { | |
| 2349 | 2328 | bret = cnl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock); |
| 2350 | 2329 | if (!bret) { |
| 2351 | 2330 | DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n"); |
| 2352 | 2331 | return NULL; |
| 2353 | 2332 | } |
| 2354 | − } else if (encoder->type == INTEL_OUTPUT_DP || | |
| 2355 | − encoder->type == INTEL_OUTPUT_DP_MST || | |
| 2356 | − encoder->type == INTEL_OUTPUT_EDP) { | |
| 2333 | + } else if (intel_crtc_has_dp_encoder(crtc_state)) { | |
| 2357 | 2334 | bret = cnl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state); |
| 2358 | 2335 | if (!bret) { |
| 2359 | 2336 | DRM_DEBUG_KMS("Could not set DP dpll HW state.\n"); |
| @@ -2361,8 +2338,8 @@ cnl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, · 1 unmodified line | ||
| 2361 | 2338 | } |
| 2362 | 2339 | crtc_state->dpll_hw_state = dpll_hw_state; |
| 2363 | 2340 | } else { |
| 2364 | − DRM_DEBUG_KMS("Skip DPLL setup for encoder %d\n", | |
| 2365 | − encoder->type); | |
| 2341 | + DRM_DEBUG_KMS("Skip DPLL setup for output_types 0x%x\n", | |
| 2342 | + crtc_state->output_types); | |
| 2366 | 2343 | return NULL; |
| 2367 | 2344 | } |
| 2368 | 2345 | |
| @@ -47,14 +47,11 @@ · 46 unmodified lines | ||
| 47 | 47 | * contexts. Note that it's important that we check the condition again after |
| 48 | 48 | * having timed out, since the timeout could be due to preemption or similar and |
| 49 | 49 | * we've never had a chance to check the condition before the timeout. |
| 50 | − * | |
| 51 | − * TODO: When modesetting has fully transitioned to atomic, the below | |
| 52 | − * drm_can_sleep() can be removed and in_atomic()/!in_atomic() asserts | |
| 53 | − * added. | |
| 54 | 50 | */ |
| 55 | 51 | #define _wait_for(COND, US, W) ({ \ |
| 56 | 52 | unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ |
| 57 | 53 | int ret__; \ |
| 54 | + might_sleep(); \ | |
| 58 | 55 | for (;;) { \ |
| 59 | 56 | bool expired__ = time_after(jiffies, timeout__); \ |
| 60 | 57 | if (COND) { \ |
| @@ -65,11 +62,7 @@ · 4 unmodified lines | ||
| 65 | 62 | ret__ = -ETIMEDOUT; \ |
| 66 | 63 | break; \ |
| 67 | 64 | } \ |
| 68 | − if ((W) && drm_can_sleep()) { \ | |
| 69 | − usleep_range((W), (W)*2); \ | |
| 70 | − } else { \ | |
| 71 | − cpu_relax(); \ | |
| 72 | − } \ | |
| 65 | + usleep_range((W), (W) * 2); \ | |
| 73 | 66 | } \ |
| 74 | 67 | ret__; \ |
| 75 | 68 | }) |
| @@ -173,7 +166,7 @@ enum intel_output_type { · 97 unmodified lines | ||
| 173 | 166 | INTEL_OUTPUT_DP = 7, |
| 174 | 167 | INTEL_OUTPUT_EDP = 8, |
| 175 | 168 | INTEL_OUTPUT_DSI = 9, |
| 176 | − INTEL_OUTPUT_UNKNOWN = 10, | |
| 169 | + INTEL_OUTPUT_DDI = 10, | |
| 177 | 170 | INTEL_OUTPUT_DP_MST = 11, |
| 178 | 171 | }; |
| 179 | 172 | |
| @@ -216,6 +209,9 @@ struct intel_encoder { · 36 unmodified lines | ||
| 216 | 209 | enum port port; |
| 217 | 210 | unsigned int cloneable; |
| 218 | 211 | void (*hot_plug)(struct intel_encoder *); |
| 212 | + enum intel_output_type (*compute_output_type)(struct intel_encoder *, | |
| 213 | + struct intel_crtc_state *, | |
| 214 | + struct drm_connector_state *); | |
| 219 | 215 | bool (*compute_config)(struct intel_encoder *, |
| 220 | 216 | struct intel_crtc_state *, |
| 221 | 217 | struct drm_connector_state *); |
| @@ -386,6 +382,8 @@ struct intel_atomic_state { · 164 unmodified lines | ||
| 386 | 382 | unsigned int active_crtcs; |
| 387 | 383 | /* minimum acceptable cdclk for each pipe */ |
| 388 | 384 | int min_cdclk[I915_MAX_PIPES]; |
| 385 | + /* minimum acceptable voltage level for each pipe */ | |
| 386 | + u8 min_voltage_level[I915_MAX_PIPES]; | |
| 389 | 387 | |
| 390 | 388 | struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; |
| 391 | 389 | |
| @@ -420,6 +418,9 @@ struct intel_plane_state { · 28 unmodified lines | ||
| 420 | 418 | /* plane control register */ |
| 421 | 419 | u32 ctl; |
| 422 | 420 | |
| 421 | + /* plane color control register */ | |
| 422 | + u32 color_ctl; | |
| 423 | + | |
| 423 | 424 | /* |
| 424 | 425 | * scaler_id |
| 425 | 426 | * = -1 : not using a scaler |
| @@ -738,6 +739,9 @@ struct intel_crtc_state { · 312 unmodified lines | ||
| 738 | 739 | */ |
| 739 | 740 | uint8_t lane_lat_optim_mask; |
| 740 | 741 | |
| 742 | + /* minimum acceptable voltage level */ | |
| 743 | + u8 min_voltage_level; | |
| 744 | + | |
| 741 | 745 | /* Panel fitter controls for gen2-gen4 + VLV */ |
| 742 | 746 | struct { |
| 743 | 747 | u32 control; |
| @@ -1048,7 +1052,6 @@ struct intel_lspcon { · 304 unmodified lines | ||
| 1048 | 1052 | |
| 1049 | 1053 | struct intel_digital_port { |
| 1050 | 1054 | struct intel_encoder base; |
| 1051 | − enum port port; | |
| 1052 | 1055 | u32 saved_port_bits; |
| 1053 | 1056 | struct intel_dp dp; |
| 1054 | 1057 | struct intel_hdmi hdmi; |
| @@ -1080,7 +1083,7 @@ struct intel_dp_mst_encoder { · 25 unmodified lines | ||
| 1080 | 1083 | static inline enum dpio_channel |
| 1081 | 1084 | vlv_dport_to_channel(struct intel_digital_port *dport) |
| 1082 | 1085 | { |
| 1083 | − switch (dport->port) { | |
| 1086 | + switch (dport->base.port) { | |
| 1084 | 1087 | case PORT_B: |
| 1085 | 1088 | case PORT_D: |
| 1086 | 1089 | return DPIO_CH0; |
| @@ -1094,7 +1097,7 @@ vlv_dport_to_channel(struct intel_digital_port *dport) · 7 unmodified lines | ||
| 1094 | 1097 | static inline enum dpio_phy |
| 1095 | 1098 | vlv_dport_to_phy(struct intel_digital_port *dport) |
| 1096 | 1099 | { |
| 1097 | − switch (dport->port) { | |
| 1100 | + switch (dport->base.port) { | |
| 1098 | 1101 | case PORT_B: |
| 1099 | 1102 | case PORT_C: |
| 1100 | 1103 | return DPIO_PHY0; |
| @@ -1147,7 +1150,7 @@ enc_to_dig_port(struct drm_encoder *encoder) · 46 unmodified lines | ||
| 1147 | 1150 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); |
| 1148 | 1151 | |
| 1149 | 1152 | switch (intel_encoder->type) { |
| 1150 | − case INTEL_OUTPUT_UNKNOWN: | |
| 1153 | + case INTEL_OUTPUT_DDI: | |
| 1151 | 1154 | WARN_ON(!HAS_DDI(to_i915(encoder->dev))); |
| 1152 | 1155 | case INTEL_OUTPUT_DP: |
| 1153 | 1156 | case INTEL_OUTPUT_EDP: |
| @@ -1271,7 +1274,6 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, · 117 unmodified lines | ||
| 1271 | 1274 | void hsw_fdi_link_train(struct intel_crtc *crtc, |
| 1272 | 1275 | const struct intel_crtc_state *crtc_state); |
| 1273 | 1276 | void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); |
| 1274 | −enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); | |
| 1275 | 1277 | bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); |
| 1276 | 1278 | void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state); |
| 1277 | 1279 | void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, |
| @@ -1288,10 +1290,10 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, · 10 unmodified lines | ||
| 1288 | 1290 | void intel_ddi_get_config(struct intel_encoder *encoder, |
| 1289 | 1291 | struct intel_crtc_state *pipe_config); |
| 1290 | 1292 | |
| 1291 | −void intel_ddi_clock_get(struct intel_encoder *encoder, | |
| 1292 | − struct intel_crtc_state *pipe_config); | |
| 1293 | 1293 | void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, |
| 1294 | 1294 | bool state); |
| 1295 | +void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, | |
| 1296 | + struct intel_crtc_state *crtc_state); | |
| 1295 | 1297 | u32 bxt_signal_levels(struct intel_dp *intel_dp); |
| 1296 | 1298 | uint32_t ddi_signal_levels(struct intel_dp *intel_dp); |
| 1297 | 1299 | u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); |
| @@ -1304,7 +1306,9 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv); · 6 unmodified lines | ||
| 1304 | 1306 | void intel_audio_codec_enable(struct intel_encoder *encoder, |
| 1305 | 1307 | const struct intel_crtc_state *crtc_state, |
| 1306 | 1308 | const struct drm_connector_state *conn_state); |
| 1307 | −void intel_audio_codec_disable(struct intel_encoder *encoder); | |
| 1309 | +void intel_audio_codec_disable(struct intel_encoder *encoder, | |
| 1310 | + const struct intel_crtc_state *old_crtc_state, | |
| 1311 | + const struct drm_connector_state *old_conn_state); | |
| 1308 | 1312 | void i915_audio_component_init(struct drm_i915_private *dev_priv); |
| 1309 | 1313 | void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); |
| 1310 | 1314 | void intel_audio_init(struct drm_i915_private *dev_priv); |
| @@ -1322,10 +1326,14 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); · 11 unmodified lines | ||
| 1322 | 1326 | void intel_update_max_cdclk(struct drm_i915_private *dev_priv); |
| 1323 | 1327 | void intel_update_cdclk(struct drm_i915_private *dev_priv); |
| 1324 | 1328 | void intel_update_rawclk(struct drm_i915_private *dev_priv); |
| 1325 | −bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, | |
| 1329 | +bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a, | |
| 1326 | 1330 | const struct intel_cdclk_state *b); |
| 1331 | +bool intel_cdclk_changed(const struct intel_cdclk_state *a, | |
| 1332 | + const struct intel_cdclk_state *b); | |
| 1327 | 1333 | void intel_set_cdclk(struct drm_i915_private *dev_priv, |
| 1328 | 1334 | const struct intel_cdclk_state *cdclk_state); |
| 1335 | +void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state, | |
| 1336 | + const char *context); | |
| 1329 | 1337 | |
| 1330 | 1338 | /* intel_display.c */ |
| 1331 | 1339 | void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); |
| @@ -1477,8 +1485,8 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, · 145 unmodified lines | ||
| 1477 | 1485 | int chv_calc_dpll_params(int refclk, struct dpll *pll_clock); |
| 1478 | 1486 | |
| 1479 | 1487 | bool intel_crtc_active(struct intel_crtc *crtc); |
| 1480 | −void hsw_enable_ips(struct intel_crtc *crtc); | |
| 1481 | −void hsw_disable_ips(struct intel_crtc *crtc); | |
| 1488 | +void hsw_enable_ips(const struct intel_crtc_state *crtc_state); | |
| 1489 | +void hsw_disable_ips(const struct intel_crtc_state *crtc_state); | |
| 1482 | 1490 | enum intel_display_power_domain intel_port_to_power_domain(enum port port); |
| 1483 | 1491 | void intel_mode_from_pipe_config(struct drm_display_mode *mode, |
| 1484 | 1492 | struct intel_crtc_state *pipe_config); |
| @@ -1491,6 +1499,8 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) · 6 unmodified lines | ||
| 1491 | 1499 | return i915_ggtt_offset(state->vma); |
| 1492 | 1500 | } |
| 1493 | 1501 | |
| 1502 | +u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |
| 1503 | + const struct intel_plane_state *plane_state); | |
| 1494 | 1504 | u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, |
| 1495 | 1505 | const struct intel_plane_state *plane_state); |
| 1496 | 1506 | u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, |
| @@ -1521,7 +1531,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); · 24 unmodified lines | ||
| 1521 | 1531 | void intel_dp_encoder_reset(struct drm_encoder *encoder); |
| 1522 | 1532 | void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder); |
| 1523 | 1533 | void intel_dp_encoder_destroy(struct drm_encoder *encoder); |
| 1524 | −int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc); | |
| 1534 | +int intel_dp_sink_crc(struct intel_dp *intel_dp, | |
| 1535 | + struct intel_crtc_state *crtc_state, u8 *crc); | |
| 1525 | 1536 | bool intel_dp_compute_config(struct intel_encoder *encoder, |
| 1526 | 1537 | struct intel_crtc_state *pipe_config, |
| 1527 | 1538 | struct drm_connector_state *conn_state); |
| @@ -1868,7 +1879,6 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv); · 340 unmodified lines | ||
| 1868 | 1879 | void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv); |
| 1869 | 1880 | void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv); |
| 1870 | 1881 | void intel_enable_gt_powersave(struct drm_i915_private *dev_priv); |
| 1871 | −void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv); | |
| 1872 | 1882 | void intel_disable_gt_powersave(struct drm_i915_private *dev_priv); |
| 1873 | 1883 | void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv); |
| 1874 | 1884 | void gen6_rps_busy(struct drm_i915_private *dev_priv); |
| @@ -662,11 +662,11 @@ static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder) · 661 unmodified lines | ||
| 662 | 662 | } |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | −static void intel_dsi_port_enable(struct intel_encoder *encoder) | |
| 665 | +static void intel_dsi_port_enable(struct intel_encoder *encoder, | |
| 666 | + const struct intel_crtc_state *crtc_state) | |
| 666 | 667 | { |
| 667 | − struct drm_device *dev = encoder->base.dev; | |
| 668 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 669 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 668 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 669 | + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | |
| 670 | 670 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
| 671 | 671 | enum port port; |
| 672 | 672 | |
| @@ -705,7 +705,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) · 32 unmodified lines | ||
| 705 | 705 | if (IS_BROXTON(dev_priv)) |
| 706 | 706 | temp |= LANE_CONFIGURATION_DUAL_LINK_A; |
| 707 | 707 | else |
| 708 | − temp |= intel_crtc->pipe ? | |
| 708 | + temp |= crtc->pipe ? | |
| 709 | 709 | LANE_CONFIGURATION_DUAL_LINK_B : |
| 710 | 710 | LANE_CONFIGURATION_DUAL_LINK_A; |
| 711 | 711 | } |
| @@ -875,7 +875,7 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, · 163 unmodified lines | ||
| 875 | 875 | |
| 876 | 876 | intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); |
| 877 | 877 | |
| 878 | − intel_dsi_port_enable(encoder); | |
| 878 | + intel_dsi_port_enable(encoder, pipe_config); | |
| 879 | 879 | } |
| 880 | 880 | |
| 881 | 881 | intel_panel_enable_backlight(pipe_config, conn_state); |
| @@ -1082,7 +1082,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, · 200 unmodified lines | ||
| 1082 | 1082 | struct drm_display_mode *adjusted_mode = |
| 1083 | 1083 | &pipe_config->base.adjusted_mode; |
| 1084 | 1084 | struct drm_display_mode *adjusted_mode_sw; |
| 1085 | − struct intel_crtc *intel_crtc; | |
| 1085 | + struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 1086 | 1086 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
| 1087 | 1087 | unsigned int lane_count = intel_dsi->lane_count; |
| 1088 | 1088 | unsigned int bpp, fmt; |
| @@ -1093,8 +1093,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, · 4 unmodified lines | ||
| 1093 | 1093 | crtc_hblank_start_sw, crtc_hblank_end_sw; |
| 1094 | 1094 | |
| 1095 | 1095 | /* FIXME: hw readout should not depend on SW state */ |
| 1096 | − intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 1097 | − adjusted_mode_sw = &intel_crtc->config->base.adjusted_mode; | |
| 1096 | + adjusted_mode_sw = &crtc->config->base.adjusted_mode; | |
| 1098 | 1097 | |
| 1099 | 1098 | /* |
| 1100 | 1099 | * Atleast one port is active as encoder->get_config called only if |
| @@ -1243,6 +1242,8 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, · 142 unmodified lines | ||
| 1243 | 1242 | u32 pclk; |
| 1244 | 1243 | DRM_DEBUG_KMS("\n"); |
| 1245 | 1244 | |
| 1245 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI); | |
| 1246 | + | |
| 1246 | 1247 | if (IS_GEN9_LP(dev_priv)) |
| 1247 | 1248 | bxt_dsi_get_pipe_config(encoder, pipe_config); |
| 1248 | 1249 | |
| @@ -159,6 +159,8 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, · 158 unmodified lines | ||
| 159 | 159 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
| 160 | 160 | u32 tmp, flags = 0; |
| 161 | 161 | |
| 162 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO); | |
| 163 | + | |
| 162 | 164 | tmp = I915_READ(intel_dvo->dev.dvo_reg); |
| 163 | 165 | if (tmp & DVO_HSYNC_ACTIVE_HIGH) |
| 164 | 166 | flags |= DRM_MODE_FLAG_PHSYNC; |
| @@ -50,6 +50,8 @@ struct engine_class_info { · 49 unmodified lines | ||
| 50 | 50 | const char *name; |
| 51 | 51 | int (*init_legacy)(struct intel_engine_cs *engine); |
| 52 | 52 | int (*init_execlists)(struct intel_engine_cs *engine); |
| 53 | + | |
| 54 | + u8 uabi_class; | |
| 53 | 55 | }; |
| 54 | 56 | |
| 55 | 57 | static const struct engine_class_info intel_engine_classes[] = { |
| @@ -57,21 +59,25 @@ static const struct engine_class_info intel_engine_classes[] = { · 1 unmodified line | ||
| 57 | 59 | .name = "rcs", |
| 58 | 60 | .init_execlists = logical_render_ring_init, |
| 59 | 61 | .init_legacy = intel_init_render_ring_buffer, |
| 62 | + .uabi_class = I915_ENGINE_CLASS_RENDER, | |
| 60 | 63 | }, |
| 61 | 64 | [COPY_ENGINE_CLASS] = { |
| 62 | 65 | .name = "bcs", |
| 63 | 66 | .init_execlists = logical_xcs_ring_init, |
| 64 | 67 | .init_legacy = intel_init_blt_ring_buffer, |
| 68 | + .uabi_class = I915_ENGINE_CLASS_COPY, | |
| 65 | 69 | }, |
| 66 | 70 | [VIDEO_DECODE_CLASS] = { |
| 67 | 71 | .name = "vcs", |
| 68 | 72 | .init_execlists = logical_xcs_ring_init, |
| 69 | 73 | .init_legacy = intel_init_bsd_ring_buffer, |
| 74 | + .uabi_class = I915_ENGINE_CLASS_VIDEO, | |
| 70 | 75 | }, |
| 71 | 76 | [VIDEO_ENHANCEMENT_CLASS] = { |
| 72 | 77 | .name = "vecs", |
| 73 | 78 | .init_execlists = logical_xcs_ring_init, |
| 74 | 79 | .init_legacy = intel_init_vebox_ring_buffer, |
| 80 | + .uabi_class = I915_ENGINE_CLASS_VIDEO_ENHANCE, | |
| 75 | 81 | }, |
| 76 | 82 | }; |
| 77 | 83 | |
| @@ -213,13 +219,15 @@ intel_engine_setup(struct drm_i915_private *dev_priv, · 135 unmodified lines | ||
| 213 | 219 | WARN_ON(snprintf(engine->name, sizeof(engine->name), "%s%u", |
| 214 | 220 | class_info->name, info->instance) >= |
| 215 | 221 | sizeof(engine->name)); |
| 216 | − engine->uabi_id = info->uabi_id; | |
| 217 | 222 | engine->hw_id = engine->guc_id = info->hw_id; |
| 218 | 223 | engine->mmio_base = info->mmio_base; |
| 219 | 224 | engine->irq_shift = info->irq_shift; |
| 220 | 225 | engine->class = info->class; |
| 221 | 226 | engine->instance = info->instance; |
| 222 | 227 | |
| 228 | + engine->uabi_id = info->uabi_id; | |
| 229 | + engine->uabi_class = class_info->uabi_class; | |
| 230 | + | |
| 223 | 231 | engine->context_size = __intel_engine_context_size(dev_priv, |
| 224 | 232 | engine->class); |
| 225 | 233 | if (WARN_ON(engine->context_size > BIT(20))) |
| @@ -281,6 +289,8 @@ int intel_engines_init_mmio(struct drm_i915_private *dev_priv) · 55 unmodified lines | ||
| 281 | 289 | |
| 282 | 290 | device_info->num_rings = hweight32(mask); |
| 283 | 291 | |
| 292 | + i915_check_and_clear_faults(dev_priv); | |
| 293 | + | |
| 284 | 294 | return 0; |
| 285 | 295 | |
| 286 | 296 | cleanup: |
| @@ -620,7 +630,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) · 333 unmodified lines | ||
| 620 | 630 | * Similarly the preempt context must always be available so that |
| 621 | 631 | * we can interrupt the engine at any time. |
| 622 | 632 | */ |
| 623 | − if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) { | |
| 633 | + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { | |
| 624 | 634 | ring = engine->context_pin(engine, |
| 625 | 635 | engine->i915->preempt_context); |
| 626 | 636 | if (IS_ERR(ring)) { |
| @@ -633,25 +643,19 @@ int intel_engine_init_common(struct intel_engine_cs *engine) · 6 unmodified lines | ||
| 633 | 643 | if (ret) |
| 634 | 644 | goto err_unpin_preempt; |
| 635 | 645 | |
| 636 | − ret = i915_gem_render_state_init(engine); | |
| 637 | − if (ret) | |
| 638 | − goto err_breadcrumbs; | |
| 639 | − | |
| 640 | 646 | if (HWS_NEEDS_PHYSICAL(engine->i915)) |
| 641 | 647 | ret = init_phys_status_page(engine); |
| 642 | 648 | else |
| 643 | 649 | ret = init_status_page(engine); |
| 644 | 650 | if (ret) |
| 645 | − goto err_rs_fini; | |
| 651 | + goto err_breadcrumbs; | |
| 646 | 652 | |
| 647 | 653 | return 0; |
| 648 | 654 | |
| 649 | −err_rs_fini: | |
| 650 | − i915_gem_render_state_fini(engine); | |
| 651 | 655 | err_breadcrumbs: |
| 652 | 656 | intel_engine_fini_breadcrumbs(engine); |
| 653 | 657 | err_unpin_preempt: |
| 654 | − if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) | |
| 658 | + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) | |
| 655 | 659 | engine->context_unpin(engine, engine->i915->preempt_context); |
| 656 | 660 | err_unpin_kernel: |
| 657 | 661 | engine->context_unpin(engine, engine->i915->kernel_context); |
| @@ -674,12 +678,14 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) · 16 unmodified lines | ||
| 674 | 678 | else |
| 675 | 679 | cleanup_status_page(engine); |
| 676 | 680 | |
| 677 | − i915_gem_render_state_fini(engine); | |
| 678 | 681 | intel_engine_fini_breadcrumbs(engine); |
| 679 | 682 | intel_engine_cleanup_cmd_parser(engine); |
| 680 | 683 | i915_gem_batch_pool_fini(&engine->batch_pool); |
| 681 | 684 | |
| 682 | − if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) | |
| 685 | + if (engine->default_state) | |
| 686 | + i915_gem_object_put(engine->default_state); | |
| 687 | + | |
| 688 | + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) | |
| 683 | 689 | engine->context_unpin(engine, engine->i915->preempt_context); |
| 684 | 690 | engine->context_unpin(engine, engine->i915->kernel_context); |
| 685 | 691 | } |
| @@ -1014,22 +1020,6 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) · 328 unmodified lines | ||
| 1014 | 1020 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
| 1015 | 1021 | GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); |
| 1016 | 1022 | |
| 1017 | − /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */ | |
| 1018 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | |
| 1019 | − WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, | |
| 1020 | − GEN9_DG_MIRROR_FIX_ENABLE); | |
| 1021 | − | |
| 1022 | − /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ | |
| 1023 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | |
| 1024 | − WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, | |
| 1025 | − GEN9_RHWO_OPTIMIZATION_DISABLE); | |
| 1026 | − /* | |
| 1027 | − * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set | |
| 1028 | − * but we do that in per ctx batchbuffer as there is an issue | |
| 1029 | − * with this register not getting restored on ctx restore | |
| 1030 | − */ | |
| 1031 | − } | |
| 1032 | − | |
| 1033 | 1023 | /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */ |
| 1034 | 1024 | /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */ |
| 1035 | 1025 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, |
| @@ -1045,11 +1035,6 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) · 9 unmodified lines | ||
| 1045 | 1035 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, |
| 1046 | 1036 | GEN9_CCS_TLB_PREFETCH_ENABLE); |
| 1047 | 1037 | |
| 1048 | − /* WaDisableMaskBasedCammingInRCC:bxt */ | |
| 1049 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | |
| 1050 | − WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, | |
| 1051 | − PIXEL_MASK_CAMMING_DISABLE); | |
| 1052 | − | |
| 1053 | 1038 | /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */ |
| 1054 | 1039 | WA_SET_BIT_MASKED(HDC_CHICKEN0, |
| 1055 | 1040 | HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | |
| @@ -1079,8 +1064,7 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) · 23 unmodified lines | ||
| 1079 | 1064 | /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */ |
| 1080 | 1065 | if (IS_SKYLAKE(dev_priv) || |
| 1081 | 1066 | IS_KABYLAKE(dev_priv) || |
| 1082 | − IS_COFFEELAKE(dev_priv) || | |
| 1083 | − IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) | |
| 1067 | + IS_COFFEELAKE(dev_priv)) | |
| 1084 | 1068 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
| 1085 | 1069 | GEN8_SAMPLER_POWER_BYPASS_DIS); |
| 1086 | 1070 | |
| @@ -1204,72 +1188,35 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) · 117 unmodified lines | ||
| 1204 | 1188 | static int bxt_init_workarounds(struct intel_engine_cs *engine) |
| 1205 | 1189 | { |
| 1206 | 1190 | struct drm_i915_private *dev_priv = engine->i915; |
| 1191 | + u32 val; | |
| 1207 | 1192 | int ret; |
| 1208 | 1193 | |
| 1209 | 1194 | ret = gen9_init_workarounds(engine); |
| 1210 | 1195 | if (ret) |
| 1211 | 1196 | return ret; |
| 1212 | 1197 | |
| 1213 | − /* WaStoreMultiplePTEenable:bxt */ | |
| 1214 | − /* This is a requirement according to Hardware specification */ | |
| 1215 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | |
| 1216 | − I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); | |
| 1217 | − | |
| 1218 | − /* WaSetClckGatingDisableMedia:bxt */ | |
| 1219 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | |
| 1220 | − I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & | |
| 1221 | − ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); | |
| 1222 | − } | |
| 1223 | − | |
| 1224 | 1198 | /* WaDisableThreadStallDopClockGating:bxt */ |
| 1225 | 1199 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
| 1226 | 1200 | STALL_DOP_GATING_DISABLE); |
| 1227 | 1201 | |
| 1228 | 1202 | /* WaDisablePooledEuLoadBalancingFix:bxt */ |
| 1229 | − if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { | |
| 1230 | − I915_WRITE(FF_SLICE_CS_CHICKEN2, | |
| 1231 | − _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); | |
| 1232 | − } | |
| 1233 | − | |
| 1234 | − /* WaDisableSbeCacheDispatchPortSharing:bxt */ | |
| 1235 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { | |
| 1236 | − WA_SET_BIT_MASKED( | |
| 1237 | − GEN7_HALF_SLICE_CHICKEN1, | |
| 1238 | − GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | |
| 1239 | − } | |
| 1240 | − | |
| 1241 | − /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ | |
| 1242 | − /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ | |
| 1243 | − /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ | |
| 1244 | − /* WaDisableLSQCROPERFforOCL:bxt */ | |
| 1245 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | |
| 1246 | − ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); | |
| 1247 | − if (ret) | |
| 1248 | − return ret; | |
| 1249 | − | |
| 1250 | − ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | |
| 1251 | − if (ret) | |
| 1252 | − return ret; | |
| 1253 | − } | |
| 1203 | + I915_WRITE(FF_SLICE_CS_CHICKEN2, | |
| 1204 | + _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); | |
| 1254 | 1205 | |
| 1255 | 1206 | /* WaProgramL3SqcReg1DefaultForPerf:bxt */ |
| 1256 | − if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { | |
| 1257 | − u32 val = I915_READ(GEN8_L3SQCREG1); | |
| 1258 | − val &= ~L3_PRIO_CREDITS_MASK; | |
| 1259 | − val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); | |
| 1260 | − I915_WRITE(GEN8_L3SQCREG1, val); | |
| 1261 | − } | |
| 1207 | + val = I915_READ(GEN8_L3SQCREG1); | |
| 1208 | + val &= ~L3_PRIO_CREDITS_MASK; | |
| 1209 | + val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); | |
| 1210 | + I915_WRITE(GEN8_L3SQCREG1, val); | |
| 1262 | 1211 | |
| 1263 | 1212 | /* WaToEnableHwFixForPushConstHWBug:bxt */ |
| 1264 | − if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) | |
| 1265 | − WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | |
| 1266 | − GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | |
| 1213 | + WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, | |
| 1214 | + GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); | |
| 1267 | 1215 | |
| 1268 | 1216 | /* WaInPlaceDecompressionHang:bxt */ |
| 1269 | − if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) | |
| 1270 | − I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | |
| 1271 | − (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | |
| 1272 | − GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | |
| 1217 | + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | |
| 1218 | + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | |
| 1219 | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); | |
| 1273 | 1220 | |
| 1274 | 1221 | return 0; |
| 1275 | 1222 | } |
| @@ -1585,6 +1532,34 @@ bool intel_engines_are_idle(struct drm_i915_private *dev_priv) · 309 unmodified lines | ||
| 1585 | 1532 | return true; |
| 1586 | 1533 | } |
| 1587 | 1534 | |
| 1535 | +/** | |
| 1536 | + * intel_engine_has_kernel_context: | |
| 1537 | + * @engine: the engine | |
| 1538 | + * | |
| 1539 | + * Returns true if the last context to be executed on this engine, or has been | |
| 1540 | + * executed if the engine is already idle, is the kernel context | |
| 1541 | + * (#i915.kernel_context). | |
| 1542 | + */ | |
| 1543 | +bool intel_engine_has_kernel_context(const struct intel_engine_cs *engine) | |
| 1544 | +{ | |
| 1545 | + const struct i915_gem_context * const kernel_context = | |
| 1546 | + engine->i915->kernel_context; | |
| 1547 | + struct drm_i915_gem_request *rq; | |
| 1548 | + | |
| 1549 | + lockdep_assert_held(&engine->i915->drm.struct_mutex); | |
| 1550 | + | |
| 1551 | + /* | |
| 1552 | + * Check the last context seen by the engine. If active, it will be | |
| 1553 | + * the last request that remains in the timeline. When idle, it is | |
| 1554 | + * the last executed context as tracked by retirement. | |
| 1555 | + */ | |
| 1556 | + rq = __i915_gem_active_peek(&engine->timeline->last_request); | |
| 1557 | + if (rq) | |
| 1558 | + return rq->ctx == kernel_context; | |
| 1559 | + else | |
| 1560 | + return engine->last_retired_context == kernel_context; | |
| 1561 | +} | |
| 1562 | + | |
| 1588 | 1563 | void intel_engines_reset_default_submission(struct drm_i915_private *i915) |
| 1589 | 1564 | { |
| 1590 | 1565 | struct intel_engine_cs *engine; |
| @@ -1594,19 +1569,63 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915) · 3 unmodified lines | ||
| 1594 | 1569 | engine->set_default_submission(engine); |
| 1595 | 1570 | } |
| 1596 | 1571 | |
| 1597 | −void intel_engines_mark_idle(struct drm_i915_private *i915) | |
| 1572 | +/** | |
| 1573 | + * intel_engines_park: called when the GT is transitioning from busy->idle | |
| 1574 | + * @i915: the i915 device | |
| 1575 | + * | |
| 1576 | + * The GT is now idle and about to go to sleep (maybe never to wake again?). | |
| 1577 | + * Time for us to tidy and put away our toys (release resources back to the | |
| 1578 | + * system). | |
| 1579 | + */ | |
| 1580 | +void intel_engines_park(struct drm_i915_private *i915) | |
| 1598 | 1581 | { |
| 1599 | 1582 | struct intel_engine_cs *engine; |
| 1600 | 1583 | enum intel_engine_id id; |
| 1601 | 1584 | |
| 1602 | 1585 | for_each_engine(engine, i915, id) { |
| 1586 | + /* Flush the residual irq tasklets first. */ | |
| 1603 | 1587 | intel_engine_disarm_breadcrumbs(engine); |
| 1588 | + tasklet_kill(&engine->execlists.tasklet); | |
| 1589 | + | |
| 1590 | + /* | |
| 1591 | + * We are committed now to parking the engines, make sure there | |
| 1592 | + * will be no more interrupts arriving later and the engines | |
| 1593 | + * are truly idle. | |
| 1594 | + */ | |
| 1595 | + if (wait_for(intel_engine_is_idle(engine), 10)) { | |
| 1596 | + struct drm_printer p = drm_debug_printer(__func__); | |
| 1597 | + | |
| 1598 | + dev_err(i915->drm.dev, | |
| 1599 | + "%s is not idle before parking\n", | |
| 1600 | + engine->name); | |
| 1601 | + intel_engine_dump(engine, &p); | |
| 1602 | + } | |
| 1603 | + | |
| 1604 | + if (engine->park) | |
| 1605 | + engine->park(engine); | |
| 1606 | + | |
| 1604 | 1607 | i915_gem_batch_pool_fini(&engine->batch_pool); |
| 1605 | − tasklet_kill(&engine->execlists.irq_tasklet); | |
| 1606 | 1608 | engine->execlists.no_priolist = false; |
| 1607 | 1609 | } |
| 1608 | 1610 | } |
| 1609 | 1611 | |
| 1612 | +/** | |
| 1613 | + * intel_engines_unpark: called when the GT is transitioning from idle->busy | |
| 1614 | + * @i915: the i915 device | |
| 1615 | + * | |
| 1616 | + * The GT was idle and now about to fire up with some new user requests. | |
| 1617 | + */ | |
| 1618 | +void intel_engines_unpark(struct drm_i915_private *i915) | |
| 1619 | +{ | |
| 1620 | + struct intel_engine_cs *engine; | |
| 1621 | + enum intel_engine_id id; | |
| 1622 | + | |
| 1623 | + for_each_engine(engine, i915, id) { | |
| 1624 | + if (engine->unpark) | |
| 1625 | + engine->unpark(engine); | |
| 1626 | + } | |
| 1627 | +} | |
| 1628 | + | |
| 1610 | 1629 | bool intel_engine_can_store_dword(struct intel_engine_cs *engine) |
| 1611 | 1630 | { |
| 1612 | 1631 | switch (INTEL_GEN(engine->i915)) { |
| @@ -1622,6 +1641,20 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine) · 9 unmodified lines | ||
| 1622 | 1641 | } |
| 1623 | 1642 | } |
| 1624 | 1643 | |
| 1644 | +unsigned int intel_engines_has_context_isolation(struct drm_i915_private *i915) | |
| 1645 | +{ | |
| 1646 | + struct intel_engine_cs *engine; | |
| 1647 | + enum intel_engine_id id; | |
| 1648 | + unsigned int which; | |
| 1649 | + | |
| 1650 | + which = 0; | |
| 1651 | + for_each_engine(engine, i915, id) | |
| 1652 | + if (engine->default_state) | |
| 1653 | + which |= BIT(engine->uabi_class); | |
| 1654 | + | |
| 1655 | + return which; | |
| 1656 | +} | |
| 1657 | + | |
| 1625 | 1658 | static void print_request(struct drm_printer *m, |
| 1626 | 1659 | struct drm_i915_gem_request *rq, |
| 1627 | 1660 | const char *prefix) |
| @@ -1688,9 +1721,14 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) · 60 unmodified lines | ||
| 1688 | 1721 | drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", |
| 1689 | 1722 | I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, |
| 1690 | 1723 | rq ? rq->ring->tail : 0); |
| 1691 | − drm_printf(m, "\tRING_CTL: 0x%08x [%s]\n", | |
| 1724 | + drm_printf(m, "\tRING_CTL: 0x%08x%s\n", | |
| 1692 | 1725 | I915_READ(RING_CTL(engine->mmio_base)), |
| 1693 | − I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : ""); | |
| 1726 | + I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? " [waiting]" : ""); | |
| 1727 | + if (INTEL_GEN(engine->i915) > 2) { | |
| 1728 | + drm_printf(m, "\tRING_MODE: 0x%08x%s\n", | |
| 1729 | + I915_READ(RING_MI_MODE(engine->mmio_base)), | |
| 1730 | + I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); | |
| 1731 | + } | |
| 1694 | 1732 | |
| 1695 | 1733 | rcu_read_unlock(); |
| 1696 | 1734 | |
| @@ -1781,6 +1819,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) · 84 unmodified lines | ||
| 1781 | 1819 | } |
| 1782 | 1820 | spin_unlock_irq(&b->rb_lock); |
| 1783 | 1821 | |
| 1822 | + drm_printf(m, "Idle? %s\n", yesno(intel_engine_is_idle(engine))); | |
| 1784 | 1823 | drm_printf(m, "\n"); |
| 1785 | 1824 | } |
| 1786 | 1825 | |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | 25 | #include "intel_guc.h" |
| 26 | +#include "intel_guc_submission.h" | |
| 26 | 27 | #include "i915_drv.h" |
| 27 | 28 | |
| 28 | 29 | static void gen8_guc_raise_irq(struct intel_guc *guc) |
| @@ -268,7 +269,6 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset) · 239 unmodified lines | ||
| 268 | 269 | int intel_guc_suspend(struct drm_i915_private *dev_priv) |
| 269 | 270 | { |
| 270 | 271 | struct intel_guc *guc = &dev_priv->guc; |
| 271 | − struct i915_gem_context *ctx; | |
| 272 | 272 | u32 data[3]; |
| 273 | 273 | |
| 274 | 274 | if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) |
| @@ -276,14 +276,33 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv) · 1 unmodified line | ||
| 276 | 276 | |
| 277 | 277 | gen9_disable_guc_interrupts(dev_priv); |
| 278 | 278 | |
| 279 | − ctx = dev_priv->kernel_context; | |
| 280 | − | |
| 281 | 279 | data[0] = INTEL_GUC_ACTION_ENTER_S_STATE; |
| 282 | 280 | /* any value greater than GUC_POWER_D0 */ |
| 283 | 281 | data[1] = GUC_POWER_D1; |
| 284 | − /* first page is shared data with GuC */ | |
| 285 | − data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + | |
| 286 | − LRC_GUCSHR_PN * PAGE_SIZE; | |
| 282 | + data[2] = guc_ggtt_offset(guc->shared_data); | |
| 283 | + | |
| 284 | + return intel_guc_send(guc, data, ARRAY_SIZE(data)); | |
| 285 | +} | |
| 286 | + | |
| 287 | +/** | |
| 288 | + * intel_guc_reset_engine() - ask GuC to reset an engine | |
| 289 | + * @guc: intel_guc structure | |
| 290 | + * @engine: engine to be reset | |
| 291 | + */ | |
| 292 | +int intel_guc_reset_engine(struct intel_guc *guc, | |
| 293 | + struct intel_engine_cs *engine) | |
| 294 | +{ | |
| 295 | + u32 data[7]; | |
| 296 | + | |
| 297 | + GEM_BUG_ON(!guc->execbuf_client); | |
| 298 | + | |
| 299 | + data[0] = INTEL_GUC_ACTION_REQUEST_ENGINE_RESET; | |
| 300 | + data[1] = engine->guc_id; | |
| 301 | + data[2] = 0; | |
| 302 | + data[3] = 0; | |
| 303 | + data[4] = 0; | |
| 304 | + data[5] = guc->execbuf_client->stage_id; | |
| 305 | + data[6] = guc_ggtt_offset(guc->shared_data); | |
| 287 | 306 | |
| 288 | 307 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
| 289 | 308 | } |
| @@ -295,7 +314,6 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv) · 5 unmodified lines | ||
| 295 | 314 | int intel_guc_resume(struct drm_i915_private *dev_priv) |
| 296 | 315 | { |
| 297 | 316 | struct intel_guc *guc = &dev_priv->guc; |
| 298 | − struct i915_gem_context *ctx; | |
| 299 | 317 | u32 data[3]; |
| 300 | 318 | |
| 301 | 319 | if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) |
| @@ -304,13 +322,9 @@ int intel_guc_resume(struct drm_i915_private *dev_priv) · 2 unmodified lines | ||
| 304 | 322 | if (i915_modparams.guc_log_level >= 0) |
| 305 | 323 | gen9_enable_guc_interrupts(dev_priv); |
| 306 | 324 | |
| 307 | − ctx = dev_priv->kernel_context; | |
| 308 | − | |
| 309 | 325 | data[0] = INTEL_GUC_ACTION_EXIT_S_STATE; |
| 310 | 326 | data[1] = GUC_POWER_D0; |
| 311 | − /* first page is shared data with GuC */ | |
| 312 | − data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + | |
| 313 | − LRC_GUCSHR_PN * PAGE_SIZE; | |
| 327 | + data[2] = guc_ggtt_offset(guc->shared_data); | |
| 314 | 328 | |
| 315 | 329 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
| 316 | 330 | } |
| @@ -34,9 +34,14 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "i915_guc_reg.h" |
| 35 | 35 | #include "i915_vma.h" |
| 36 | 36 | |
| 37 | +struct guc_preempt_work { | |
| 38 | + struct work_struct work; | |
| 39 | + struct intel_engine_cs *engine; | |
| 40 | +}; | |
| 41 | + | |
| 37 | 42 | /* |
| 38 | 43 | * Top level structure of GuC. It handles firmware loading and manages client |
| 39 | − * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy | |
| 44 | + * pool and doorbells. intel_guc owns a intel_guc_client to replace the legacy | |
| 40 | 45 | * ExecList submission. |
| 41 | 46 | */ |
| 42 | 47 | struct intel_guc { |
| @@ -54,8 +59,14 @@ struct intel_guc { · 11 unmodified lines | ||
| 54 | 59 | struct i915_vma *stage_desc_pool; |
| 55 | 60 | void *stage_desc_pool_vaddr; |
| 56 | 61 | struct ida stage_ids; |
| 62 | + struct i915_vma *shared_data; | |
| 63 | + void *shared_data_vaddr; | |
| 64 | + | |
| 65 | + struct intel_guc_client *execbuf_client; | |
| 66 | + struct intel_guc_client *preempt_client; | |
| 57 | 67 | |
| 58 | − struct i915_guc_client *execbuf_client; | |
| 68 | + struct guc_preempt_work preempt_work[I915_NUM_ENGINES]; | |
| 69 | + struct workqueue_struct *preempt_wq; | |
| 59 | 70 | |
| 60 | 71 | DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS); |
| 61 | 72 | /* Cyclic counter mod pagesize */ |
| @@ -198,6 +198,7 @@ static int ctch_open(struct intel_guc *guc, · 197 unmodified lines | ||
| 198 | 198 | err = ctch_init(guc, ctch); |
| 199 | 199 | if (unlikely(err)) |
| 200 | 200 | goto err_out; |
| 201 | + GEM_BUG_ON(!ctch->vma); | |
| 201 | 202 | } |
| 202 | 203 | |
| 203 | 204 | /* vma should be already allocated and map'ed */ |
| @@ -97,23 +97,50 @@ int intel_guc_fw_select(struct intel_guc *guc) · 96 unmodified lines | ||
| 97 | 97 | return 0; |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | −/* | |
| 101 | − * Read the GuC status register (GUC_STATUS) and store it in the | |
| 102 | − * specified location; then return a boolean indicating whether | |
| 103 | − * the value matches either of two values representing completion | |
| 104 | − * of the GuC boot process. | |
| 105 | − * | |
| 106 | − * This is used for polling the GuC status in a wait_for() | |
| 107 | − * loop below. | |
| 108 | − */ | |
| 109 | −static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, | |
| 110 | − u32 *status) | |
| 100 | +static void guc_prepare_xfer(struct intel_guc *guc) | |
| 111 | 101 | { |
| 112 | − u32 val = I915_READ(GUC_STATUS); | |
| 113 | − u32 uk_val = val & GS_UKERNEL_MASK; | |
| 114 | − *status = val; | |
| 115 | − return (uk_val == GS_UKERNEL_READY || | |
| 116 | − ((val & GS_MIA_CORE_STATE) && uk_val == GS_UKERNEL_LAPIC_DONE)); | |
| 102 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 103 | + | |
| 104 | + /* Must program this register before loading the ucode with DMA */ | |
| 105 | + I915_WRITE(GUC_SHIM_CONTROL, GUC_DISABLE_SRAM_INIT_TO_ZEROES | | |
| 106 | + GUC_ENABLE_READ_CACHE_LOGIC | | |
| 107 | + GUC_ENABLE_MIA_CACHING | | |
| 108 | + GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA | | |
| 109 | + GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | | |
| 110 | + GUC_ENABLE_MIA_CLOCK_GATING); | |
| 111 | + | |
| 112 | + if (IS_GEN9_LP(dev_priv)) | |
| 113 | + I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | |
| 114 | + else | |
| 115 | + I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | |
| 116 | + | |
| 117 | + if (IS_GEN9(dev_priv)) { | |
| 118 | + /* DOP Clock Gating Enable for GuC clocks */ | |
| 119 | + I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | | |
| 120 | + I915_READ(GEN7_MISCCPCTL))); | |
| 121 | + | |
| 122 | + /* allows for 5us (in 10ns units) before GT can go to RC6 */ | |
| 123 | + I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); | |
| 124 | + } | |
| 125 | +} | |
| 126 | + | |
| 127 | +/* Copy RSA signature from the fw image to HW for verification */ | |
| 128 | +static int guc_xfer_rsa(struct intel_guc *guc, struct i915_vma *vma) | |
| 129 | +{ | |
| 130 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 131 | + struct intel_uc_fw *guc_fw = &guc->fw; | |
| 132 | + struct sg_table *sg = vma->pages; | |
| 133 | + u32 rsa[UOS_RSA_SCRATCH_MAX_COUNT]; | |
| 134 | + int i; | |
| 135 | + | |
| 136 | + if (sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), | |
| 137 | + guc_fw->rsa_offset) != sizeof(rsa)) | |
| 138 | + return -EINVAL; | |
| 139 | + | |
| 140 | + for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++) | |
| 141 | + I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]); | |
| 142 | + | |
| 143 | + return 0; | |
| 117 | 144 | } |
| 118 | 145 | |
| 119 | 146 | /* |
| @@ -122,29 +149,19 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 122 | 149 | * Architecturally, the DMA engine is bidirectional, and can potentially even |
| 123 | 150 | * transfer between GTT locations. This functionality is left out of the API |
| 124 | 151 | * for now as there is no need for it. |
| 125 | − * | |
| 126 | − * Note that GuC needs the CSS header plus uKernel code to be copied by the | |
| 127 | − * DMA engine in one operation, whereas the RSA signature is loaded via MMIO. | |
| 128 | 152 | */ |
| 129 | −static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv, | |
| 130 | − struct i915_vma *vma) | |
| 153 | +static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma) | |
| 131 | 154 | { |
| 132 | − struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; | |
| 155 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 156 | + struct intel_uc_fw *guc_fw = &guc->fw; | |
| 133 | 157 | unsigned long offset; |
| 134 | − struct sg_table *sg = vma->pages; | |
| 135 | − u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT]; | |
| 136 | − int i, ret = 0; | |
| 137 | − | |
| 138 | − /* where RSA signature starts */ | |
| 139 | − offset = guc_fw->rsa_offset; | |
| 140 | − | |
| 141 | − /* Copy RSA signature from the fw image to HW for verification */ | |
| 142 | − sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), offset); | |
| 143 | − for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++) | |
| 144 | − I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]); | |
| 158 | + u32 status; | |
| 159 | + int ret; | |
| 145 | 160 | |
| 146 | − /* The header plus uCode will be copied to WOPCM via DMA, excluding any | |
| 147 | − * other components */ | |
| 161 | + /* | |
| 162 | + * The header plus uCode will be copied to WOPCM via DMA, excluding any | |
| 163 | + * other components | |
| 164 | + */ | |
| 148 | 165 | I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size); |
| 149 | 166 | |
| 150 | 167 | /* Set the source address for the new blob */ |
| @@ -162,33 +179,62 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv, · 11 unmodified lines | ||
| 162 | 179 | /* Finally start the DMA */ |
| 163 | 180 | I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA)); |
| 164 | 181 | |
| 182 | + /* Wait for DMA to finish */ | |
| 183 | + ret = __intel_wait_for_register_fw(dev_priv, DMA_CTRL, START_DMA, 0, | |
| 184 | + 2, 100, &status); | |
| 185 | + DRM_DEBUG_DRIVER("GuC DMA status %#x\n", status); | |
| 186 | + | |
| 187 | + return ret; | |
| 188 | +} | |
| 189 | + | |
| 190 | +/* | |
| 191 | + * Read the GuC status register (GUC_STATUS) and store it in the | |
| 192 | + * specified location; then return a boolean indicating whether | |
| 193 | + * the value matches either of two values representing completion | |
| 194 | + * of the GuC boot process. | |
| 195 | + * | |
| 196 | + * This is used for polling the GuC status in a wait_for() | |
| 197 | + * loop below. | |
| 198 | + */ | |
| 199 | +static inline bool guc_ready(struct intel_guc *guc, u32 *status) | |
| 200 | +{ | |
| 201 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 202 | + u32 val = I915_READ(GUC_STATUS); | |
| 203 | + u32 uk_val = val & GS_UKERNEL_MASK; | |
| 204 | + | |
| 205 | + *status = val; | |
| 206 | + return (uk_val == GS_UKERNEL_READY) || | |
| 207 | + ((val & GS_MIA_CORE_STATE) && (uk_val == GS_UKERNEL_LAPIC_DONE)); | |
| 208 | +} | |
| 209 | + | |
| 210 | +static int guc_wait_ucode(struct intel_guc *guc) | |
| 211 | +{ | |
| 212 | + u32 status; | |
| 213 | + int ret; | |
| 214 | + | |
| 165 | 215 | /* |
| 166 | − * Wait for the DMA to complete & the GuC to start up. | |
| 216 | + * Wait for the GuC to start up. | |
| 167 | 217 | * NB: Docs recommend not using the interrupt for completion. |
| 168 | 218 | * Measurements indicate this should take no more than 20ms, so a |
| 169 | 219 | * timeout here indicates that the GuC has failed and is unusable. |
| 170 | 220 | * (Higher levels of the driver will attempt to fall back to |
| 171 | 221 | * execlist mode if this happens.) |
| 172 | 222 | */ |
| 173 | − ret = wait_for(guc_ucode_response(dev_priv, &status), 100); | |
| 174 | − | |
| 175 | − DRM_DEBUG_DRIVER("DMA status 0x%x, GuC status 0x%x\n", | |
| 176 | − I915_READ(DMA_CTRL), status); | |
| 223 | + ret = wait_for(guc_ready(guc, &status), 100); | |
| 224 | + DRM_DEBUG_DRIVER("GuC status %#x\n", status); | |
| 177 | 225 | |
| 178 | 226 | if ((status & GS_BOOTROM_MASK) == GS_BOOTROM_RSA_FAILED) { |
| 179 | 227 | DRM_ERROR("GuC firmware signature verification failed\n"); |
| 180 | 228 | ret = -ENOEXEC; |
| 181 | 229 | } |
| 182 | 230 | |
| 183 | − DRM_DEBUG_DRIVER("returning %d\n", ret); | |
| 184 | − | |
| 185 | 231 | return ret; |
| 186 | 232 | } |
| 187 | 233 | |
| 188 | 234 | /* |
| 189 | 235 | * Load the GuC firmware blob into the MinuteIA. |
| 190 | 236 | */ |
| 191 | −static int guc_ucode_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) | |
| 237 | +static int guc_fw_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) | |
| 192 | 238 | { |
| 193 | 239 | struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw); |
| 194 | 240 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| @@ -198,34 +244,24 @@ static int guc_ucode_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) · 3 unmodified lines | ||
| 198 | 244 | |
| 199 | 245 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
| 200 | 246 | |
| 201 | − /* Enable MIA caching. GuC clock gating is disabled. */ | |
| 202 | − I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); | |
| 247 | + guc_prepare_xfer(guc); | |
| 203 | 248 | |
| 204 | − /* WaDisableMinuteIaClockGating:bxt */ | |
| 205 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | |
| 206 | − I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & | |
| 207 | − ~GUC_ENABLE_MIA_CLOCK_GATING)); | |
| 208 | − } | |
| 209 | − | |
| 210 | − /* WaC6DisallowByGfxPause:bxt */ | |
| 211 | − if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) | |
| 212 | − I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); | |
| 213 | − | |
| 214 | − if (IS_GEN9_LP(dev_priv)) | |
| 215 | − I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | |
| 216 | − else | |
| 217 | − I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | |
| 218 | − | |
| 219 | − if (IS_GEN9(dev_priv)) { | |
| 220 | − /* DOP Clock Gating Enable for GuC clocks */ | |
| 221 | − I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | | |
| 222 | − I915_READ(GEN7_MISCCPCTL))); | |
| 249 | + /* | |
| 250 | + * Note that GuC needs the CSS header plus uKernel code to be copied | |
| 251 | + * by the DMA engine in one operation, whereas the RSA signature is | |
| 252 | + * loaded via MMIO. | |
| 253 | + */ | |
| 254 | + ret = guc_xfer_rsa(guc, vma); | |
| 255 | + if (ret) | |
| 256 | + DRM_WARN("GuC firmware signature xfer error %d\n", ret); | |
| 223 | 257 | |
| 224 | − /* allows for 5us (in 10ns units) before GT can go to RC6 */ | |
| 225 | − I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); | |
| 226 | − } | |
| 258 | + ret = guc_xfer_ucode(guc, vma); | |
| 259 | + if (ret) | |
| 260 | + DRM_WARN("GuC firmware code xfer error %d\n", ret); | |
| 227 | 261 | |
| 228 | − ret = guc_ucode_xfer_dma(dev_priv, vma); | |
| 262 | + ret = guc_wait_ucode(guc); | |
| 263 | + if (ret) | |
| 264 | + DRM_ERROR("GuC firmware xfer error %d\n", ret); | |
| 229 | 265 | |
| 230 | 266 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
| 231 | 267 | |
| @@ -247,5 +283,5 @@ static int guc_ucode_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) · 15 unmodified lines | ||
| 247 | 283 | */ |
| 248 | 284 | int intel_guc_fw_upload(struct intel_guc *guc) |
| 249 | 285 | { |
| 250 | − return intel_uc_fw_upload(&guc->fw, guc_ucode_xfer); | |
| 286 | + return intel_uc_fw_upload(&guc->fw, guc_fw_xfer); | |
| 251 | 287 | } |
| @@ -544,9 +544,37 @@ union guc_log_control { · 543 unmodified lines | ||
| 544 | 544 | u32 value; |
| 545 | 545 | } __packed; |
| 546 | 546 | |
| 547 | +struct guc_ctx_report { | |
| 548 | + u32 report_return_status; | |
| 549 | + u32 reserved1[64]; | |
| 550 | + u32 affected_count; | |
| 551 | + u32 reserved2[2]; | |
| 552 | +} __packed; | |
| 553 | + | |
| 554 | +/* GuC Shared Context Data Struct */ | |
| 555 | +struct guc_shared_ctx_data { | |
| 556 | + u32 addr_of_last_preempted_data_low; | |
| 557 | + u32 addr_of_last_preempted_data_high; | |
| 558 | + u32 addr_of_last_preempted_data_high_tmp; | |
| 559 | + u32 padding; | |
| 560 | + u32 is_mapped_to_proxy; | |
| 561 | + u32 proxy_ctx_id; | |
| 562 | + u32 engine_reset_ctx_id; | |
| 563 | + u32 media_reset_count; | |
| 564 | + u32 reserved1[8]; | |
| 565 | + u32 uk_last_ctx_switch_reason; | |
| 566 | + u32 was_reset; | |
| 567 | + u32 lrca_gpu_addr; | |
| 568 | + u64 execlist_ctx; | |
| 569 | + u32 reserved2[66]; | |
| 570 | + struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM]; | |
| 571 | +} __packed; | |
| 572 | + | |
| 547 | 573 | /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */ |
| 548 | 574 | enum intel_guc_action { |
| 549 | 575 | INTEL_GUC_ACTION_DEFAULT = 0x0, |
| 576 | + INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2, | |
| 577 | + INTEL_GUC_ACTION_REQUEST_ENGINE_RESET = 0x3, | |
| 550 | 578 | INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x6, |
| 551 | 579 | INTEL_GUC_ACTION_ALLOCATE_DOORBELL = 0x10, |
| 552 | 580 | INTEL_GUC_ACTION_DEALLOCATE_DOORBELL = 0x20, |
| @@ -562,6 +590,18 @@ enum intel_guc_action { · 9 unmodified lines | ||
| 562 | 590 | INTEL_GUC_ACTION_LIMIT |
| 563 | 591 | }; |
| 564 | 592 | |
| 593 | +enum intel_guc_preempt_options { | |
| 594 | + INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4, | |
| 595 | + INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8, | |
| 596 | +}; | |
| 597 | + | |
| 598 | +enum intel_guc_report_status { | |
| 599 | + INTEL_GUC_REPORT_STATUS_UNKNOWN = 0x0, | |
| 600 | + INTEL_GUC_REPORT_STATUS_ACKED = 0x1, | |
| 601 | + INTEL_GUC_REPORT_STATUS_ERROR = 0x2, | |
| 602 | + INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4, | |
| 603 | +}; | |
| 604 | + | |
| 565 | 605 | /* |
| 566 | 606 | * The GuC sends its response to a command by overwriting the |
| 567 | 607 | * command in SS0. The response is distinguishable from a command |
| @@ -25,23 +25,24 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/circ_buf.h> |
| 26 | 26 | #include <trace/events/dma_fence.h> |
| 27 | 27 | |
| 28 | −#include "i915_guc_submission.h" | |
| 28 | +#include "intel_guc_submission.h" | |
| 29 | 29 | #include "i915_drv.h" |
| 30 | 30 | |
| 31 | 31 | /** |
| 32 | 32 | * DOC: GuC-based command submission |
| 33 | 33 | * |
| 34 | 34 | * GuC client: |
| 35 | − * A i915_guc_client refers to a submission path through GuC. Currently, there | |
| 36 | − * is only one of these (the execbuf_client) and this one is charged with all | |
| 37 | − * submissions to the GuC. This struct is the owner of a doorbell, a process | |
| 38 | − * descriptor and a workqueue (all of them inside a single gem object that | |
| 39 | − * contains all required pages for these elements). | |
| 35 | + * A intel_guc_client refers to a submission path through GuC. Currently, there | |
| 36 | + * are two clients. One of them (the execbuf_client) is charged with all | |
| 37 | + * submissions to the GuC, the other one (preempt_client) is responsible for | |
| 38 | + * preempting the execbuf_client. This struct is the owner of a doorbell, a | |
| 39 | + * process descriptor and a workqueue (all of them inside a single gem object | |
| 40 | + * that contains all required pages for these elements). | |
| 40 | 41 | * |
| 41 | 42 | * GuC stage descriptor: |
| 42 | 43 | * During initialization, the driver allocates a static pool of 1024 such |
| 43 | 44 | * descriptors, and shares them with the GuC. |
| 44 | − * Currently, there exists a 1:1 mapping between a i915_guc_client and a | |
| 45 | + * Currently, there exists a 1:1 mapping between a intel_guc_client and a | |
| 45 | 46 | * guc_stage_desc (via the client's stage_id), so effectively only one |
| 46 | 47 | * gets used. This stage descriptor lets the GuC know about the doorbell, |
| 47 | 48 | * workqueue and process descriptor. Theoretically, it also lets the GuC |
| @@ -70,7 +71,7 @@ · 22 unmodified lines | ||
| 70 | 71 | * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which |
| 71 | 72 | * represents in-order queue. The kernel driver packs ring tail pointer and an |
| 72 | 73 | * ELSP context descriptor dword into Work Item. |
| 73 | − * See guc_wq_item_append() | |
| 74 | + * See guc_add_request() | |
| 74 | 75 | * |
| 75 | 76 | * ADS: |
| 76 | 77 | * The Additional Data Struct (ADS) has pointers for different buffers used by |
| @@ -81,12 +82,13 @@ · 4 unmodified lines | ||
| 81 | 82 | * |
| 82 | 83 | */ |
| 83 | 84 | |
| 84 | −static inline bool is_high_priority(struct i915_guc_client* client) | |
| 85 | +static inline bool is_high_priority(struct intel_guc_client *client) | |
| 85 | 86 | { |
| 86 | − return client->priority <= GUC_CLIENT_PRIORITY_HIGH; | |
| 87 | + return (client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH || | |
| 88 | + client->priority == GUC_CLIENT_PRIORITY_HIGH); | |
| 87 | 89 | } |
| 88 | 90 | |
| 89 | −static int __reserve_doorbell(struct i915_guc_client *client) | |
| 91 | +static int __reserve_doorbell(struct intel_guc_client *client) | |
| 90 | 92 | { |
| 91 | 93 | unsigned long offset; |
| 92 | 94 | unsigned long end; |
| @@ -100,7 +102,7 @@ static int __reserve_doorbell(struct i915_guc_client *client) · 7 unmodified lines | ||
| 100 | 102 | * priority contexts, the second half for high-priority ones. |
| 101 | 103 | */ |
| 102 | 104 | offset = 0; |
| 103 | − end = GUC_NUM_DOORBELLS/2; | |
| 105 | + end = GUC_NUM_DOORBELLS / 2; | |
| 104 | 106 | if (is_high_priority(client)) { |
| 105 | 107 | offset = end; |
| 106 | 108 | end += offset; |
| @@ -118,7 +120,7 @@ static int __reserve_doorbell(struct i915_guc_client *client) · 11 unmodified lines | ||
| 118 | 120 | return 0; |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | −static void __unreserve_doorbell(struct i915_guc_client *client) | |
| 123 | +static void __unreserve_doorbell(struct intel_guc_client *client) | |
| 122 | 124 | { |
| 123 | 125 | GEM_BUG_ON(client->doorbell_id == GUC_DOORBELL_INVALID); |
| 124 | 126 | |
| @@ -150,7 +152,7 @@ static int __guc_deallocate_doorbell(struct intel_guc *guc, u32 stage_id) · 25 unmodified lines | ||
| 150 | 152 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | −static struct guc_stage_desc *__get_stage_desc(struct i915_guc_client *client) | |
| 155 | +static struct guc_stage_desc *__get_stage_desc(struct intel_guc_client *client) | |
| 154 | 156 | { |
| 155 | 157 | struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; |
| 156 | 158 | |
| @@ -164,7 +166,7 @@ static struct guc_stage_desc *__get_stage_desc(struct i915_guc_client *client) · 7 unmodified lines | ||
| 164 | 166 | * client object which contains the page being used for the doorbell |
| 165 | 167 | */ |
| 166 | 168 | |
| 167 | −static void __update_doorbell_desc(struct i915_guc_client *client, u16 new_id) | |
| 169 | +static void __update_doorbell_desc(struct intel_guc_client *client, u16 new_id) | |
| 168 | 170 | { |
| 169 | 171 | struct guc_stage_desc *desc; |
| 170 | 172 | |
| @@ -173,12 +175,12 @@ static void __update_doorbell_desc(struct i915_guc_client *client, u16 new_id) · 2 unmodified lines | ||
| 173 | 175 | desc->db_id = new_id; |
| 174 | 176 | } |
| 175 | 177 | |
| 176 | −static struct guc_doorbell_info *__get_doorbell(struct i915_guc_client *client) | |
| 178 | +static struct guc_doorbell_info *__get_doorbell(struct intel_guc_client *client) | |
| 177 | 179 | { |
| 178 | 180 | return client->vaddr + client->doorbell_offset; |
| 179 | 181 | } |
| 180 | 182 | |
| 181 | −static bool has_doorbell(struct i915_guc_client *client) | |
| 183 | +static bool has_doorbell(struct intel_guc_client *client) | |
| 182 | 184 | { |
| 183 | 185 | if (client->doorbell_id == GUC_DOORBELL_INVALID) |
| 184 | 186 | return false; |
| @@ -186,7 +188,7 @@ static bool has_doorbell(struct i915_guc_client *client) · 1 unmodified line | ||
| 186 | 188 | return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); |
| 187 | 189 | } |
| 188 | 190 | |
| 189 | −static int __create_doorbell(struct i915_guc_client *client) | |
| 191 | +static int __create_doorbell(struct intel_guc_client *client) | |
| 190 | 192 | { |
| 191 | 193 | struct guc_doorbell_info *doorbell; |
| 192 | 194 | int err; |
| @@ -196,13 +198,16 @@ static int __create_doorbell(struct i915_guc_client *client) · 3 unmodified lines | ||
| 196 | 198 | doorbell->cookie = 0; |
| 197 | 199 | |
| 198 | 200 | err = __guc_allocate_doorbell(client->guc, client->stage_id); |
| 199 | − if (err) | |
| 201 | + if (err) { | |
| 200 | 202 | doorbell->db_status = GUC_DOORBELL_DISABLED; |
| 203 | + DRM_ERROR("Couldn't create client %u doorbell: %d\n", | |
| 204 | + client->stage_id, err); | |
| 205 | + } | |
| 201 | 206 | |
| 202 | 207 | return err; |
| 203 | 208 | } |
| 204 | 209 | |
| 205 | −static int __destroy_doorbell(struct i915_guc_client *client) | |
| 210 | +static int __destroy_doorbell(struct intel_guc_client *client) | |
| 206 | 211 | { |
| 207 | 212 | struct drm_i915_private *dev_priv = guc_to_i915(client->guc); |
| 208 | 213 | struct guc_doorbell_info *doorbell; |
| @@ -216,14 +221,15 @@ static int __destroy_doorbell(struct i915_guc_client *client) · 7 unmodified lines | ||
| 216 | 221 | |
| 217 | 222 | /* Doorbell release flow requires that we wait for GEN8_DRB_VALID bit |
| 218 | 223 | * to go to zero after updating db_status before we call the GuC to |
| 219 | − * release the doorbell */ | |
| 224 | + * release the doorbell | |
| 225 | + */ | |
| 220 | 226 | if (wait_for_us(!(I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID), 10)) |
| 221 | 227 | WARN_ONCE(true, "Doorbell never became invalid after disable\n"); |
| 222 | 228 | |
| 223 | 229 | return __guc_deallocate_doorbell(client->guc, client->stage_id); |
| 224 | 230 | } |
| 225 | 231 | |
| 226 | −static int create_doorbell(struct i915_guc_client *client) | |
| 232 | +static int create_doorbell(struct intel_guc_client *client) | |
| 227 | 233 | { |
| 228 | 234 | int ret; |
| 229 | 235 | |
| @@ -245,7 +251,7 @@ err: · 15 unmodified lines | ||
| 245 | 251 | return ret; |
| 246 | 252 | } |
| 247 | 253 | |
| 248 | −static int destroy_doorbell(struct i915_guc_client *client) | |
| 254 | +static int destroy_doorbell(struct intel_guc_client *client) | |
| 249 | 255 | { |
| 250 | 256 | int err; |
| 251 | 257 | |
| @@ -265,7 +271,7 @@ static int destroy_doorbell(struct i915_guc_client *client) · 13 unmodified lines | ||
| 265 | 271 | return 0; |
| 266 | 272 | } |
| 267 | 273 | |
| 268 | −static unsigned long __select_cacheline(struct intel_guc* guc) | |
| 274 | +static unsigned long __select_cacheline(struct intel_guc *guc) | |
| 269 | 275 | { |
| 270 | 276 | unsigned long offset; |
| 271 | 277 | |
| @@ -276,12 +282,12 @@ static unsigned long __select_cacheline(struct intel_guc* guc) · 4 unmodified lines | ||
| 276 | 282 | guc->db_cacheline += cache_line_size(); |
| 277 | 283 | |
| 278 | 284 | DRM_DEBUG_DRIVER("reserved cacheline 0x%lx, next 0x%x, linesize %u\n", |
| 279 | − offset, guc->db_cacheline, cache_line_size()); | |
| 285 | + offset, guc->db_cacheline, cache_line_size()); | |
| 280 | 286 | return offset; |
| 281 | 287 | } |
| 282 | 288 | |
| 283 | 289 | static inline struct guc_process_desc * |
| 284 | −__get_process_desc(struct i915_guc_client *client) | |
| 290 | +__get_process_desc(struct intel_guc_client *client) | |
| 285 | 291 | { |
| 286 | 292 | return client->vaddr + client->proc_desc_offset; |
| 287 | 293 | } |
| @@ -290,7 +296,7 @@ __get_process_desc(struct i915_guc_client *client) · 2 unmodified lines | ||
| 290 | 296 | * Initialise the process descriptor shared with the GuC firmware. |
| 291 | 297 | */ |
| 292 | 298 | static void guc_proc_desc_init(struct intel_guc *guc, |
| 293 | − struct i915_guc_client *client) | |
| 299 | + struct intel_guc_client *client) | |
| 294 | 300 | { |
| 295 | 301 | struct guc_process_desc *desc; |
| 296 | 302 | |
| @@ -311,6 +317,37 @@ static void guc_proc_desc_init(struct intel_guc *guc, · 14 unmodified lines | ||
| 311 | 317 | desc->priority = client->priority; |
| 312 | 318 | } |
| 313 | 319 | |
| 320 | +static int guc_stage_desc_pool_create(struct intel_guc *guc) | |
| 321 | +{ | |
| 322 | + struct i915_vma *vma; | |
| 323 | + void *vaddr; | |
| 324 | + | |
| 325 | + vma = intel_guc_allocate_vma(guc, | |
| 326 | + PAGE_ALIGN(sizeof(struct guc_stage_desc) * | |
| 327 | + GUC_MAX_STAGE_DESCRIPTORS)); | |
| 328 | + if (IS_ERR(vma)) | |
| 329 | + return PTR_ERR(vma); | |
| 330 | + | |
| 331 | + vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); | |
| 332 | + if (IS_ERR(vaddr)) { | |
| 333 | + i915_vma_unpin_and_release(&vma); | |
| 334 | + return PTR_ERR(vaddr); | |
| 335 | + } | |
| 336 | + | |
| 337 | + guc->stage_desc_pool = vma; | |
| 338 | + guc->stage_desc_pool_vaddr = vaddr; | |
| 339 | + ida_init(&guc->stage_ids); | |
| 340 | + | |
| 341 | + return 0; | |
| 342 | +} | |
| 343 | + | |
| 344 | +static void guc_stage_desc_pool_destroy(struct intel_guc *guc) | |
| 345 | +{ | |
| 346 | + ida_destroy(&guc->stage_ids); | |
| 347 | + i915_gem_object_unpin_map(guc->stage_desc_pool->obj); | |
| 348 | + i915_vma_unpin_and_release(&guc->stage_desc_pool); | |
| 349 | +} | |
| 350 | + | |
| 314 | 351 | /* |
| 315 | 352 | * Initialise/clear the stage descriptor shared with the GuC firmware. |
| 316 | 353 | * |
| @@ -319,7 +356,7 @@ static void guc_proc_desc_init(struct intel_guc *guc, · 2 unmodified lines | ||
| 319 | 356 | * write queue, etc). |
| 320 | 357 | */ |
| 321 | 358 | static void guc_stage_desc_init(struct intel_guc *guc, |
| 322 | − struct i915_guc_client *client) | |
| 359 | + struct intel_guc_client *client) | |
| 323 | 360 | { |
| 324 | 361 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
| 325 | 362 | struct intel_engine_cs *engine; |
| @@ -331,7 +368,10 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 5 unmodified lines | ||
| 331 | 368 | desc = __get_stage_desc(client); |
| 332 | 369 | memset(desc, 0, sizeof(*desc)); |
| 333 | 370 | |
| 334 | − desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL; | |
| 371 | + desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | | |
| 372 | + GUC_STAGE_DESC_ATTR_KERNEL; | |
| 373 | + if (is_high_priority(client)) | |
| 374 | + desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT; | |
| 335 | 375 | desc->stage_id = client->stage_id; |
| 336 | 376 | desc->priority = client->priority; |
| 337 | 377 | desc->db_id = client->doorbell_id; |
| @@ -356,7 +396,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 18 unmodified lines | ||
| 356 | 396 | * submission or, in other words, not using a direct submission |
| 357 | 397 | * model) the KMD's LRCA is not used for any work submission. |
| 358 | 398 | * Instead, the GuC uses the LRCA of the user mode context (see |
| 359 | − * guc_wq_item_append below). | |
| 399 | + * guc_add_request below). | |
| 360 | 400 | */ |
| 361 | 401 | lrc->context_desc = lower_32_bits(ce->lrc_desc); |
| 362 | 402 | |
| @@ -365,7 +405,8 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 2 unmodified lines | ||
| 365 | 405 | guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; |
| 366 | 406 | |
| 367 | 407 | /* XXX: In direct submission, the GuC wants the HW context id |
| 368 | − * here. In proxy submission, it wants the stage id */ | |
| 408 | + * here. In proxy submission, it wants the stage id | |
| 409 | + */ | |
| 369 | 410 | lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | |
| 370 | 411 | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); |
| 371 | 412 | |
| @@ -378,7 +419,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 6 unmodified lines | ||
| 378 | 419 | } |
| 379 | 420 | |
| 380 | 421 | DRM_DEBUG_DRIVER("Host engines 0x%x => GuC engines used 0x%x\n", |
| 381 | − client->engines, desc->engines_used); | |
| 422 | + client->engines, desc->engines_used); | |
| 382 | 423 | WARN_ON(desc->engines_used == 0); |
| 383 | 424 | |
| 384 | 425 | /* |
| @@ -398,7 +439,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, · 13 unmodified lines | ||
| 398 | 439 | } |
| 399 | 440 | |
| 400 | 441 | static void guc_stage_desc_fini(struct intel_guc *guc, |
| 401 | − struct i915_guc_client *client) | |
| 442 | + struct intel_guc_client *client) | |
| 402 | 443 | { |
| 403 | 444 | struct guc_stage_desc *desc; |
| 404 | 445 | |
| @@ -406,24 +447,47 @@ static void guc_stage_desc_fini(struct intel_guc *guc, · 1 unmodified line | ||
| 406 | 447 | memset(desc, 0, sizeof(*desc)); |
| 407 | 448 | } |
| 408 | 449 | |
| 450 | +static int guc_shared_data_create(struct intel_guc *guc) | |
| 451 | +{ | |
| 452 | + struct i915_vma *vma; | |
| 453 | + void *vaddr; | |
| 454 | + | |
| 455 | + vma = intel_guc_allocate_vma(guc, PAGE_SIZE); | |
| 456 | + if (IS_ERR(vma)) | |
| 457 | + return PTR_ERR(vma); | |
| 458 | + | |
| 459 | + vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); | |
| 460 | + if (IS_ERR(vaddr)) { | |
| 461 | + i915_vma_unpin_and_release(&vma); | |
| 462 | + return PTR_ERR(vaddr); | |
| 463 | + } | |
| 464 | + | |
| 465 | + guc->shared_data = vma; | |
| 466 | + guc->shared_data_vaddr = vaddr; | |
| 467 | + | |
| 468 | + return 0; | |
| 469 | +} | |
| 470 | + | |
| 471 | +static void guc_shared_data_destroy(struct intel_guc *guc) | |
| 472 | +{ | |
| 473 | + i915_gem_object_unpin_map(guc->shared_data->obj); | |
| 474 | + i915_vma_unpin_and_release(&guc->shared_data); | |
| 475 | +} | |
| 476 | + | |
| 409 | 477 | /* Construct a Work Item and append it to the GuC's Work Queue */ |
| 410 | −static void guc_wq_item_append(struct i915_guc_client *client, | |
| 411 | − struct drm_i915_gem_request *rq) | |
| 478 | +static void guc_wq_item_append(struct intel_guc_client *client, | |
| 479 | + u32 target_engine, u32 context_desc, | |
| 480 | + u32 ring_tail, u32 fence_id) | |
| 412 | 481 | { |
| 413 | 482 | /* wqi_len is in DWords, and does not include the one-word header */ |
| 414 | 483 | const size_t wqi_size = sizeof(struct guc_wq_item); |
| 415 | 484 | const u32 wqi_len = wqi_size / sizeof(u32) - 1; |
| 416 | − struct intel_engine_cs *engine = rq->engine; | |
| 417 | − struct i915_gem_context *ctx = rq->ctx; | |
| 418 | 485 | struct guc_process_desc *desc = __get_process_desc(client); |
| 419 | 486 | struct guc_wq_item *wqi; |
| 420 | − u32 ring_tail, wq_off; | |
| 487 | + u32 wq_off; | |
| 421 | 488 | |
| 422 | 489 | lockdep_assert_held(&client->wq_lock); |
| 423 | 490 | |
| 424 | − ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); | |
| 425 | − GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); | |
| 426 | − | |
| 427 | 491 | /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we |
| 428 | 492 | * should not have the case where structure wqi is across page, neither |
| 429 | 493 | * wrapped to the beginning. This simplifies the implementation below. |
| @@ -445,19 +509,18 @@ static void guc_wq_item_append(struct i915_guc_client *client, · 15 unmodified lines | ||
| 445 | 509 | /* Now fill in the 4-word work queue item */ |
| 446 | 510 | wqi->header = WQ_TYPE_INORDER | |
| 447 | 511 | (wqi_len << WQ_LEN_SHIFT) | |
| 448 | − (engine->guc_id << WQ_TARGET_SHIFT) | | |
| 512 | + (target_engine << WQ_TARGET_SHIFT) | | |
| 449 | 513 | WQ_NO_WCFLUSH_WAIT; |
| 450 | − | |
| 451 | − wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine)); | |
| 452 | − | |
| 514 | + wqi->context_desc = context_desc; | |
| 453 | 515 | wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; |
| 454 | − wqi->fence_id = rq->global_seqno; | |
| 516 | + GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); | |
| 517 | + wqi->fence_id = fence_id; | |
| 455 | 518 | |
| 456 | − /* Postincrement WQ tail for next time. */ | |
| 519 | + /* Make the update visible to GuC */ | |
| 457 | 520 | WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1)); |
| 458 | 521 | } |
| 459 | 522 | |
| 460 | −static void guc_reset_wq(struct i915_guc_client *client) | |
| 523 | +static void guc_reset_wq(struct intel_guc_client *client) | |
| 461 | 524 | { |
| 462 | 525 | struct guc_process_desc *desc = __get_process_desc(client); |
| 463 | 526 | |
| @@ -465,7 +528,7 @@ static void guc_reset_wq(struct i915_guc_client *client) · 1 unmodified line | ||
| 465 | 528 | desc->tail = 0; |
| 466 | 529 | } |
| 467 | 530 | |
| 468 | −static void guc_ring_doorbell(struct i915_guc_client *client) | |
| 531 | +static void guc_ring_doorbell(struct intel_guc_client *client) | |
| 469 | 532 | { |
| 470 | 533 | struct guc_doorbell_info *db; |
| 471 | 534 | u32 cookie; |
| @@ -475,29 +538,166 @@ static void guc_ring_doorbell(struct i915_guc_client *client) · 3 unmodified lines | ||
| 475 | 538 | /* pointer of current doorbell cacheline */ |
| 476 | 539 | db = __get_doorbell(client); |
| 477 | 540 | |
| 478 | − /* we're not expecting the doorbell cookie to change behind our back */ | |
| 541 | + /* | |
| 542 | + * We're not expecting the doorbell cookie to change behind our back, | |
| 543 | + * we also need to treat 0 as a reserved value. | |
| 544 | + */ | |
| 479 | 545 | cookie = READ_ONCE(db->cookie); |
| 480 | − WARN_ON_ONCE(xchg(&db->cookie, cookie + 1) != cookie); | |
| 546 | + WARN_ON_ONCE(xchg(&db->cookie, cookie + 1 ?: cookie + 2) != cookie); | |
| 481 | 547 | |
| 482 | 548 | /* XXX: doorbell was lost and need to acquire it again */ |
| 483 | 549 | GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED); |
| 484 | 550 | } |
| 485 | 551 | |
| 552 | +static void guc_add_request(struct intel_guc *guc, | |
| 553 | + struct drm_i915_gem_request *rq) | |
| 554 | +{ | |
| 555 | + struct intel_guc_client *client = guc->execbuf_client; | |
| 556 | + struct intel_engine_cs *engine = rq->engine; | |
| 557 | + u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(rq->ctx, | |
| 558 | + engine)); | |
| 559 | + u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); | |
| 560 | + | |
| 561 | + spin_lock(&client->wq_lock); | |
| 562 | + | |
| 563 | + guc_wq_item_append(client, engine->guc_id, ctx_desc, | |
| 564 | + ring_tail, rq->global_seqno); | |
| 565 | + guc_ring_doorbell(client); | |
| 566 | + | |
| 567 | + client->submissions[engine->id] += 1; | |
| 568 | + | |
| 569 | + spin_unlock(&client->wq_lock); | |
| 570 | +} | |
| 571 | + | |
| 572 | +/* | |
| 573 | + * When we're doing submissions using regular execlists backend, writing to | |
| 574 | + * ELSP from CPU side is enough to make sure that writes to ringbuffer pages | |
| 575 | + * pinned in mappable aperture portion of GGTT are visible to command streamer. | |
| 576 | + * Writes done by GuC on our behalf are not guaranteeing such ordering, | |
| 577 | + * therefore, to ensure the flush, we're issuing a POSTING READ. | |
| 578 | + */ | |
| 579 | +static void flush_ggtt_writes(struct i915_vma *vma) | |
| 580 | +{ | |
| 581 | + struct drm_i915_private *dev_priv = to_i915(vma->obj->base.dev); | |
| 582 | + | |
| 583 | + if (i915_vma_is_map_and_fenceable(vma)) | |
| 584 | + POSTING_READ_FW(GUC_STATUS); | |
| 585 | +} | |
| 586 | + | |
| 587 | +#define GUC_PREEMPT_FINISHED 0x1 | |
| 588 | +#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8 | |
| 589 | +static void inject_preempt_context(struct work_struct *work) | |
| 590 | +{ | |
| 591 | + struct guc_preempt_work *preempt_work = | |
| 592 | + container_of(work, typeof(*preempt_work), work); | |
| 593 | + struct intel_engine_cs *engine = preempt_work->engine; | |
| 594 | + struct intel_guc *guc = container_of(preempt_work, typeof(*guc), | |
| 595 | + preempt_work[engine->id]); | |
| 596 | + struct intel_guc_client *client = guc->preempt_client; | |
| 597 | + struct guc_stage_desc *stage_desc = __get_stage_desc(client); | |
| 598 | + struct intel_ring *ring = client->owner->engine[engine->id].ring; | |
| 599 | + u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner, | |
| 600 | + engine)); | |
| 601 | + u32 *cs = ring->vaddr + ring->tail; | |
| 602 | + u32 data[7]; | |
| 603 | + | |
| 604 | + if (engine->id == RCS) { | |
| 605 | + cs = gen8_emit_ggtt_write_rcs(cs, GUC_PREEMPT_FINISHED, | |
| 606 | + intel_hws_preempt_done_address(engine)); | |
| 607 | + } else { | |
| 608 | + cs = gen8_emit_ggtt_write(cs, GUC_PREEMPT_FINISHED, | |
| 609 | + intel_hws_preempt_done_address(engine)); | |
| 610 | + *cs++ = MI_NOOP; | |
| 611 | + *cs++ = MI_NOOP; | |
| 612 | + } | |
| 613 | + *cs++ = MI_USER_INTERRUPT; | |
| 614 | + *cs++ = MI_NOOP; | |
| 615 | + | |
| 616 | + GEM_BUG_ON(!IS_ALIGNED(ring->size, | |
| 617 | + GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32))); | |
| 618 | + GEM_BUG_ON((void *)cs - (ring->vaddr + ring->tail) != | |
| 619 | + GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32)); | |
| 620 | + | |
| 621 | + ring->tail += GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32); | |
| 622 | + ring->tail &= (ring->size - 1); | |
| 623 | + | |
| 624 | + flush_ggtt_writes(ring->vma); | |
| 625 | + | |
| 626 | + spin_lock_irq(&client->wq_lock); | |
| 627 | + guc_wq_item_append(client, engine->guc_id, ctx_desc, | |
| 628 | + ring->tail / sizeof(u64), 0); | |
| 629 | + spin_unlock_irq(&client->wq_lock); | |
| 630 | + | |
| 631 | + /* | |
| 632 | + * If GuC firmware performs an engine reset while that engine had | |
| 633 | + * a preemption pending, it will set the terminated attribute bit | |
| 634 | + * on our preemption stage descriptor. GuC firmware retains all | |
| 635 | + * pending work items for a high-priority GuC client, unlike the | |
| 636 | + * normal-priority GuC client where work items are dropped. It | |
| 637 | + * wants to make sure the preempt-to-idle work doesn't run when | |
| 638 | + * scheduling resumes, and uses this bit to inform its scheduler | |
| 639 | + * and presumably us as well. Our job is to clear it for the next | |
| 640 | + * preemption after reset, otherwise that and future preemptions | |
| 641 | + * will never complete. We'll just clear it every time. | |
| 642 | + */ | |
| 643 | + stage_desc->attribute &= ~GUC_STAGE_DESC_ATTR_TERMINATED; | |
| 644 | + | |
| 645 | + data[0] = INTEL_GUC_ACTION_REQUEST_PREEMPTION; | |
| 646 | + data[1] = client->stage_id; | |
| 647 | + data[2] = INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q | | |
| 648 | + INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q; | |
| 649 | + data[3] = engine->guc_id; | |
| 650 | + data[4] = guc->execbuf_client->priority; | |
| 651 | + data[5] = guc->execbuf_client->stage_id; | |
| 652 | + data[6] = guc_ggtt_offset(guc->shared_data); | |
| 653 | + | |
| 654 | + if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { | |
| 655 | + execlists_clear_active(&engine->execlists, | |
| 656 | + EXECLISTS_ACTIVE_PREEMPT); | |
| 657 | + tasklet_schedule(&engine->execlists.tasklet); | |
| 658 | + } | |
| 659 | +} | |
| 660 | + | |
| 661 | +/* | |
| 662 | + * We're using user interrupt and HWSP value to mark that preemption has | |
| 663 | + * finished and GPU is idle. Normally, we could unwind and continue similar to | |
| 664 | + * execlists submission path. Unfortunately, with GuC we also need to wait for | |
| 665 | + * it to finish its own postprocessing, before attempting to submit. Otherwise | |
| 666 | + * GuC may silently ignore our submissions, and thus we risk losing request at | |
| 667 | + * best, executing out-of-order and causing kernel panic at worst. | |
| 668 | + */ | |
| 669 | +#define GUC_PREEMPT_POSTPROCESS_DELAY_MS 10 | |
| 670 | +static void wait_for_guc_preempt_report(struct intel_engine_cs *engine) | |
| 671 | +{ | |
| 672 | + struct intel_guc *guc = &engine->i915->guc; | |
| 673 | + struct guc_shared_ctx_data *data = guc->shared_data_vaddr; | |
| 674 | + struct guc_ctx_report *report = | |
| 675 | + &data->preempt_ctx_report[engine->guc_id]; | |
| 676 | + | |
| 677 | + WARN_ON(wait_for_atomic(report->report_return_status == | |
| 678 | + INTEL_GUC_REPORT_STATUS_COMPLETE, | |
| 679 | + GUC_PREEMPT_POSTPROCESS_DELAY_MS)); | |
| 680 | + /* | |
| 681 | + * GuC is expecting that we're also going to clear the affected context | |
| 682 | + * counter, let's also reset the return status to not depend on GuC | |
| 683 | + * resetting it after recieving another preempt action | |
| 684 | + */ | |
| 685 | + report->affected_count = 0; | |
| 686 | + report->report_return_status = INTEL_GUC_REPORT_STATUS_UNKNOWN; | |
| 687 | +} | |
| 688 | + | |
| 486 | 689 | /** |
| 487 | − * i915_guc_submit() - Submit commands through GuC | |
| 690 | + * guc_submit() - Submit commands through GuC | |
| 488 | 691 | * @engine: engine associated with the commands |
| 489 | 692 | * |
| 490 | 693 | * The only error here arises if the doorbell hardware isn't functioning |
| 491 | 694 | * as expected, which really shouln't happen. |
| 492 | 695 | */ |
| 493 | −static void i915_guc_submit(struct intel_engine_cs *engine) | |
| 696 | +static void guc_submit(struct intel_engine_cs *engine) | |
| 494 | 697 | { |
| 495 | − struct drm_i915_private *dev_priv = engine->i915; | |
| 496 | − struct intel_guc *guc = &dev_priv->guc; | |
| 497 | − struct i915_guc_client *client = guc->execbuf_client; | |
| 698 | + struct intel_guc *guc = &engine->i915->guc; | |
| 498 | 699 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 499 | 700 | struct execlist_port *port = execlists->port; |
| 500 | − const unsigned int engine_id = engine->id; | |
| 501 | 701 | unsigned int n; |
| 502 | 702 | |
| 503 | 703 | for (n = 0; n < execlists_num_ports(execlists); n++) { |
| @@ -508,44 +708,13 @@ static void i915_guc_submit(struct intel_engine_cs *engine) · 4 unmodified lines | ||
| 508 | 708 | if (rq && count == 0) { |
| 509 | 709 | port_set(&port[n], port_pack(rq, ++count)); |
| 510 | 710 | |
| 511 | − if (i915_vma_is_map_and_fenceable(rq->ring->vma)) | |
| 512 | − POSTING_READ_FW(GUC_STATUS); | |
| 513 | − | |
| 514 | − spin_lock(&client->wq_lock); | |
| 515 | − | |
| 516 | − guc_wq_item_append(client, rq); | |
| 517 | − guc_ring_doorbell(client); | |
| 711 | + flush_ggtt_writes(rq->ring->vma); | |
| 518 | 712 | |
| 519 | − client->submissions[engine_id] += 1; | |
| 520 | − | |
| 521 | − spin_unlock(&client->wq_lock); | |
| 713 | + guc_add_request(guc, rq); | |
| 522 | 714 | } |
| 523 | 715 | } |
| 524 | 716 | } |
| 525 | 717 | |
| 526 | −static void nested_enable_signaling(struct drm_i915_gem_request *rq) | |
| 527 | −{ | |
| 528 | − /* If we use dma_fence_enable_sw_signaling() directly, lockdep | |
| 529 | − * detects an ordering issue between the fence lockclass and the | |
| 530 | − * global_timeline. This circular dependency can only occur via 2 | |
| 531 | − * different fences (but same fence lockclass), so we use the nesting | |
| 532 | − * annotation here to prevent the warn, equivalent to the nesting | |
| 533 | − * inside i915_gem_request_submit() for when we also enable the | |
| 534 | − * signaler. | |
| 535 | − */ | |
| 536 | − | |
| 537 | − if (test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, | |
| 538 | − &rq->fence.flags)) | |
| 539 | − return; | |
| 540 | − | |
| 541 | − GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)); | |
| 542 | − trace_dma_fence_enable_signal(&rq->fence); | |
| 543 | − | |
| 544 | − spin_lock_nested(&rq->lock, SINGLE_DEPTH_NESTING); | |
| 545 | − intel_engine_enable_signaling(rq, true); | |
| 546 | − spin_unlock(&rq->lock); | |
| 547 | −} | |
| 548 | − | |
| 549 | 718 | static void port_assign(struct execlist_port *port, |
| 550 | 719 | struct drm_i915_gem_request *rq) |
| 551 | 720 | { |
| @@ -555,10 +724,9 @@ static void port_assign(struct execlist_port *port, · 3 unmodified lines | ||
| 555 | 724 | i915_gem_request_put(port_request(port)); |
| 556 | 725 | |
| 557 | 726 | port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); |
| 558 | − nested_enable_signaling(rq); | |
| 559 | 727 | } |
| 560 | 728 | |
| 561 | −static void i915_guc_dequeue(struct intel_engine_cs *engine) | |
| 729 | +static void guc_dequeue(struct intel_engine_cs *engine) | |
| 562 | 730 | { |
| 563 | 731 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 564 | 732 | struct execlist_port *port = execlists->port; |
| @@ -568,13 +736,32 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) · 3 unmodified lines | ||
| 568 | 736 | bool submit = false; |
| 569 | 737 | struct rb_node *rb; |
| 570 | 738 | |
| 571 | − if (port_isset(port)) | |
| 572 | − port++; | |
| 573 | − | |
| 574 | 739 | spin_lock_irq(&engine->timeline->lock); |
| 575 | 740 | rb = execlists->first; |
| 576 | 741 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
| 577 | − while (rb) { | |
| 742 | + | |
| 743 | + if (!rb) | |
| 744 | + goto unlock; | |
| 745 | + | |
| 746 | + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && port_isset(port)) { | |
| 747 | + struct guc_preempt_work *preempt_work = | |
| 748 | + &engine->i915->guc.preempt_work[engine->id]; | |
| 749 | + | |
| 750 | + if (rb_entry(rb, struct i915_priolist, node)->priority > | |
| 751 | + max(port_request(port)->priotree.priority, 0)) { | |
| 752 | + execlists_set_active(execlists, | |
| 753 | + EXECLISTS_ACTIVE_PREEMPT); | |
| 754 | + queue_work(engine->i915->guc.preempt_wq, | |
| 755 | + &preempt_work->work); | |
| 756 | + goto unlock; | |
| 757 | + } else if (port_isset(last_port)) { | |
| 758 | + goto unlock; | |
| 759 | + } | |
| 760 | + | |
| 761 | + port++; | |
| 762 | + } | |
| 763 | + | |
| 764 | + do { | |
| 578 | 765 | struct i915_priolist *p = rb_entry(rb, typeof(*p), node); |
| 579 | 766 | struct drm_i915_gem_request *rq, *rn; |
| 580 | 767 | |
| @@ -592,10 +779,10 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) · 11 unmodified lines | ||
| 592 | 779 | } |
| 593 | 780 | |
| 594 | 781 | INIT_LIST_HEAD(&rq->priotree.link); |
| 595 | − rq->priotree.priority = INT_MAX; | |
| 596 | 782 | |
| 597 | 783 | __i915_gem_request_submit(rq); |
| 598 | − trace_i915_gem_request_in(rq, port_index(port, execlists)); | |
| 784 | + trace_i915_gem_request_in(rq, | |
| 785 | + port_index(port, execlists)); | |
| 599 | 786 | last = rq; |
| 600 | 787 | submit = true; |
| 601 | 788 | } |
| @@ -605,24 +792,23 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) · 3 unmodified lines | ||
| 605 | 792 | INIT_LIST_HEAD(&p->requests); |
| 606 | 793 | if (p->priority != I915_PRIORITY_NORMAL) |
| 607 | 794 | kmem_cache_free(engine->i915->priorities, p); |
| 608 | − } | |
| 795 | + } while (rb); | |
| 609 | 796 | done: |
| 610 | 797 | execlists->first = rb; |
| 611 | 798 | if (submit) { |
| 612 | 799 | port_assign(port, last); |
| 613 | 800 | execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); |
| 614 | − i915_guc_submit(engine); | |
| 801 | + guc_submit(engine); | |
| 615 | 802 | } |
| 803 | +unlock: | |
| 616 | 804 | spin_unlock_irq(&engine->timeline->lock); |
| 617 | 805 | } |
| 618 | 806 | |
| 619 | −static void i915_guc_irq_handler(unsigned long data) | |
| 807 | +static void guc_submission_tasklet(unsigned long data) | |
| 620 | 808 | { |
| 621 | 809 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; |
| 622 | 810 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| 623 | 811 | struct execlist_port *port = execlists->port; |
| 624 | − const struct execlist_port * const last_port = | |
| 625 | − &execlists->port[execlists->port_mask]; | |
| 626 | 812 | struct drm_i915_gem_request *rq; |
| 627 | 813 | |
| 628 | 814 | rq = port_request(&port[0]); |
| @@ -637,14 +823,26 @@ static void i915_guc_irq_handler(unsigned long data) · 8 unmodified lines | ||
| 637 | 823 | if (!rq) |
| 638 | 824 | execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); |
| 639 | 825 | |
| 640 | − if (!port_isset(last_port)) | |
| 641 | − i915_guc_dequeue(engine); | |
| 826 | + if (execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT) && | |
| 827 | + intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) == | |
| 828 | + GUC_PREEMPT_FINISHED) { | |
| 829 | + execlists_cancel_port_requests(&engine->execlists); | |
| 830 | + execlists_unwind_incomplete_requests(execlists); | |
| 831 | + | |
| 832 | + wait_for_guc_preempt_report(engine); | |
| 833 | + | |
| 834 | + execlists_clear_active(execlists, EXECLISTS_ACTIVE_PREEMPT); | |
| 835 | + intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0); | |
| 836 | + } | |
| 837 | + | |
| 838 | + if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT)) | |
| 839 | + guc_dequeue(engine); | |
| 642 | 840 | } |
| 643 | 841 | |
| 644 | 842 | /* |
| 645 | 843 | * Everything below here is concerned with setup & teardown, and is |
| 646 | 844 | * therefore not part of the somewhat time-critical batch-submission |
| 647 | − * path of i915_guc_submit() above. | |
| 845 | + * path of guc_submit() above. | |
| 648 | 846 | */ |
| 649 | 847 | |
| 650 | 848 | /* Check that a doorbell register is in the expected state */ |
| @@ -673,7 +871,7 @@ static bool doorbell_ok(struct intel_guc *guc, u16 db_id) · 22 unmodified lines | ||
| 673 | 871 | * reloaded the GuC FW) we can use this function to tell the GuC to reassign the |
| 674 | 872 | * doorbell to the rightful owner. |
| 675 | 873 | */ |
| 676 | −static int __reset_doorbell(struct i915_guc_client* client, u16 db_id) | |
| 874 | +static int __reset_doorbell(struct intel_guc_client *client, u16 db_id) | |
| 677 | 875 | { |
| 678 | 876 | int err; |
| 679 | 877 | |
| @@ -694,7 +892,7 @@ static int __reset_doorbell(struct i915_guc_client* client, u16 db_id) · 14 unmodified lines | ||
| 694 | 892 | */ |
| 695 | 893 | static int guc_init_doorbell_hw(struct intel_guc *guc) |
| 696 | 894 | { |
| 697 | − struct i915_guc_client *client = guc->execbuf_client; | |
| 895 | + struct intel_guc_client *client = guc->execbuf_client; | |
| 698 | 896 | bool recreate_first_client = false; |
| 699 | 897 | u16 db_id; |
| 700 | 898 | int ret; |
| @@ -717,7 +915,8 @@ static int guc_init_doorbell_hw(struct intel_guc *guc) · 16 unmodified lines | ||
| 717 | 915 | if (recreate_first_client) { |
| 718 | 916 | ret = __reserve_doorbell(client); |
| 719 | 917 | if (unlikely(ret)) { |
| 720 | − DRM_ERROR("Couldn't re-reserve first client db: %d\n", ret); | |
| 918 | + DRM_ERROR("Couldn't re-reserve first client db: %d\n", | |
| 919 | + ret); | |
| 721 | 920 | return ret; |
| 722 | 921 | } |
| 723 | 922 | |
| @@ -725,15 +924,16 @@ static int guc_init_doorbell_hw(struct intel_guc *guc) · 1 unmodified line | ||
| 725 | 924 | } |
| 726 | 925 | |
| 727 | 926 | /* Now for every client (and not only execbuf_client) make sure their |
| 728 | − * doorbells are known by the GuC */ | |
| 729 | − //for (client = client_list; client != NULL; client = client->next) | |
| 730 | − { | |
| 731 | − ret = __create_doorbell(client); | |
| 732 | − if (ret) { | |
| 733 | − DRM_ERROR("Couldn't recreate client %u doorbell: %d\n", | |
| 734 | − client->stage_id, ret); | |
| 735 | − return ret; | |
| 736 | − } | |
| 927 | + * doorbells are known by the GuC | |
| 928 | + */ | |
| 929 | + ret = __create_doorbell(guc->execbuf_client); | |
| 930 | + if (ret) | |
| 931 | + return ret; | |
| 932 | + | |
| 933 | + ret = __create_doorbell(guc->preempt_client); | |
| 934 | + if (ret) { | |
| 935 | + __destroy_doorbell(guc->execbuf_client); | |
| 936 | + return ret; | |
| 737 | 937 | } |
| 738 | 938 | |
| 739 | 939 | /* Read back & verify all (used & unused) doorbell registers */ |
| @@ -744,25 +944,25 @@ static int guc_init_doorbell_hw(struct intel_guc *guc) · 4 unmodified lines | ||
| 744 | 944 | } |
| 745 | 945 | |
| 746 | 946 | /** |
| 747 | − * guc_client_alloc() - Allocate an i915_guc_client | |
| 947 | + * guc_client_alloc() - Allocate an intel_guc_client | |
| 748 | 948 | * @dev_priv: driver private data structure |
| 749 | 949 | * @engines: The set of engines to enable for this client |
| 750 | 950 | * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW |
| 751 | − * The kernel client to replace ExecList submission is created with | |
| 752 | − * NORMAL priority. Priority of a client for scheduler can be HIGH, | |
| 753 | − * while a preemption context can use CRITICAL. | |
| 951 | + * The kernel client to replace ExecList submission is created with | |
| 952 | + * NORMAL priority. Priority of a client for scheduler can be HIGH, | |
| 953 | + * while a preemption context can use CRITICAL. | |
| 754 | 954 | * @ctx: the context that owns the client (we use the default render |
| 755 | − * context) | |
| 955 | + * context) | |
| 756 | 956 | * |
| 757 | − * Return: An i915_guc_client object if success, else NULL. | |
| 957 | + * Return: An intel_guc_client object if success, else NULL. | |
| 758 | 958 | */ |
| 759 | −static struct i915_guc_client * | |
| 959 | +static struct intel_guc_client * | |
| 760 | 960 | guc_client_alloc(struct drm_i915_private *dev_priv, |
| 761 | 961 | u32 engines, |
| 762 | 962 | u32 priority, |
| 763 | 963 | struct i915_gem_context *ctx) |
| 764 | 964 | { |
| 765 | − struct i915_guc_client *client; | |
| 965 | + struct intel_guc_client *client; | |
| 766 | 966 | struct intel_guc *guc = &dev_priv->guc; |
| 767 | 967 | struct i915_vma *vma; |
| 768 | 968 | void *vaddr; |
| @@ -780,7 +980,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv, · 11 unmodified lines | ||
| 780 | 980 | spin_lock_init(&client->wq_lock); |
| 781 | 981 | |
| 782 | 982 | ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, |
| 783 | − GFP_KERNEL); | |
| 983 | + GFP_KERNEL); | |
| 784 | 984 | if (ret < 0) |
| 785 | 985 | goto err_client; |
| 786 | 986 | |
| @@ -840,7 +1040,7 @@ err_client: · 53 unmodified lines | ||
| 840 | 1040 | return ERR_PTR(ret); |
| 841 | 1041 | } |
| 842 | 1042 | |
| 843 | −static void guc_client_free(struct i915_guc_client *client) | |
| 1043 | +static void guc_client_free(struct intel_guc_client *client) | |
| 844 | 1044 | { |
| 845 | 1045 | /* |
| 846 | 1046 | * XXX: wait for any outstanding submissions before freeing memory. |
| @@ -849,7 +1049,8 @@ static void guc_client_free(struct i915_guc_client *client) · 2 unmodified lines | ||
| 849 | 1049 | |
| 850 | 1050 | /* FIXME: in many cases, by the time we get here the GuC has been |
| 851 | 1051 | * reset, so we cannot destroy the doorbell properly. Ignore the |
| 852 | − * error message for now */ | |
| 1052 | + * error message for now | |
| 1053 | + */ | |
| 853 | 1054 | destroy_doorbell(client); |
| 854 | 1055 | guc_stage_desc_fini(client->guc, client); |
| 855 | 1056 | i915_gem_object_unpin_map(client->vma->obj); |
| @@ -858,6 +1059,50 @@ static void guc_client_free(struct i915_guc_client *client) · 2 unmodified lines | ||
| 858 | 1059 | kfree(client); |
| 859 | 1060 | } |
| 860 | 1061 | |
| 1062 | +static int guc_clients_create(struct intel_guc *guc) | |
| 1063 | +{ | |
| 1064 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 1065 | + struct intel_guc_client *client; | |
| 1066 | + | |
| 1067 | + GEM_BUG_ON(guc->execbuf_client); | |
| 1068 | + GEM_BUG_ON(guc->preempt_client); | |
| 1069 | + | |
| 1070 | + client = guc_client_alloc(dev_priv, | |
| 1071 | + INTEL_INFO(dev_priv)->ring_mask, | |
| 1072 | + GUC_CLIENT_PRIORITY_KMD_NORMAL, | |
| 1073 | + dev_priv->kernel_context); | |
| 1074 | + if (IS_ERR(client)) { | |
| 1075 | + DRM_ERROR("Failed to create GuC client for submission!\n"); | |
| 1076 | + return PTR_ERR(client); | |
| 1077 | + } | |
| 1078 | + guc->execbuf_client = client; | |
| 1079 | + | |
| 1080 | + client = guc_client_alloc(dev_priv, | |
| 1081 | + INTEL_INFO(dev_priv)->ring_mask, | |
| 1082 | + GUC_CLIENT_PRIORITY_KMD_HIGH, | |
| 1083 | + dev_priv->preempt_context); | |
| 1084 | + if (IS_ERR(client)) { | |
| 1085 | + DRM_ERROR("Failed to create GuC client for preemption!\n"); | |
| 1086 | + guc_client_free(guc->execbuf_client); | |
| 1087 | + guc->execbuf_client = NULL; | |
| 1088 | + return PTR_ERR(client); | |
| 1089 | + } | |
| 1090 | + guc->preempt_client = client; | |
| 1091 | + | |
| 1092 | + return 0; | |
| 1093 | +} | |
| 1094 | + | |
| 1095 | +static void guc_clients_destroy(struct intel_guc *guc) | |
| 1096 | +{ | |
| 1097 | + struct intel_guc_client *client; | |
| 1098 | + | |
| 1099 | + client = fetch_and_zero(&guc->execbuf_client); | |
| 1100 | + guc_client_free(client); | |
| 1101 | + | |
| 1102 | + client = fetch_and_zero(&guc->preempt_client); | |
| 1103 | + guc_client_free(client); | |
| 1104 | +} | |
| 1105 | + | |
| 861 | 1106 | static void guc_policy_init(struct guc_policy *policy) |
| 862 | 1107 | { |
| 863 | 1108 | policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US; |
| @@ -941,7 +1186,8 @@ static int guc_ads_create(struct intel_guc *guc) · 77 unmodified lines | ||
| 941 | 1186 | * because our GuC shared data is there. |
| 942 | 1187 | */ |
| 943 | 1188 | blob->ads.golden_context_lrca = |
| 944 | − guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + skipped_offset; | |
| 1189 | + guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + | |
| 1190 | + skipped_offset; | |
| 945 | 1191 | |
| 946 | 1192 | /* |
| 947 | 1193 | * The GuC expects us to exclude the portion of the context image that |
| @@ -950,7 +1196,8 @@ static int guc_ads_create(struct intel_guc *guc) · 2 unmodified lines | ||
| 950 | 1196 | * dwords). Weird guc is weird. |
| 951 | 1197 | */ |
| 952 | 1198 | for_each_engine(engine, dev_priv, id) |
| 953 | − blob->ads.eng_state_size[engine->guc_id] = engine->context_size - skipped_size; | |
| 1199 | + blob->ads.eng_state_size[engine->guc_id] = | |
| 1200 | + engine->context_size - skipped_size; | |
| 954 | 1201 | |
| 955 | 1202 | base = guc_ggtt_offset(vma); |
| 956 | 1203 | blob->ads.scheduler_policies = base + ptr_offset(blob, policies); |
| @@ -967,66 +1214,110 @@ static void guc_ads_destroy(struct intel_guc *guc) · 10 unmodified lines | ||
| 967 | 1214 | i915_vma_unpin_and_release(&guc->ads_vma); |
| 968 | 1215 | } |
| 969 | 1216 | |
| 1217 | +static int guc_preempt_work_create(struct intel_guc *guc) | |
| 1218 | +{ | |
| 1219 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 1220 | + struct intel_engine_cs *engine; | |
| 1221 | + enum intel_engine_id id; | |
| 1222 | + | |
| 1223 | + /* | |
| 1224 | + * Even though both sending GuC action, and adding a new workitem to | |
| 1225 | + * GuC workqueue are serialized (each with its own locking), since | |
| 1226 | + * we're using mutliple engines, it's possible that we're going to | |
| 1227 | + * issue a preempt request with two (or more - each for different | |
| 1228 | + * engine) workitems in GuC queue. In this situation, GuC may submit | |
| 1229 | + * all of them, which will make us very confused. | |
| 1230 | + * Our preemption contexts may even already be complete - before we | |
| 1231 | + * even had the chance to sent the preempt action to GuC!. Rather | |
| 1232 | + * than introducing yet another lock, we can just use ordered workqueue | |
| 1233 | + * to make sure we're always sending a single preemption request with a | |
| 1234 | + * single workitem. | |
| 1235 | + */ | |
| 1236 | + guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", | |
| 1237 | + WQ_HIGHPRI); | |
| 1238 | + if (!guc->preempt_wq) | |
| 1239 | + return -ENOMEM; | |
| 1240 | + | |
| 1241 | + for_each_engine(engine, dev_priv, id) { | |
| 1242 | + guc->preempt_work[id].engine = engine; | |
| 1243 | + INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context); | |
| 1244 | + } | |
| 1245 | + | |
| 1246 | + return 0; | |
| 1247 | +} | |
| 1248 | + | |
| 1249 | +static void guc_preempt_work_destroy(struct intel_guc *guc) | |
| 1250 | +{ | |
| 1251 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 1252 | + struct intel_engine_cs *engine; | |
| 1253 | + enum intel_engine_id id; | |
| 1254 | + | |
| 1255 | + for_each_engine(engine, dev_priv, id) | |
| 1256 | + cancel_work_sync(&guc->preempt_work[id].work); | |
| 1257 | + | |
| 1258 | + destroy_workqueue(guc->preempt_wq); | |
| 1259 | + guc->preempt_wq = NULL; | |
| 1260 | +} | |
| 1261 | + | |
| 970 | 1262 | /* |
| 971 | 1263 | * Set up the memory resources to be shared with the GuC (via the GGTT) |
| 972 | 1264 | * at firmware loading time. |
| 973 | 1265 | */ |
| 974 | −int i915_guc_submission_init(struct drm_i915_private *dev_priv) | |
| 1266 | +int intel_guc_submission_init(struct intel_guc *guc) | |
| 975 | 1267 | { |
| 976 | − struct intel_guc *guc = &dev_priv->guc; | |
| 977 | − struct i915_vma *vma; | |
| 978 | − void *vaddr; | |
| 979 | 1268 | int ret; |
| 980 | 1269 | |
| 981 | 1270 | if (guc->stage_desc_pool) |
| 982 | 1271 | return 0; |
| 983 | 1272 | |
| 984 | − vma = intel_guc_allocate_vma(guc, | |
| 985 | − PAGE_ALIGN(sizeof(struct guc_stage_desc) * | |
| 986 | − GUC_MAX_STAGE_DESCRIPTORS)); | |
| 987 | − if (IS_ERR(vma)) | |
| 988 | − return PTR_ERR(vma); | |
| 989 | − | |
| 990 | − guc->stage_desc_pool = vma; | |
| 991 | − | |
| 992 | − vaddr = i915_gem_object_pin_map(guc->stage_desc_pool->obj, I915_MAP_WB); | |
| 993 | − if (IS_ERR(vaddr)) { | |
| 994 | − ret = PTR_ERR(vaddr); | |
| 995 | − goto err_vma; | |
| 996 | − } | |
| 1273 | + ret = guc_stage_desc_pool_create(guc); | |
| 1274 | + if (ret) | |
| 1275 | + return ret; | |
| 1276 | + /* | |
| 1277 | + * Keep static analysers happy, let them know that we allocated the | |
| 1278 | + * vma after testing that it didn't exist earlier. | |
| 1279 | + */ | |
| 1280 | + GEM_BUG_ON(!guc->stage_desc_pool); | |
| 997 | 1281 | |
| 998 | − guc->stage_desc_pool_vaddr = vaddr; | |
| 1282 | + ret = guc_shared_data_create(guc); | |
| 1283 | + if (ret) | |
| 1284 | + goto err_stage_desc_pool; | |
| 1285 | + GEM_BUG_ON(!guc->shared_data); | |
| 999 | 1286 | |
| 1000 | 1287 | ret = intel_guc_log_create(guc); |
| 1001 | 1288 | if (ret < 0) |
| 1002 | − goto err_vaddr; | |
| 1289 | + goto err_shared_data; | |
| 1003 | 1290 | |
| 1004 | − ret = guc_ads_create(guc); | |
| 1005 | − if (ret < 0) | |
| 1291 | + ret = guc_preempt_work_create(guc); | |
| 1292 | + if (ret) | |
| 1006 | 1293 | goto err_log; |
| 1294 | + GEM_BUG_ON(!guc->preempt_wq); | |
| 1007 | 1295 | |
| 1008 | − ida_init(&guc->stage_ids); | |
| 1296 | + ret = guc_ads_create(guc); | |
| 1297 | + if (ret < 0) | |
| 1298 | + goto err_wq; | |
| 1299 | + GEM_BUG_ON(!guc->ads_vma); | |
| 1009 | 1300 | |
| 1010 | 1301 | return 0; |
| 1011 | 1302 | |
| 1303 | +err_wq: | |
| 1304 | + guc_preempt_work_destroy(guc); | |
| 1012 | 1305 | err_log: |
| 1013 | 1306 | intel_guc_log_destroy(guc); |
| 1014 | −err_vaddr: | |
| 1015 | − i915_gem_object_unpin_map(guc->stage_desc_pool->obj); | |
| 1016 | −err_vma: | |
| 1017 | − i915_vma_unpin_and_release(&guc->stage_desc_pool); | |
| 1307 | +err_shared_data: | |
| 1308 | + guc_shared_data_destroy(guc); | |
| 1309 | +err_stage_desc_pool: | |
| 1310 | + guc_stage_desc_pool_destroy(guc); | |
| 1018 | 1311 | return ret; |
| 1019 | 1312 | } |
| 1020 | 1313 | |
| 1021 | −void i915_guc_submission_fini(struct drm_i915_private *dev_priv) | |
| 1314 | +void intel_guc_submission_fini(struct intel_guc *guc) | |
| 1022 | 1315 | { |
| 1023 | − struct intel_guc *guc = &dev_priv->guc; | |
| 1024 | − | |
| 1025 | − ida_destroy(&guc->stage_ids); | |
| 1026 | 1316 | guc_ads_destroy(guc); |
| 1317 | + guc_preempt_work_destroy(guc); | |
| 1027 | 1318 | intel_guc_log_destroy(guc); |
| 1028 | − i915_gem_object_unpin_map(guc->stage_desc_pool->obj); | |
| 1029 | − i915_vma_unpin_and_release(&guc->stage_desc_pool); | |
| 1319 | + guc_shared_data_destroy(guc); | |
| 1320 | + guc_stage_desc_pool_destroy(guc); | |
| 1030 | 1321 | } |
| 1031 | 1322 | |
| 1032 | 1323 | static void guc_interrupts_capture(struct drm_i915_private *dev_priv) |
| @@ -1036,7 +1327,9 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv) · 3 unmodified lines | ||
| 1036 | 1327 | enum intel_engine_id id; |
| 1037 | 1328 | int irqs; |
| 1038 | 1329 | |
| 1039 | − /* tell all command streamers to forward interrupts (but not vblank) to GuC */ | |
| 1330 | + /* tell all command streamers to forward interrupts (but not vblank) | |
| 1331 | + * to GuC | |
| 1332 | + */ | |
| 1040 | 1333 | irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); |
| 1041 | 1334 | for_each_engine(engine, dev_priv, id) |
| 1042 | 1335 | I915_WRITE(RING_MODE_GEN7(engine), irqs); |
| @@ -1097,10 +1390,19 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) · 54 unmodified lines | ||
| 1097 | 1390 | rps->pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; |
| 1098 | 1391 | } |
| 1099 | 1392 | |
| 1100 | −int i915_guc_submission_enable(struct drm_i915_private *dev_priv) | |
| 1393 | +static void guc_submission_park(struct intel_engine_cs *engine) | |
| 1101 | 1394 | { |
| 1102 | − struct intel_guc *guc = &dev_priv->guc; | |
| 1103 | − struct i915_guc_client *client = guc->execbuf_client; | |
| 1395 | + intel_engine_unpin_breadcrumbs_irq(engine); | |
| 1396 | +} | |
| 1397 | + | |
| 1398 | +static void guc_submission_unpark(struct intel_engine_cs *engine) | |
| 1399 | +{ | |
| 1400 | + intel_engine_pin_breadcrumbs_irq(engine); | |
| 1401 | +} | |
| 1402 | + | |
| 1403 | +int intel_guc_submission_enable(struct intel_guc *guc) | |
| 1404 | +{ | |
| 1405 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 1104 | 1406 | struct intel_engine_cs *engine; |
| 1105 | 1407 | enum intel_engine_id id; |
| 1106 | 1408 | int err; |
| @@ -1118,61 +1420,62 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) · 11 unmodified lines | ||
| 1118 | 1420 | sizeof(struct guc_wq_item) * |
| 1119 | 1421 | I915_NUM_ENGINES > GUC_WQ_SIZE); |
| 1120 | 1422 | |
| 1121 | − if (!client) { | |
| 1122 | − client = guc_client_alloc(dev_priv, | |
| 1123 | − INTEL_INFO(dev_priv)->ring_mask, | |
| 1124 | − GUC_CLIENT_PRIORITY_KMD_NORMAL, | |
| 1125 | − dev_priv->kernel_context); | |
| 1126 | − if (IS_ERR(client)) { | |
| 1127 | − DRM_ERROR("Failed to create GuC client for execbuf!\n"); | |
| 1128 | − return PTR_ERR(client); | |
| 1129 | − } | |
| 1130 | − | |
| 1131 | − guc->execbuf_client = client; | |
| 1423 | + /* | |
| 1424 | + * We're being called on both module initialization and on reset, | |
| 1425 | + * until this flow is changed, we're using regular client presence to | |
| 1426 | + * determine which case are we in, and whether we should allocate new | |
| 1427 | + * clients or just reset their workqueues. | |
| 1428 | + */ | |
| 1429 | + if (!guc->execbuf_client) { | |
| 1430 | + err = guc_clients_create(guc); | |
| 1431 | + if (err) | |
| 1432 | + return err; | |
| 1433 | + } else { | |
| 1434 | + guc_reset_wq(guc->execbuf_client); | |
| 1435 | + guc_reset_wq(guc->preempt_client); | |
| 1132 | 1436 | } |
| 1133 | 1437 | |
| 1134 | 1438 | err = intel_guc_sample_forcewake(guc); |
| 1135 | 1439 | if (err) |
| 1136 | − goto err_execbuf_client; | |
| 1137 | − | |
| 1138 | − guc_reset_wq(client); | |
| 1440 | + goto err_free_clients; | |
| 1139 | 1441 | |
| 1140 | 1442 | err = guc_init_doorbell_hw(guc); |
| 1141 | 1443 | if (err) |
| 1142 | − goto err_execbuf_client; | |
| 1444 | + goto err_free_clients; | |
| 1143 | 1445 | |
| 1144 | 1446 | /* Take over from manual control of ELSP (execlists) */ |
| 1145 | 1447 | guc_interrupts_capture(dev_priv); |
| 1146 | 1448 | |
| 1147 | 1449 | for_each_engine(engine, dev_priv, id) { |
| 1148 | − struct intel_engine_execlists * const execlists = &engine->execlists; | |
| 1149 | − /* The tasklet was initialised by execlists, and may be in | |
| 1150 | − * a state of flux (across a reset) and so we just want to | |
| 1151 | − * take over the callback without changing any other state | |
| 1152 | − * in the tasklet. | |
| 1153 | − */ | |
| 1154 | − execlists->irq_tasklet.func = i915_guc_irq_handler; | |
| 1155 | − clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | |
| 1156 | − tasklet_schedule(&execlists->irq_tasklet); | |
| 1450 | + struct intel_engine_execlists * const execlists = | |
| 1451 | + &engine->execlists; | |
| 1452 | + | |
| 1453 | + execlists->tasklet.func = guc_submission_tasklet; | |
| 1454 | + engine->park = guc_submission_park; | |
| 1455 | + engine->unpark = guc_submission_unpark; | |
| 1157 | 1456 | } |
| 1158 | 1457 | |
| 1159 | 1458 | return 0; |
| 1160 | 1459 | |
| 1161 | −err_execbuf_client: | |
| 1162 | − guc_client_free(guc->execbuf_client); | |
| 1163 | − guc->execbuf_client = NULL; | |
| 1460 | +err_free_clients: | |
| 1461 | + guc_clients_destroy(guc); | |
| 1164 | 1462 | return err; |
| 1165 | 1463 | } |
| 1166 | 1464 | |
| 1167 | −void i915_guc_submission_disable(struct drm_i915_private *dev_priv) | |
| 1465 | +void intel_guc_submission_disable(struct intel_guc *guc) | |
| 1168 | 1466 | { |
| 1169 | − struct intel_guc *guc = &dev_priv->guc; | |
| 1467 | + struct drm_i915_private *dev_priv = guc_to_i915(guc); | |
| 1468 | + | |
| 1469 | + GEM_BUG_ON(dev_priv->gt.awake); /* GT should be parked first */ | |
| 1170 | 1470 | |
| 1171 | 1471 | guc_interrupts_release(dev_priv); |
| 1172 | 1472 | |
| 1173 | 1473 | /* Revert back to manual ELSP submission */ |
| 1174 | 1474 | intel_engines_reset_default_submission(dev_priv); |
| 1175 | 1475 | |
| 1176 | − guc_client_free(guc->execbuf_client); | |
| 1177 | − guc->execbuf_client = NULL; | |
| 1476 | + guc_clients_destroy(guc); | |
| 1178 | 1477 | } |
| 1478 | + | |
| 1479 | +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | |
| 1480 | +#include "selftests/intel_guc.c" | |
| 1481 | +#endif | |
| @@ -52,7 +52,7 @@ struct drm_i915_private; · 51 unmodified lines | ||
| 52 | 52 | * queue (a circular array of work items), again described in the process |
| 53 | 53 | * descriptor. Work queue pages are mapped momentarily as required. |
| 54 | 54 | */ |
| 55 | −struct i915_guc_client { | |
| 55 | +struct intel_guc_client { | |
| 56 | 56 | struct i915_vma *vma; |
| 57 | 57 | void *vaddr; |
| 58 | 58 | struct i915_gem_context *owner; |
| @@ -67,14 +67,15 @@ struct i915_guc_client { · 8 unmodified lines | ||
| 67 | 67 | u16 doorbell_id; |
| 68 | 68 | unsigned long doorbell_offset; |
| 69 | 69 | |
| 70 | + /* Protects GuC client's WQ access */ | |
| 70 | 71 | spinlock_t wq_lock; |
| 71 | 72 | /* Per-engine counts of GuC submissions */ |
| 72 | 73 | u64 submissions[I915_NUM_ENGINES]; |
| 73 | 74 | }; |
| 74 | 75 | |
| 75 | −int i915_guc_submission_init(struct drm_i915_private *dev_priv); | |
| 76 | −int i915_guc_submission_enable(struct drm_i915_private *dev_priv); | |
| 77 | −void i915_guc_submission_disable(struct drm_i915_private *dev_priv); | |
| 78 | −void i915_guc_submission_fini(struct drm_i915_private *dev_priv); | |
| 76 | +int intel_guc_submission_init(struct intel_guc *guc); | |
| 77 | +int intel_guc_submission_enable(struct intel_guc *guc); | |
| 78 | +void intel_guc_submission_disable(struct intel_guc *guc); | |
| 79 | +void intel_guc_submission_fini(struct intel_guc *guc); | |
| 79 | 80 | |
| 80 | 81 | #endif |
| @@ -186,7 +186,7 @@ static bool g4x_infoframe_enabled(struct drm_encoder *encoder, · 185 unmodified lines | ||
| 186 | 186 | if ((val & VIDEO_DIP_ENABLE) == 0) |
| 187 | 187 | return false; |
| 188 | 188 | |
| 189 | − if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) | |
| 189 | + if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port)) | |
| 190 | 190 | return false; |
| 191 | 191 | |
| 192 | 192 | return val & (VIDEO_DIP_ENABLE_AVI | |
| @@ -245,7 +245,7 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder, · 52 unmodified lines | ||
| 245 | 245 | if ((val & VIDEO_DIP_ENABLE) == 0) |
| 246 | 246 | return false; |
| 247 | 247 | |
| 248 | − if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) | |
| 248 | + if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port)) | |
| 249 | 249 | return false; |
| 250 | 250 | |
| 251 | 251 | return val & (VIDEO_DIP_ENABLE_AVI | |
| @@ -362,7 +362,7 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder, · 110 unmodified lines | ||
| 362 | 362 | if ((val & VIDEO_DIP_ENABLE) == 0) |
| 363 | 363 | return false; |
| 364 | 364 | |
| 365 | − if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) | |
| 365 | + if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port)) | |
| 366 | 366 | return false; |
| 367 | 367 | |
| 368 | 368 | return val & (VIDEO_DIP_ENABLE_AVI | |
| @@ -538,7 +538,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, · 169 unmodified lines | ||
| 538 | 538 | struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; |
| 539 | 539 | i915_reg_t reg = VIDEO_DIP_CTL; |
| 540 | 540 | u32 val = I915_READ(reg); |
| 541 | − u32 port = VIDEO_DIP_PORT(intel_dig_port->port); | |
| 541 | + u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port); | |
| 542 | 542 | |
| 543 | 543 | assert_hdmi_port_disabled(intel_hdmi); |
| 544 | 544 | |
| @@ -689,7 +689,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, · 144 unmodified lines | ||
| 689 | 689 | struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; |
| 690 | 690 | i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
| 691 | 691 | u32 val = I915_READ(reg); |
| 692 | − u32 port = VIDEO_DIP_PORT(intel_dig_port->port); | |
| 692 | + u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port); | |
| 693 | 693 | |
| 694 | 694 | assert_hdmi_port_disabled(intel_hdmi); |
| 695 | 695 | |
| @@ -785,7 +785,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, · 89 unmodified lines | ||
| 785 | 785 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 786 | 786 | i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
| 787 | 787 | u32 val = I915_READ(reg); |
| 788 | − u32 port = VIDEO_DIP_PORT(intel_dig_port->port); | |
| 788 | + u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port); | |
| 789 | 789 | |
| 790 | 790 | assert_hdmi_port_disabled(intel_hdmi); |
| 791 | 791 | |
| @@ -960,6 +960,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, · 168 unmodified lines | ||
| 960 | 960 | u32 tmp, flags = 0; |
| 961 | 961 | int dotclock; |
| 962 | 962 | |
| 963 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI); | |
| 964 | + | |
| 963 | 965 | tmp = I915_READ(intel_hdmi->hdmi_reg); |
| 964 | 966 | |
| 965 | 967 | if (tmp & SDVO_HSYNC_ACTIVE_HIGH) |
| @@ -1207,7 +1209,8 @@ static void g4x_disable_hdmi(struct intel_encoder *encoder, · 241 unmodified lines | ||
| 1207 | 1209 | const struct drm_connector_state *old_conn_state) |
| 1208 | 1210 | { |
| 1209 | 1211 | if (old_crtc_state->has_audio) |
| 1210 | − intel_audio_codec_disable(encoder); | |
| 1212 | + intel_audio_codec_disable(encoder, | |
| 1213 | + old_crtc_state, old_conn_state); | |
| 1211 | 1214 | |
| 1212 | 1215 | intel_disable_hdmi(encoder, old_crtc_state, old_conn_state); |
| 1213 | 1216 | } |
| @@ -1217,7 +1220,8 @@ static void pch_disable_hdmi(struct intel_encoder *encoder, · 3 unmodified lines | ||
| 1217 | 1220 | const struct drm_connector_state *old_conn_state) |
| 1218 | 1221 | { |
| 1219 | 1222 | if (old_crtc_state->has_audio) |
| 1220 | − intel_audio_codec_disable(encoder); | |
| 1223 | + intel_audio_codec_disable(encoder, | |
| 1224 | + old_crtc_state, old_conn_state); | |
| 1221 | 1225 | } |
| 1222 | 1226 | |
| 1223 | 1227 | static void pch_post_disable_hdmi(struct intel_encoder *encoder, |
| @@ -1227,24 +1231,34 @@ static void pch_post_disable_hdmi(struct intel_encoder *encoder, · 3 unmodified lines | ||
| 1227 | 1231 | intel_disable_hdmi(encoder, old_crtc_state, old_conn_state); |
| 1228 | 1232 | } |
| 1229 | 1233 | |
| 1230 | −static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv) | |
| 1234 | +static int intel_hdmi_source_max_tmds_clock(struct intel_encoder *encoder) | |
| 1231 | 1235 | { |
| 1232 | − if (IS_G4X(dev_priv)) | |
| 1233 | − return 165000; | |
| 1234 | − else if (IS_GEMINILAKE(dev_priv)) | |
| 1235 | − return 594000; | |
| 1236 | − else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) | |
| 1237 | − return 300000; | |
| 1236 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1237 | + const struct ddi_vbt_port_info *info = | |
| 1238 | + &dev_priv->vbt.ddi_port_info[encoder->port]; | |
| 1239 | + int max_tmds_clock; | |
| 1240 | + | |
| 1241 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | |
| 1242 | + max_tmds_clock = 594000; | |
| 1243 | + else if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) | |
| 1244 | + max_tmds_clock = 300000; | |
| 1245 | + else if (INTEL_GEN(dev_priv) >= 5) | |
| 1246 | + max_tmds_clock = 225000; | |
| 1238 | 1247 | else |
| 1239 | − return 225000; | |
| 1248 | + max_tmds_clock = 165000; | |
| 1249 | + | |
| 1250 | + if (info->max_tmds_clock) | |
| 1251 | + max_tmds_clock = min(max_tmds_clock, info->max_tmds_clock); | |
| 1252 | + | |
| 1253 | + return max_tmds_clock; | |
| 1240 | 1254 | } |
| 1241 | 1255 | |
| 1242 | 1256 | static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, |
| 1243 | 1257 | bool respect_downstream_limits, |
| 1244 | 1258 | bool force_dvi) |
| 1245 | 1259 | { |
| 1246 | − struct drm_device *dev = intel_hdmi_to_dev(hdmi); | |
| 1247 | − int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev)); | |
| 1260 | + struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base; | |
| 1261 | + int max_tmds_clock = intel_hdmi_source_max_tmds_clock(encoder); | |
| 1248 | 1262 | |
| 1249 | 1263 | if (respect_downstream_limits) { |
| 1250 | 1264 | struct intel_connector *connector = hdmi->attached_connector; |
| @@ -1339,6 +1353,12 @@ static bool hdmi_12bpc_possible(const struct intel_crtc_state *crtc_state) · 88 unmodified lines | ||
| 1339 | 1353 | if (HAS_GMCH_DISPLAY(dev_priv)) |
| 1340 | 1354 | return false; |
| 1341 | 1355 | |
| 1356 | + if (crtc_state->pipe_bpp <= 8*3) | |
| 1357 | + return false; | |
| 1358 | + | |
| 1359 | + if (!crtc_state->has_hdmi_sink) | |
| 1360 | + return false; | |
| 1361 | + | |
| 1342 | 1362 | /* |
| 1343 | 1363 | * HDMI 12bpc affects the clocks, so it's only possible |
| 1344 | 1364 | * when not cloning with other encoder types. |
| @@ -1464,9 +1484,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, · 119 unmodified lines | ||
| 1464 | 1484 | * outputs. We also need to check that the higher clock still fits |
| 1465 | 1485 | * within limits. |
| 1466 | 1486 | */ |
| 1467 | − if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && !force_dvi && | |
| 1468 | − hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true, force_dvi) == MODE_OK && | |
| 1469 | − hdmi_12bpc_possible(pipe_config)) { | |
| 1487 | + if (hdmi_12bpc_possible(pipe_config) && | |
| 1488 | + hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true, force_dvi) == MODE_OK) { | |
| 1470 | 1489 | DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); |
| 1471 | 1490 | desired_bpp = 12*3; |
| 1472 | 1491 | |
| @@ -1495,7 +1514,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, · 22 unmodified lines | ||
| 1495 | 1514 | |
| 1496 | 1515 | pipe_config->lane_count = 4; |
| 1497 | 1516 | |
| 1498 | − if (scdc->scrambling.supported && IS_GEMINILAKE(dev_priv)) { | |
| 1517 | + if (scdc->scrambling.supported && (INTEL_GEN(dev_priv) >= 10 || | |
| 1518 | + IS_GEMINILAKE(dev_priv))) { | |
| 1499 | 1519 | if (scdc->scrambling.low_rates) |
| 1500 | 1520 | pipe_config->hdmi_scrambling = true; |
| 1501 | 1521 | |
| @@ -1529,7 +1549,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) · 27 unmodified lines | ||
| 1529 | 1549 | { |
| 1530 | 1550 | struct drm_i915_private *dev_priv = to_i915(connector->dev); |
| 1531 | 1551 | struct intel_hdmi *hdmi = intel_attached_hdmi(connector); |
| 1532 | − enum port port = hdmi_to_dig_port(hdmi)->port; | |
| 1552 | + enum port port = hdmi_to_dig_port(hdmi)->base.port; | |
| 1533 | 1553 | struct i2c_adapter *adapter = |
| 1534 | 1554 | intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); |
| 1535 | 1555 | enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter); |
| @@ -1613,12 +1633,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) · 77 unmodified lines | ||
| 1613 | 1633 | |
| 1614 | 1634 | intel_hdmi_unset_edid(connector); |
| 1615 | 1635 | |
| 1616 | − if (intel_hdmi_set_edid(connector)) { | |
| 1617 | − struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | |
| 1618 | − | |
| 1619 | − hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; | |
| 1636 | + if (intel_hdmi_set_edid(connector)) | |
| 1620 | 1637 | status = connector_status_connected; |
| 1621 | − } else | |
| 1638 | + else | |
| 1622 | 1639 | status = connector_status_disconnected; |
| 1623 | 1640 | |
| 1624 | 1641 | intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); |
| @@ -1629,8 +1646,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) · 4 unmodified lines | ||
| 1629 | 1646 | static void |
| 1630 | 1647 | intel_hdmi_force(struct drm_connector *connector) |
| 1631 | 1648 | { |
| 1632 | − struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | |
| 1633 | − | |
| 1634 | 1649 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
| 1635 | 1650 | connector->base.id, connector->name); |
| 1636 | 1651 | |
| @@ -1640,7 +1655,6 @@ intel_hdmi_force(struct drm_connector *connector) · 3 unmodified lines | ||
| 1640 | 1655 | return; |
| 1641 | 1656 | |
| 1642 | 1657 | intel_hdmi_set_edid(connector); |
| 1643 | − hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; | |
| 1644 | 1658 | } |
| 1645 | 1659 | |
| 1646 | 1660 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
| @@ -1673,10 +1687,9 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder, · 26 unmodified lines | ||
| 1673 | 1687 | const struct drm_connector_state *conn_state) |
| 1674 | 1688 | { |
| 1675 | 1689 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| 1676 | − struct drm_device *dev = encoder->base.dev; | |
| 1677 | − struct drm_i915_private *dev_priv = to_i915(dev); | |
| 1690 | + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | |
| 1678 | 1691 | |
| 1679 | − vlv_phy_pre_encoder_enable(encoder); | |
| 1692 | + vlv_phy_pre_encoder_enable(encoder, pipe_config); | |
| 1680 | 1693 | |
| 1681 | 1694 | /* HDMI 1.0V-2dB */ |
| 1682 | 1695 | vlv_set_phy_signal_level(encoder, 0x2b245f5f, 0x00002000, 0x5578b83a, |
| @@ -1697,7 +1710,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder, · 14 unmodified lines | ||
| 1697 | 1710 | { |
| 1698 | 1711 | intel_hdmi_prepare(encoder, pipe_config); |
| 1699 | 1712 | |
| 1700 | − vlv_phy_pre_pll_enable(encoder); | |
| 1713 | + vlv_phy_pre_pll_enable(encoder, pipe_config); | |
| 1701 | 1714 | } |
| 1702 | 1715 | |
| 1703 | 1716 | static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder, |
| @@ -1706,14 +1719,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder, · 2 unmodified lines | ||
| 1706 | 1719 | { |
| 1707 | 1720 | intel_hdmi_prepare(encoder, pipe_config); |
| 1708 | 1721 | |
| 1709 | − chv_phy_pre_pll_enable(encoder); | |
| 1722 | + chv_phy_pre_pll_enable(encoder, pipe_config); | |
| 1710 | 1723 | } |
| 1711 | 1724 | |
| 1712 | 1725 | static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder, |
| 1713 | 1726 | const struct intel_crtc_state *old_crtc_state, |
| 1714 | 1727 | const struct drm_connector_state *old_conn_state) |
| 1715 | 1728 | { |
| 1716 | − chv_phy_post_pll_disable(encoder); | |
| 1729 | + chv_phy_post_pll_disable(encoder, old_crtc_state); | |
| 1717 | 1730 | } |
| 1718 | 1731 | |
| 1719 | 1732 | static void vlv_hdmi_post_disable(struct intel_encoder *encoder, |
| @@ -1721,7 +1734,7 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder, · 1 unmodified line | ||
| 1721 | 1734 | const struct drm_connector_state *old_conn_state) |
| 1722 | 1735 | { |
| 1723 | 1736 | /* Reset lanes to avoid HDMI flicker (VLV w/a) */ |
| 1724 | − vlv_phy_reset_lanes(encoder); | |
| 1737 | + vlv_phy_reset_lanes(encoder, old_crtc_state); | |
| 1725 | 1738 | } |
| 1726 | 1739 | |
| 1727 | 1740 | static void chv_hdmi_post_disable(struct intel_encoder *encoder, |
| @@ -1734,7 +1747,7 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder, · 6 unmodified lines | ||
| 1734 | 1747 | mutex_lock(&dev_priv->sb_lock); |
| 1735 | 1748 | |
| 1736 | 1749 | /* Assert data lane reset */ |
| 1737 | − chv_data_lane_soft_reset(encoder, true); | |
| 1750 | + chv_data_lane_soft_reset(encoder, old_crtc_state, true); | |
| 1738 | 1751 | |
| 1739 | 1752 | mutex_unlock(&dev_priv->sb_lock); |
| 1740 | 1753 | } |
| @@ -1747,7 +1760,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder, · 6 unmodified lines | ||
| 1747 | 1760 | struct drm_device *dev = encoder->base.dev; |
| 1748 | 1761 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1749 | 1762 | |
| 1750 | − chv_phy_pre_encoder_enable(encoder); | |
| 1763 | + chv_phy_pre_encoder_enable(encoder, pipe_config); | |
| 1751 | 1764 | |
| 1752 | 1765 | /* FIXME: Program the support xxx V-dB */ |
| 1753 | 1766 | /* Use 800mV-0dB */ |
| @@ -2006,7 +2019,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, · 252 unmodified lines | ||
| 2006 | 2019 | struct intel_encoder *intel_encoder = &intel_dig_port->base; |
| 2007 | 2020 | struct drm_device *dev = intel_encoder->base.dev; |
| 2008 | 2021 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2009 | − enum port port = intel_dig_port->port; | |
| 2022 | + enum port port = intel_encoder->port; | |
| 2010 | 2023 | |
| 2011 | 2024 | DRM_DEBUG_KMS("Adding HDMI connector on port %c\n", |
| 2012 | 2025 | port_name(port)); |
| @@ -2024,7 +2037,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, · 11 unmodified lines | ||
| 2024 | 2037 | connector->doublescan_allowed = 0; |
| 2025 | 2038 | connector->stereo_allowed = 1; |
| 2026 | 2039 | |
| 2027 | − if (IS_GEMINILAKE(dev_priv)) | |
| 2040 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | |
| 2028 | 2041 | connector->ycbcr_420_allowed = true; |
| 2029 | 2042 | |
| 2030 | 2043 | intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); |
| @@ -2126,7 +2139,6 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, · 95 unmodified lines | ||
| 2126 | 2139 | if (IS_G4X(dev_priv)) |
| 2127 | 2140 | intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; |
| 2128 | 2141 | |
| 2129 | − intel_dig_port->port = port; | |
| 2130 | 2142 | intel_dig_port->hdmi.hdmi_reg = hdmi_reg; |
| 2131 | 2143 | intel_dig_port->dp.output_reg = INVALID_MMIO_REG; |
| 2132 | 2144 | intel_dig_port->max_lanes = 4; |
| @@ -151,7 +151,7 @@ static int huc_ucode_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) · 150 unmodified lines | ||
| 151 | 151 | I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA)); |
| 152 | 152 | |
| 153 | 153 | /* Wait for DMA to finish */ |
| 154 | − ret = wait_for((I915_READ(DMA_CTRL) & START_DMA) == 0, 100); | |
| 154 | + ret = intel_wait_for_register_fw(dev_priv, DMA_CTRL, START_DMA, 0, 100); | |
| 155 | 155 | |
| 156 | 156 | DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret); |
| 157 | 157 | |
| @@ -136,6 +136,7 @@ · 135 unmodified lines | ||
| 136 | 136 | #include <drm/drmP.h> |
| 137 | 137 | #include <drm/i915_drm.h> |
| 138 | 138 | #include "i915_drv.h" |
| 139 | +#include "i915_gem_render_state.h" | |
| 139 | 140 | #include "intel_mocs.h" |
| 140 | 141 | |
| 141 | 142 | #define RING_EXECLIST_QFULL (1 << 0x2) |
| @@ -354,7 +355,7 @@ static void unwind_wa_tail(struct drm_i915_gem_request *rq) · 212 unmodified lines | ||
| 354 | 355 | assert_ring_tail_valid(rq->ring, rq->tail); |
| 355 | 356 | } |
| 356 | 357 | |
| 357 | −static void unwind_incomplete_requests(struct intel_engine_cs *engine) | |
| 358 | +static void __unwind_incomplete_requests(struct intel_engine_cs *engine) | |
| 358 | 359 | { |
| 359 | 360 | struct drm_i915_gem_request *rq, *rn; |
| 360 | 361 | struct i915_priolist *uninitialized_var(p); |
| @@ -385,6 +386,17 @@ static void unwind_incomplete_requests(struct intel_engine_cs *engine) · 24 unmodified lines | ||
| 385 | 386 | } |
| 386 | 387 | } |
| 387 | 388 | |
| 389 | +void | |
| 390 | +execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists) | |
| 391 | +{ | |
| 392 | + struct intel_engine_cs *engine = | |
| 393 | + container_of(execlists, typeof(*engine), execlists); | |
| 394 | + | |
| 395 | + spin_lock_irq(&engine->timeline->lock); | |
| 396 | + __unwind_incomplete_requests(engine); | |
| 397 | + spin_unlock_irq(&engine->timeline->lock); | |
| 398 | +} | |
| 399 | + | |
| 388 | 400 | static inline void |
| 389 | 401 | execlists_context_status_change(struct drm_i915_gem_request *rq, |
| 390 | 402 | unsigned long status) |
| @@ -455,6 +467,11 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) · 64 unmodified lines | ||
| 455 | 467 | port_set(&port[n], port_pack(rq, count)); |
| 456 | 468 | desc = execlists_update_context(rq); |
| 457 | 469 | GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); |
| 470 | + | |
| 471 | + GEM_TRACE("%s in[%d]: ctx=%d.%d, seqno=%x\n", | |
| 472 | + engine->name, n, | |
| 473 | + rq->ctx->hw_id, count, | |
| 474 | + rq->global_seqno); | |
| 458 | 475 | } else { |
| 459 | 476 | GEM_BUG_ON(!n); |
| 460 | 477 | desc = 0; |
| @@ -509,17 +526,13 @@ static void inject_preempt_context(struct intel_engine_cs *engine) · 48 unmodified lines | ||
| 509 | 526 | ce->ring->tail &= (ce->ring->size - 1); |
| 510 | 527 | ce->lrc_reg_state[CTX_RING_TAIL+1] = ce->ring->tail; |
| 511 | 528 | |
| 529 | + GEM_TRACE("\n"); | |
| 512 | 530 | for (n = execlists_num_ports(&engine->execlists); --n; ) |
| 513 | 531 | elsp_write(0, elsp); |
| 514 | 532 | |
| 515 | 533 | elsp_write(ce->lrc_desc, elsp); |
| 516 | 534 | } |
| 517 | 535 | |
| 518 | −static bool can_preempt(struct intel_engine_cs *engine) | |
| 519 | −{ | |
| 520 | − return INTEL_INFO(engine->i915)->has_logical_ring_preemption; | |
| 521 | −} | |
| 522 | − | |
| 523 | 536 | static void execlists_dequeue(struct intel_engine_cs *engine) |
| 524 | 537 | { |
| 525 | 538 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| @@ -567,7 +580,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) · 41 unmodified lines | ||
| 567 | 580 | if (port_count(&port[0]) > 1) |
| 568 | 581 | goto unlock; |
| 569 | 582 | |
| 570 | − if (can_preempt(engine) && | |
| 583 | + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && | |
| 571 | 584 | rb_entry(rb, struct i915_priolist, node)->priority > |
| 572 | 585 | max(last->priotree.priority, 0)) { |
| 573 | 586 | /* |
| @@ -690,8 +703,8 @@ unlock: · 116 unmodified lines | ||
| 690 | 703 | } |
| 691 | 704 | } |
| 692 | 705 | |
| 693 | −static void | |
| 694 | −execlist_cancel_port_requests(struct intel_engine_execlists *execlists) | |
| 706 | +void | |
| 707 | +execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) | |
| 695 | 708 | { |
| 696 | 709 | struct execlist_port *port = execlists->port; |
| 697 | 710 | unsigned int num_ports = execlists_num_ports(execlists); |
| @@ -718,7 +731,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) · 20 unmodified lines | ||
| 718 | 731 | spin_lock_irqsave(&engine->timeline->lock, flags); |
| 719 | 732 | |
| 720 | 733 | /* Cancel the requests on the HW and clear the ELSP tracker. */ |
| 721 | − execlist_cancel_port_requests(execlists); | |
| 734 | + execlists_cancel_port_requests(execlists); | |
| 722 | 735 | |
| 723 | 736 | /* Mark all executing requests as skipped. */ |
| 724 | 737 | list_for_each_entry(rq, &engine->timeline->requests, link) { |
| @@ -768,7 +781,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) · 43 unmodified lines | ||
| 768 | 781 | * Check the unread Context Status Buffers and manage the submission of new |
| 769 | 782 | * contexts to the ELSP accordingly. |
| 770 | 783 | */ |
| 771 | −static void intel_lrc_irq_handler(unsigned long data) | |
| 784 | +static void execlists_submission_tasklet(unsigned long data) | |
| 772 | 785 | { |
| 773 | 786 | struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; |
| 774 | 787 | struct intel_engine_execlists * const execlists = &engine->execlists; |
| @@ -826,6 +839,10 @@ static void intel_lrc_irq_handler(unsigned long data) · 51 unmodified lines | ||
| 826 | 839 | head = execlists->csb_head; |
| 827 | 840 | tail = READ_ONCE(buf[write_idx]); |
| 828 | 841 | } |
| 842 | + GEM_TRACE("%s cs-irq head=%d [%d], tail=%d [%d]\n", | |
| 843 | + engine->name, | |
| 844 | + head, GEN8_CSB_READ_PTR(readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)))), | |
| 845 | + tail, GEN8_CSB_WRITE_PTR(readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))))); | |
| 829 | 846 | |
| 830 | 847 | while (head != tail) { |
| 831 | 848 | struct drm_i915_gem_request *rq; |
| @@ -853,16 +870,16 @@ static void intel_lrc_irq_handler(unsigned long data) · 21 unmodified lines | ||
| 853 | 870 | */ |
| 854 | 871 | |
| 855 | 872 | status = READ_ONCE(buf[2 * head]); /* maybe mmio! */ |
| 873 | + GEM_TRACE("%s csb[%dd]: status=0x%08x:0x%08x\n", | |
| 874 | + engine->name, head, | |
| 875 | + status, buf[2*head + 1]); | |
| 856 | 876 | if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) |
| 857 | 877 | continue; |
| 858 | 878 | |
| 859 | 879 | if (status & GEN8_CTX_STATUS_ACTIVE_IDLE && |
| 860 | 880 | buf[2*head + 1] == PREEMPT_ID) { |
| 861 | − execlist_cancel_port_requests(execlists); | |
| 862 | − | |
| 863 | − spin_lock_irq(&engine->timeline->lock); | |
| 864 | − unwind_incomplete_requests(engine); | |
| 865 | − spin_unlock_irq(&engine->timeline->lock); | |
| 881 | + execlists_cancel_port_requests(execlists); | |
| 882 | + execlists_unwind_incomplete_requests(execlists); | |
| 866 | 883 | |
| 867 | 884 | GEM_BUG_ON(!execlists_is_active(execlists, |
| 868 | 885 | EXECLISTS_ACTIVE_PREEMPT)); |
| @@ -883,6 +900,10 @@ static void intel_lrc_irq_handler(unsigned long data) · 14 unmodified lines | ||
| 883 | 900 | GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); |
| 884 | 901 | |
| 885 | 902 | rq = port_unpack(port, &count); |
| 903 | + GEM_TRACE("%s out[0]: ctx=%d.%d, seqno=%x\n", | |
| 904 | + engine->name, | |
| 905 | + rq->ctx->hw_id, count, | |
| 906 | + rq->global_seqno); | |
| 886 | 907 | GEM_BUG_ON(count == 0); |
| 887 | 908 | if (--count == 0) { |
| 888 | 909 | GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); |
| @@ -926,7 +947,7 @@ static void insert_request(struct intel_engine_cs *engine, · 37 unmodified lines | ||
| 926 | 947 | |
| 927 | 948 | list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); |
| 928 | 949 | if (ptr_unmask_bits(p, 1)) |
| 929 | − tasklet_hi_schedule(&engine->execlists.irq_tasklet); | |
| 950 | + tasklet_hi_schedule(&engine->execlists.tasklet); | |
| 930 | 951 | } |
| 931 | 952 | |
| 932 | 953 | static void execlists_submit_request(struct drm_i915_gem_request *request) |
| @@ -1057,12 +1078,34 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) · 124 unmodified lines | ||
| 1057 | 1078 | spin_unlock_irq(&engine->timeline->lock); |
| 1058 | 1079 | } |
| 1059 | 1080 | |
| 1081 | +static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) | |
| 1082 | +{ | |
| 1083 | + unsigned int flags; | |
| 1084 | + int err; | |
| 1085 | + | |
| 1086 | + /* | |
| 1087 | + * Clear this page out of any CPU caches for coherent swap-in/out. | |
| 1088 | + * We only want to do this on the first bind so that we do not stall | |
| 1089 | + * on an active context (which by nature is already on the GPU). | |
| 1090 | + */ | |
| 1091 | + if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { | |
| 1092 | + err = i915_gem_object_set_to_gtt_domain(vma->obj, true); | |
| 1093 | + if (err) | |
| 1094 | + return err; | |
| 1095 | + } | |
| 1096 | + | |
| 1097 | + flags = PIN_GLOBAL | PIN_HIGH; | |
| 1098 | + if (ctx->ggtt_offset_bias) | |
| 1099 | + flags |= PIN_OFFSET_BIAS | ctx->ggtt_offset_bias; | |
| 1100 | + | |
| 1101 | + return i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, flags); | |
| 1102 | +} | |
| 1103 | + | |
| 1060 | 1104 | static struct intel_ring * |
| 1061 | 1105 | execlists_context_pin(struct intel_engine_cs *engine, |
| 1062 | 1106 | struct i915_gem_context *ctx) |
| 1063 | 1107 | { |
| 1064 | 1108 | struct intel_context *ce = &ctx->engine[engine->id]; |
| 1065 | − unsigned int flags; | |
| 1066 | 1109 | void *vaddr; |
| 1067 | 1110 | int ret; |
| 1068 | 1111 | |
| @@ -1079,11 +1122,7 @@ execlists_context_pin(struct intel_engine_cs *engine, · 10 unmodified lines | ||
| 1079 | 1122 | } |
| 1080 | 1123 | GEM_BUG_ON(!ce->state); |
| 1081 | 1124 | |
| 1082 | − flags = PIN_GLOBAL | PIN_HIGH; | |
| 1083 | − if (ctx->ggtt_offset_bias) | |
| 1084 | − flags |= PIN_OFFSET_BIAS | ctx->ggtt_offset_bias; | |
| 1085 | − | |
| 1086 | − ret = i915_vma_pin(ce->state, 0, GEN8_LR_CONTEXT_ALIGN, flags); | |
| 1125 | + ret = __context_pin(ctx, ce->state); | |
| 1087 | 1126 | if (ret) |
| 1088 | 1127 | goto err; |
| 1089 | 1128 | |
| @@ -1103,9 +1142,7 @@ execlists_context_pin(struct intel_engine_cs *engine, · 13 unmodified lines | ||
| 1103 | 1142 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = |
| 1104 | 1143 | i915_ggtt_offset(ce->ring->vma); |
| 1105 | 1144 | |
| 1106 | − ce->state->obj->mm.dirty = true; | |
| 1107 | 1145 | ce->state->obj->pin_global++; |
| 1108 | − | |
| 1109 | 1146 | i915_gem_context_get(ctx); |
| 1110 | 1147 | out: |
| 1111 | 1148 | return ce->ring; |
| @@ -1143,7 +1180,6 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) · 31 unmodified lines | ||
| 1143 | 1180 | { |
| 1144 | 1181 | struct intel_engine_cs *engine = request->engine; |
| 1145 | 1182 | struct intel_context *ce = &request->ctx->engine[engine->id]; |
| 1146 | − u32 *cs; | |
| 1147 | 1183 | int ret; |
| 1148 | 1184 | |
| 1149 | 1185 | GEM_BUG_ON(!ce->pin_count); |
| @@ -1154,17 +1190,9 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) · 4 unmodified lines | ||
| 1154 | 1190 | */ |
| 1155 | 1191 | request->reserved_space += EXECLISTS_REQUEST_SIZE; |
| 1156 | 1192 | |
| 1157 | − cs = intel_ring_begin(request, 0); | |
| 1158 | − if (IS_ERR(cs)) | |
| 1159 | − return PTR_ERR(cs); | |
| 1160 | − | |
| 1161 | − if (!ce->initialised) { | |
| 1162 | − ret = engine->init_context(request); | |
| 1163 | − if (ret) | |
| 1164 | − return ret; | |
| 1165 | − | |
| 1166 | − ce->initialised = true; | |
| 1167 | − } | |
| 1193 | + ret = intel_ring_wait_for_space(request->ring, request->reserved_space); | |
| 1194 | + if (ret) | |
| 1195 | + return ret; | |
| 1168 | 1196 | |
| 1169 | 1197 | /* Note that after this point, we have committed to using |
| 1170 | 1198 | * this request as it is being used to both track the |
| @@ -1474,8 +1502,8 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) · 303 unmodified lines | ||
| 1474 | 1502 | execlists->active = 0; |
| 1475 | 1503 | |
| 1476 | 1504 | /* After a GPU reset, we may have requests to replay */ |
| 1477 | − if (!i915_modparams.enable_guc_submission && execlists->first) | |
| 1478 | − tasklet_schedule(&execlists->irq_tasklet); | |
| 1505 | + if (execlists->first) | |
| 1506 | + tasklet_schedule(&execlists->tasklet); | |
| 1479 | 1507 | |
| 1480 | 1508 | return 0; |
| 1481 | 1509 | } |
| @@ -1531,10 +1559,10 @@ static void reset_common_ring(struct intel_engine_cs *engine, · 49 unmodified lines | ||
| 1531 | 1559 | * guessing the missed context-switch events by looking at what |
| 1532 | 1560 | * requests were completed. |
| 1533 | 1561 | */ |
| 1534 | − execlist_cancel_port_requests(execlists); | |
| 1562 | + execlists_cancel_port_requests(execlists); | |
| 1535 | 1563 | |
| 1536 | 1564 | /* Push back any incomplete requests for replay after the reset. */ |
| 1537 | − unwind_incomplete_requests(engine); | |
| 1565 | + __unwind_incomplete_requests(engine); | |
| 1538 | 1566 | |
| 1539 | 1567 | spin_unlock_irqrestore(&engine->timeline->lock, flags); |
| 1540 | 1568 | |
| @@ -1794,10 +1822,8 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs) · 253 unmodified lines | ||
| 1794 | 1822 | /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */ |
| 1795 | 1823 | BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5)); |
| 1796 | 1824 | |
| 1797 | − *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; | |
| 1798 | − *cs++ = intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT; | |
| 1799 | − *cs++ = 0; | |
| 1800 | − *cs++ = request->global_seqno; | |
| 1825 | + cs = gen8_emit_ggtt_write(cs, request->global_seqno, | |
| 1826 | + intel_hws_seqno_address(request->engine)); | |
| 1801 | 1827 | *cs++ = MI_USER_INTERRUPT; |
| 1802 | 1828 | *cs++ = MI_NOOP; |
| 1803 | 1829 | request->tail = intel_ring_offset(request, cs); |
| @@ -1807,24 +1833,14 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs) · 3 unmodified lines | ||
| 1807 | 1833 | } |
| 1808 | 1834 | static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; |
| 1809 | 1835 | |
| 1810 | −static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, | |
| 1836 | +static void gen8_emit_breadcrumb_rcs(struct drm_i915_gem_request *request, | |
| 1811 | 1837 | u32 *cs) |
| 1812 | 1838 | { |
| 1813 | 1839 | /* We're using qword write, seqno should be aligned to 8 bytes. */ |
| 1814 | 1840 | BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1); |
| 1815 | 1841 | |
| 1816 | − /* w/a for post sync ops following a GPGPU operation we | |
| 1817 | − * need a prior CS_STALL, which is emitted by the flush | |
| 1818 | − * following the batch. | |
| 1819 | − */ | |
| 1820 | − *cs++ = GFX_OP_PIPE_CONTROL(6); | |
| 1821 | − *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | | |
| 1822 | − PIPE_CONTROL_QW_WRITE; | |
| 1823 | − *cs++ = intel_hws_seqno_address(request->engine); | |
| 1824 | − *cs++ = 0; | |
| 1825 | − *cs++ = request->global_seqno; | |
| 1826 | − /* We're thrashing one dword of HWS. */ | |
| 1827 | − *cs++ = 0; | |
| 1842 | + cs = gen8_emit_ggtt_write_rcs(cs, request->global_seqno, | |
| 1843 | + intel_hws_seqno_address(request->engine)); | |
| 1828 | 1844 | *cs++ = MI_USER_INTERRUPT; |
| 1829 | 1845 | *cs++ = MI_NOOP; |
| 1830 | 1846 | request->tail = intel_ring_offset(request, cs); |
| @@ -1832,7 +1848,7 @@ static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, · 1 unmodified line | ||
| 1832 | 1848 | |
| 1833 | 1849 | gen8_emit_wa_tail(request, cs); |
| 1834 | 1850 | } |
| 1835 | −static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; | |
| 1851 | +static const int gen8_emit_breadcrumb_rcs_sz = 8 + WA_TAIL_DWORDS; | |
| 1836 | 1852 | |
| 1837 | 1853 | static int gen8_init_rcs_context(struct drm_i915_gem_request *req) |
| 1838 | 1854 | { |
| @@ -1865,8 +1881,9 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) · 26 unmodified lines | ||
| 1865 | 1881 | * Tasklet cannot be active at this point due intel_mark_active/idle |
| 1866 | 1882 | * so this is just for documentation. |
| 1867 | 1883 | */ |
| 1868 | − if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->execlists.irq_tasklet.state))) | |
| 1869 | − tasklet_kill(&engine->execlists.irq_tasklet); | |
| 1884 | + if (WARN_ON(test_bit(TASKLET_STATE_SCHED, | |
| 1885 | + &engine->execlists.tasklet.state))) | |
| 1886 | + tasklet_kill(&engine->execlists.tasklet); | |
| 1870 | 1887 | |
| 1871 | 1888 | dev_priv = engine->i915; |
| 1872 | 1889 | |
| @@ -1890,7 +1907,10 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) · 17 unmodified lines | ||
| 1890 | 1907 | engine->submit_request = execlists_submit_request; |
| 1891 | 1908 | engine->cancel_requests = execlists_cancel_requests; |
| 1892 | 1909 | engine->schedule = execlists_schedule; |
| 1893 | − engine->execlists.irq_tasklet.func = intel_lrc_irq_handler; | |
| 1910 | + engine->execlists.tasklet.func = execlists_submission_tasklet; | |
| 1911 | + | |
| 1912 | + engine->park = NULL; | |
| 1913 | + engine->unpark = NULL; | |
| 1894 | 1914 | } |
| 1895 | 1915 | |
| 1896 | 1916 | static void |
| @@ -1949,8 +1969,8 @@ logical_ring_setup(struct intel_engine_cs *engine) · 52 unmodified lines | ||
| 1949 | 1969 | |
| 1950 | 1970 | engine->execlists.fw_domains = fw_domains; |
| 1951 | 1971 | |
| 1952 | − tasklet_init(&engine->execlists.irq_tasklet, | |
| 1953 | − intel_lrc_irq_handler, (unsigned long)engine); | |
| 1972 | + tasklet_init(&engine->execlists.tasklet, | |
| 1973 | + execlists_submission_tasklet, (unsigned long)engine); | |
| 1954 | 1974 | |
| 1955 | 1975 | logical_ring_default_vfuncs(engine); |
| 1956 | 1976 | logical_ring_default_irqs(engine); |
| @@ -1988,8 +2008,8 @@ int logical_render_ring_init(struct intel_engine_cs *engine) · 31 unmodified lines | ||
| 1988 | 2008 | engine->init_hw = gen8_init_render_ring; |
| 1989 | 2009 | engine->init_context = gen8_init_rcs_context; |
| 1990 | 2010 | engine->emit_flush = gen8_emit_flush_render; |
| 1991 | − engine->emit_breadcrumb = gen8_emit_breadcrumb_render; | |
| 1992 | − engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_render_sz; | |
| 2011 | + engine->emit_breadcrumb = gen8_emit_breadcrumb_rcs; | |
| 2012 | + engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_rcs_sz; | |
| 1993 | 2013 | |
| 1994 | 2014 | ret = intel_engine_create_scratch(engine, PAGE_SIZE); |
| 1995 | 2015 | if (ret) |
| @@ -2106,7 +2126,6 @@ static void execlists_init_reg_state(u32 *regs, · 110 unmodified lines | ||
| 2106 | 2126 | |
| 2107 | 2127 | CTX_REG(regs, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(engine), |
| 2108 | 2128 | _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | |
| 2109 | − CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | | |
| 2110 | 2129 | (HAS_RESOURCE_STREAMER(dev_priv) ? |
| 2111 | 2130 | CTX_CTRL_RS_CTX_ENABLE : 0))); |
| 2112 | 2131 | CTX_REG(regs, CTX_RING_HEAD, RING_HEAD(base), 0); |
| @@ -2183,6 +2202,7 @@ populate_lr_context(struct i915_gem_context *ctx, · 70 unmodified lines | ||
| 2183 | 2202 | struct intel_ring *ring) |
| 2184 | 2203 | { |
| 2185 | 2204 | void *vaddr; |
| 2205 | + u32 *regs; | |
| 2186 | 2206 | int ret; |
| 2187 | 2207 | |
| 2188 | 2208 | ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true); |
| @@ -2199,11 +2219,31 @@ populate_lr_context(struct i915_gem_context *ctx, · 10 unmodified lines | ||
| 2199 | 2219 | } |
| 2200 | 2220 | ctx_obj->mm.dirty = true; |
| 2201 | 2221 | |
| 2222 | + if (engine->default_state) { | |
| 2223 | + /* | |
| 2224 | + * We only want to copy over the template context state; | |
| 2225 | + * skipping over the headers reserved for GuC communication, | |
| 2226 | + * leaving those as zero. | |
| 2227 | + */ | |
| 2228 | + const unsigned long start = LRC_HEADER_PAGES * PAGE_SIZE; | |
| 2229 | + void *defaults; | |
| 2230 | + | |
| 2231 | + defaults = i915_gem_object_pin_map(engine->default_state, | |
| 2232 | + I915_MAP_WB); | |
| 2233 | + if (IS_ERR(defaults)) | |
| 2234 | + return PTR_ERR(defaults); | |
| 2235 | + | |
| 2236 | + memcpy(vaddr + start, defaults + start, engine->context_size); | |
| 2237 | + i915_gem_object_unpin_map(engine->default_state); | |
| 2238 | + } | |
| 2239 | + | |
| 2202 | 2240 | /* The second page of the context object contains some fields which must |
| 2203 | 2241 | * be set up prior to the first execution. */ |
| 2204 | − | |
| 2205 | − execlists_init_reg_state(vaddr + LRC_STATE_PN * PAGE_SIZE, | |
| 2206 | − ctx, engine, ring); | |
| 2242 | + regs = vaddr + LRC_STATE_PN * PAGE_SIZE; | |
| 2243 | + execlists_init_reg_state(regs, ctx, engine, ring); | |
| 2244 | + if (!engine->default_state) | |
| 2245 | + regs[CTX_CONTEXT_CONTROL + 1] |= | |
| 2246 | + _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); | |
| 2207 | 2247 | |
| 2208 | 2248 | i915_gem_object_unpin_map(ctx_obj); |
| 2209 | 2249 | |
| @@ -2256,7 +2296,6 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, · 46 unmodified lines | ||
| 2256 | 2296 | |
| 2257 | 2297 | ce->ring = ring; |
| 2258 | 2298 | ce->state = vma; |
| 2259 | − ce->initialised |= engine->init_context == NULL; | |
| 2260 | 2299 | |
| 2261 | 2300 | return 0; |
| 2262 | 2301 | |
| @@ -107,7 +107,6 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx, · 106 unmodified lines | ||
| 107 | 107 | return ctx->engine[engine->id].lrc_desc; |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | − | |
| 111 | 110 | /* Execlists */ |
| 112 | 111 | int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, |
| 113 | 112 | int enable_execlists); |
| @@ -125,6 +125,8 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, · 124 unmodified lines | ||
| 125 | 125 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); |
| 126 | 126 | u32 tmp, flags = 0; |
| 127 | 127 | |
| 128 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_LVDS); | |
| 129 | + | |
| 128 | 130 | tmp = I915_READ(lvds_encoder->reg); |
| 129 | 131 | if (tmp & LVDS_HSYNC_POLARITY) |
| 130 | 132 | flags |= DRM_MODE_FLAG_NHSYNC; |
| @@ -367,7 +367,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, · 366 unmodified lines | ||
| 367 | 367 | if (intel_encoder->type == INTEL_OUTPUT_DSI) |
| 368 | 368 | port = 0; |
| 369 | 369 | else |
| 370 | − port = intel_ddi_get_encoder_port(intel_encoder); | |
| 370 | + port = intel_encoder->port; | |
| 371 | 371 | |
| 372 | 372 | if (port == PORT_E) { |
| 373 | 373 | port = 0; |
| @@ -383,7 +383,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, · 9 unmodified lines | ||
| 383 | 383 | case INTEL_OUTPUT_ANALOG: |
| 384 | 384 | type = DISPLAY_TYPE_CRT; |
| 385 | 385 | break; |
| 386 | − case INTEL_OUTPUT_UNKNOWN: | |
| 386 | + case INTEL_OUTPUT_DDI: | |
| 387 | 387 | case INTEL_OUTPUT_DP: |
| 388 | 388 | case INTEL_OUTPUT_HDMI: |
| 389 | 389 | case INTEL_OUTPUT_DP_MST: |
| @@ -269,7 +269,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, · 268 unmodified lines | ||
| 269 | 269 | case INTEL_OUTPUT_DP: |
| 270 | 270 | case INTEL_OUTPUT_EDP: |
| 271 | 271 | dig_port = enc_to_dig_port(&encoder->base); |
| 272 | − switch (dig_port->port) { | |
| 272 | + switch (dig_port->base.port) { | |
| 273 | 273 | case PORT_B: |
| 274 | 274 | *source = INTEL_PIPE_CRC_SOURCE_DP_B; |
| 275 | 275 | break; |
| @@ -281,7 +281,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, · 5 unmodified lines | ||
| 281 | 281 | break; |
| 282 | 282 | default: |
| 283 | 283 | WARN(1, "nonexisting DP port %c\n", |
| 284 | − port_name(dig_port->port)); | |
| 284 | + port_name(dig_port->base.port)); | |
| 285 | 285 | break; |
| 286 | 286 | } |
| 287 | 287 | break; |
| @@ -75,9 +75,6 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) · 74 unmodified lines | ||
| 75 | 75 | I915_WRITE(CHICKEN_PAR1_1, |
| 76 | 76 | I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP); |
| 77 | 77 | |
| 78 | − I915_WRITE(GEN8_CONFIG0, | |
| 79 | − I915_READ(GEN8_CONFIG0) | GEN9_DEFAULT_FIXES); | |
| 80 | − | |
| 81 | 78 | /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */ |
| 82 | 79 | I915_WRITE(GEN8_CHICKEN_DCPR_1, |
| 83 | 80 | I915_READ(GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM); |
| @@ -124,7 +121,6 @@ static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) · 40 unmodified lines | ||
| 124 | 121 | |
| 125 | 122 | static void glk_init_clock_gating(struct drm_i915_private *dev_priv) |
| 126 | 123 | { |
| 127 | − u32 val; | |
| 128 | 124 | gen9_init_clock_gating(dev_priv); |
| 129 | 125 | |
| 130 | 126 | /* |
| @@ -144,11 +140,6 @@ static void glk_init_clock_gating(struct drm_i915_private *dev_priv) · 13 unmodified lines | ||
| 144 | 140 | I915_WRITE(CHICKEN_MISC_2, val); |
| 145 | 141 | } |
| 146 | 142 | |
| 147 | − /* Display WA #1133: WaFbcSkipSegments:glk */ | |
| 148 | − val = I915_READ(ILK_DPFC_CHICKEN); | |
| 149 | − val &= ~GLK_SKIP_SEG_COUNT_MASK; | |
| 150 | − val |= GLK_SKIP_SEG_EN | GLK_SKIP_SEG_COUNT(1); | |
| 151 | − I915_WRITE(ILK_DPFC_CHICKEN, val); | |
| 152 | 143 | } |
| 153 | 144 | |
| 154 | 145 | static void i915_pineview_get_mem_freq(struct drm_i915_private *dev_priv) |
| @@ -928,7 +919,7 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) · 773 unmodified lines | ||
| 928 | 919 | * and the size of 8 whole lines. This adjustment is always performed |
| 929 | 920 | * in the actual pixel depth regardless of whether FBC is enabled or not." |
| 930 | 921 | */ |
| 931 | −static int g4x_tlb_miss_wa(int fifo_size, int width, int cpp) | |
| 922 | +static unsigned int g4x_tlb_miss_wa(int fifo_size, int width, int cpp) | |
| 932 | 923 | { |
| 933 | 924 | int tlb_miss = fifo_size * 64 - width * cpp * 8; |
| 934 | 925 | |
| @@ -1105,8 +1096,8 @@ static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state, · 170 unmodified lines | ||
| 1105 | 1096 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
| 1106 | 1097 | const struct drm_display_mode *adjusted_mode = |
| 1107 | 1098 | &crtc_state->base.adjusted_mode; |
| 1108 | − int clock, htotal, cpp, width, wm; | |
| 1109 | − int latency = dev_priv->wm.pri_latency[level] * 10; | |
| 1099 | + unsigned int latency = dev_priv->wm.pri_latency[level] * 10; | |
| 1100 | + unsigned int clock, htotal, cpp, width, wm; | |
| 1110 | 1101 | |
| 1111 | 1102 | if (latency == 0) |
| 1112 | 1103 | return USHRT_MAX; |
| @@ -1145,7 +1136,7 @@ static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state, · 32 unmodified lines | ||
| 1145 | 1136 | level == G4X_WM_LEVEL_NORMAL) { |
| 1146 | 1137 | wm = intel_wm_method1(clock, cpp, latency); |
| 1147 | 1138 | } else { |
| 1148 | − int small, large; | |
| 1139 | + unsigned int small, large; | |
| 1149 | 1140 | |
| 1150 | 1141 | small = intel_wm_method1(clock, cpp, latency); |
| 1151 | 1142 | large = intel_wm_method2(clock, htotal, width, cpp, latency); |
| @@ -1158,7 +1149,7 @@ static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state, · 6 unmodified lines | ||
| 1158 | 1149 | |
| 1159 | 1150 | wm = DIV_ROUND_UP(wm, 64) + 2; |
| 1160 | 1151 | |
| 1161 | − return min_t(int, wm, USHRT_MAX); | |
| 1152 | + return min_t(unsigned int, wm, USHRT_MAX); | |
| 1162 | 1153 | } |
| 1163 | 1154 | |
| 1164 | 1155 | static bool g4x_raw_plane_wm_set(struct intel_crtc_state *crtc_state, |
| @@ -1409,17 +1400,29 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) · 244 unmodified lines | ||
| 1409 | 1400 | |
| 1410 | 1401 | static int g4x_compute_intermediate_wm(struct drm_device *dev, |
| 1411 | 1402 | struct intel_crtc *crtc, |
| 1412 | − struct intel_crtc_state *crtc_state) | |
| 1403 | + struct intel_crtc_state *new_crtc_state) | |
| 1413 | 1404 | { |
| 1414 | − struct g4x_wm_state *intermediate = &crtc_state->wm.g4x.intermediate; | |
| 1415 | − const struct g4x_wm_state *optimal = &crtc_state->wm.g4x.optimal; | |
| 1416 | − const struct g4x_wm_state *active = &crtc->wm.active.g4x; | |
| 1405 | + struct g4x_wm_state *intermediate = &new_crtc_state->wm.g4x.intermediate; | |
| 1406 | + const struct g4x_wm_state *optimal = &new_crtc_state->wm.g4x.optimal; | |
| 1407 | + struct intel_atomic_state *intel_state = | |
| 1408 | + to_intel_atomic_state(new_crtc_state->base.state); | |
| 1409 | + const struct intel_crtc_state *old_crtc_state = | |
| 1410 | + intel_atomic_get_old_crtc_state(intel_state, crtc); | |
| 1411 | + const struct g4x_wm_state *active = &old_crtc_state->wm.g4x.optimal; | |
| 1417 | 1412 | enum plane_id plane_id; |
| 1418 | 1413 | |
| 1414 | + if (!new_crtc_state->base.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { | |
| 1415 | + *intermediate = *optimal; | |
| 1416 | + | |
| 1417 | + intermediate->cxsr = false; | |
| 1418 | + intermediate->hpll_en = false; | |
| 1419 | + goto out; | |
| 1420 | + } | |
| 1421 | + | |
| 1419 | 1422 | intermediate->cxsr = optimal->cxsr && active->cxsr && |
| 1420 | − !crtc_state->disable_cxsr; | |
| 1423 | + !new_crtc_state->disable_cxsr; | |
| 1421 | 1424 | intermediate->hpll_en = optimal->hpll_en && active->hpll_en && |
| 1422 | − !crtc_state->disable_cxsr; | |
| 1425 | + !new_crtc_state->disable_cxsr; | |
| 1423 | 1426 | intermediate->fbc_en = optimal->fbc_en && active->fbc_en; |
| 1424 | 1427 | |
| 1425 | 1428 | for_each_plane_id_on_crtc(crtc, plane_id) { |
| @@ -1461,12 +1464,13 @@ static int g4x_compute_intermediate_wm(struct drm_device *dev, · 35 unmodified lines | ||
| 1461 | 1464 | WARN_ON(intermediate->hpll.fbc > g4x_fbc_fifo_size(2) && |
| 1462 | 1465 | intermediate->fbc_en && intermediate->hpll_en); |
| 1463 | 1466 | |
| 1467 | +out: | |
| 1464 | 1468 | /* |
| 1465 | 1469 | * If our intermediate WM are identical to the final WM, then we can |
| 1466 | 1470 | * omit the post-vblank programming; only update if it's different. |
| 1467 | 1471 | */ |
| 1468 | 1472 | if (memcmp(intermediate, optimal, sizeof(*intermediate)) != 0) |
| 1469 | − crtc_state->wm.need_postvbl_update = true; | |
| 1473 | + new_crtc_state->wm.need_postvbl_update = true; | |
| 1470 | 1474 | |
| 1471 | 1475 | return 0; |
| 1472 | 1476 | } |
| @@ -1602,7 +1606,7 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, · 129 unmodified lines | ||
| 1602 | 1606 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
| 1603 | 1607 | const struct drm_display_mode *adjusted_mode = |
| 1604 | 1608 | &crtc_state->base.adjusted_mode; |
| 1605 | − int clock, htotal, cpp, width, wm; | |
| 1609 | + unsigned int clock, htotal, cpp, width, wm; | |
| 1606 | 1610 | |
| 1607 | 1611 | if (dev_priv->wm.pri_latency[level] == 0) |
| 1608 | 1612 | return USHRT_MAX; |
| @@ -1628,7 +1632,7 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, · 19 unmodified lines | ||
| 1628 | 1632 | dev_priv->wm.pri_latency[level] * 10); |
| 1629 | 1633 | } |
| 1630 | 1634 | |
| 1631 | − return min_t(int, wm, USHRT_MAX); | |
| 1635 | + return min_t(unsigned int, wm, USHRT_MAX); | |
| 1632 | 1636 | } |
| 1633 | 1637 | |
| 1634 | 1638 | static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes) |
| @@ -2029,16 +2033,27 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, · 394 unmodified lines | ||
| 2029 | 2033 | |
| 2030 | 2034 | static int vlv_compute_intermediate_wm(struct drm_device *dev, |
| 2031 | 2035 | struct intel_crtc *crtc, |
| 2032 | − struct intel_crtc_state *crtc_state) | |
| 2036 | + struct intel_crtc_state *new_crtc_state) | |
| 2033 | 2037 | { |
| 2034 | − struct vlv_wm_state *intermediate = &crtc_state->wm.vlv.intermediate; | |
| 2035 | − const struct vlv_wm_state *optimal = &crtc_state->wm.vlv.optimal; | |
| 2036 | − const struct vlv_wm_state *active = &crtc->wm.active.vlv; | |
| 2038 | + struct vlv_wm_state *intermediate = &new_crtc_state->wm.vlv.intermediate; | |
| 2039 | + const struct vlv_wm_state *optimal = &new_crtc_state->wm.vlv.optimal; | |
| 2040 | + struct intel_atomic_state *intel_state = | |
| 2041 | + to_intel_atomic_state(new_crtc_state->base.state); | |
| 2042 | + const struct intel_crtc_state *old_crtc_state = | |
| 2043 | + intel_atomic_get_old_crtc_state(intel_state, crtc); | |
| 2044 | + const struct vlv_wm_state *active = &old_crtc_state->wm.vlv.optimal; | |
| 2037 | 2045 | int level; |
| 2038 | 2046 | |
| 2047 | + if (!new_crtc_state->base.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { | |
| 2048 | + *intermediate = *optimal; | |
| 2049 | + | |
| 2050 | + intermediate->cxsr = false; | |
| 2051 | + goto out; | |
| 2052 | + } | |
| 2053 | + | |
| 2039 | 2054 | intermediate->num_levels = min(optimal->num_levels, active->num_levels); |
| 2040 | 2055 | intermediate->cxsr = optimal->cxsr && active->cxsr && |
| 2041 | − !crtc_state->disable_cxsr; | |
| 2056 | + !new_crtc_state->disable_cxsr; | |
| 2042 | 2057 | |
| 2043 | 2058 | for (level = 0; level < intermediate->num_levels; level++) { |
| 2044 | 2059 | enum plane_id plane_id; |
| @@ -2057,12 +2072,13 @@ static int vlv_compute_intermediate_wm(struct drm_device *dev, · 12 unmodified lines | ||
| 2057 | 2072 | |
| 2058 | 2073 | vlv_invalidate_wms(crtc, intermediate, level); |
| 2059 | 2074 | |
| 2075 | +out: | |
| 2060 | 2076 | /* |
| 2061 | 2077 | * If our intermediate WM are identical to the final WM, then we can |
| 2062 | 2078 | * omit the post-vblank programming; only update if it's different. |
| 2063 | 2079 | */ |
| 2064 | 2080 | if (memcmp(intermediate, optimal, sizeof(*intermediate)) != 0) |
| 2065 | − crtc_state->wm.need_postvbl_update = true; | |
| 2081 | + new_crtc_state->wm.need_postvbl_update = true; | |
| 2066 | 2082 | |
| 2067 | 2083 | return 0; |
| 2068 | 2084 | } |
| @@ -3930,6 +3946,7 @@ skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state) · 1861 unmodified lines | ||
| 3930 | 3946 | int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, |
| 3931 | 3947 | struct intel_crtc_state *cstate) |
| 3932 | 3948 | { |
| 3949 | + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | |
| 3933 | 3950 | struct drm_crtc_state *crtc_state = &cstate->base; |
| 3934 | 3951 | struct drm_atomic_state *state = crtc_state->state; |
| 3935 | 3952 | struct drm_plane *plane; |
| @@ -3972,7 +3989,7 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, · 36 unmodified lines | ||
| 3972 | 3989 | crtc_clock = crtc_state->adjusted_mode.crtc_clock; |
| 3973 | 3990 | dotclk = to_intel_atomic_state(state)->cdclk.logical.cdclk; |
| 3974 | 3991 | |
| 3975 | − if (IS_GEMINILAKE(to_i915(intel_crtc->base.dev))) | |
| 3992 | + if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) | |
| 3976 | 3993 | dotclk *= 2; |
| 3977 | 3994 | |
| 3978 | 3995 | pipe_max_pixel_rate = div_round_up_u32_fixed16(dotclk, pipe_downscale); |
| @@ -6620,12 +6637,19 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) · 2641 unmodified lines | ||
| 6620 | 6637 | I915_WRITE(GEN6_RC_CONTROL, 0); |
| 6621 | 6638 | |
| 6622 | 6639 | /* 2b: Program RC6 thresholds.*/ |
| 6623 | − | |
| 6624 | − /* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */ | |
| 6625 | − if (IS_SKYLAKE(dev_priv)) | |
| 6640 | + if (INTEL_GEN(dev_priv) >= 10) { | |
| 6641 | + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85); | |
| 6642 | + I915_WRITE(GEN10_MEDIA_WAKE_RATE_LIMIT, 150); | |
| 6643 | + } else if (IS_SKYLAKE(dev_priv)) { | |
| 6644 | + /* | |
| 6645 | + * WaRsDoubleRc6WrlWithCoarsePowerGating:skl Doubling WRL only | |
| 6646 | + * when CPG is enabled | |
| 6647 | + */ | |
| 6626 | 6648 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16); |
| 6627 | − else | |
| 6649 | + } else { | |
| 6628 | 6650 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); |
| 6651 | + } | |
| 6652 | + | |
| 6629 | 6653 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ |
| 6630 | 6654 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ |
| 6631 | 6655 | for_each_engine(engine, dev_priv, id) |
| @@ -7910,7 +7934,6 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) · 1278 unmodified lines | ||
| 7910 | 7934 | intel_runtime_pm_get(dev_priv); |
| 7911 | 7935 | } |
| 7912 | 7936 | |
| 7913 | − mutex_lock(&dev_priv->drm.struct_mutex); | |
| 7914 | 7937 | mutex_lock(&dev_priv->pcu_lock); |
| 7915 | 7938 | |
| 7916 | 7939 | /* Initialize RPS limits (for userspace) */ |
| @@ -7952,9 +7975,6 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) · 35 unmodified lines | ||
| 7952 | 7975 | rps->boost_freq = rps->max_freq; |
| 7953 | 7976 | |
| 7954 | 7977 | mutex_unlock(&dev_priv->pcu_lock); |
| 7955 | − mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 7956 | − | |
| 7957 | − intel_autoenable_gt_powersave(dev_priv); | |
| 7958 | 7978 | } |
| 7959 | 7979 | |
| 7960 | 7980 | void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv) |
| @@ -7979,9 +7999,6 @@ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv) · 18 unmodified lines | ||
| 7979 | 7999 | if (INTEL_GEN(dev_priv) < 6) |
| 7980 | 8000 | return; |
| 7981 | 8001 | |
| 7982 | − if (cancel_delayed_work_sync(&dev_priv->gt_pm.autoenable_work)) | |
| 7983 | − intel_runtime_pm_put(dev_priv); | |
| 7984 | − | |
| 7985 | 8002 | /* gen6_rps_idle() will be called later to disable interrupts */ |
| 7986 | 8003 | } |
| 7987 | 8004 | |
| @@ -8140,65 +8157,6 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv) · 152 unmodified lines | ||
| 8140 | 8157 | mutex_unlock(&dev_priv->pcu_lock); |
| 8141 | 8158 | } |
| 8142 | 8159 | |
| 8143 | −static void __intel_autoenable_gt_powersave(struct work_struct *work) | |
| 8144 | −{ | |
| 8145 | − struct drm_i915_private *dev_priv = | |
| 8146 | − container_of(work, | |
| 8147 | − typeof(*dev_priv), | |
| 8148 | − gt_pm.autoenable_work.work); | |
| 8149 | − struct intel_engine_cs *rcs; | |
| 8150 | − struct drm_i915_gem_request *req; | |
| 8151 | − | |
| 8152 | − rcs = dev_priv->engine[RCS]; | |
| 8153 | − if (rcs->last_retired_context) | |
| 8154 | − goto out; | |
| 8155 | − | |
| 8156 | − if (!rcs->init_context) | |
| 8157 | − goto out; | |
| 8158 | − | |
| 8159 | − mutex_lock(&dev_priv->drm.struct_mutex); | |
| 8160 | − | |
| 8161 | − req = i915_gem_request_alloc(rcs, dev_priv->kernel_context); | |
| 8162 | − if (IS_ERR(req)) | |
| 8163 | − goto unlock; | |
| 8164 | − | |
| 8165 | − if (!i915_modparams.enable_execlists && i915_switch_context(req) == 0) | |
| 8166 | − rcs->init_context(req); | |
| 8167 | − | |
| 8168 | − /* Mark the device busy, calling intel_enable_gt_powersave() */ | |
| 8169 | − i915_add_request(req); | |
| 8170 | − | |
| 8171 | −unlock: | |
| 8172 | − mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 8173 | −out: | |
| 8174 | − intel_runtime_pm_put(dev_priv); | |
| 8175 | −} | |
| 8176 | − | |
| 8177 | −void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv) | |
| 8178 | −{ | |
| 8179 | − if (IS_IRONLAKE_M(dev_priv)) { | |
| 8180 | − ironlake_enable_drps(dev_priv); | |
| 8181 | − intel_init_emon(dev_priv); | |
| 8182 | − } else if (INTEL_INFO(dev_priv)->gen >= 6) { | |
| 8183 | − /* | |
| 8184 | − * PCU communication is slow and this doesn't need to be | |
| 8185 | − * done at any specific time, so do this out of our fast path | |
| 8186 | − * to make resume and init faster. | |
| 8187 | − * | |
| 8188 | − * We depend on the HW RC6 power context save/restore | |
| 8189 | − * mechanism when entering D3 through runtime PM suspend. So | |
| 8190 | − * disable RPM until RPS/RC6 is properly setup. We can only | |
| 8191 | − * get here via the driver load/system resume/runtime resume | |
| 8192 | − * paths, so the _noresume version is enough (and in case of | |
| 8193 | − * runtime resume it's necessary). | |
| 8194 | − */ | |
| 8195 | − if (queue_delayed_work(dev_priv->wq, | |
| 8196 | − &dev_priv->gt_pm.autoenable_work, | |
| 8197 | − round_jiffies_up_relative(HZ))) | |
| 8198 | − intel_runtime_pm_get_noresume(dev_priv); | |
| 8199 | − } | |
| 8200 | −} | |
| 8201 | − | |
| 8202 | 8160 | static void ibx_init_clock_gating(struct drm_i915_private *dev_priv) |
| 8203 | 8161 | { |
| 8204 | 8162 | /* |
| @@ -8532,17 +8490,13 @@ static void cnl_init_clock_gating(struct drm_i915_private *dev_priv) · 327 unmodified lines | ||
| 8532 | 8490 | I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | |
| 8533 | 8491 | DISP_FBC_MEMORY_WAKE); |
| 8534 | 8492 | |
| 8493 | + val = I915_READ(SLICE_UNIT_LEVEL_CLKGATE); | |
| 8494 | + /* ReadHitWriteOnlyDisable:cnl */ | |
| 8495 | + val |= RCCUNIT_CLKGATE_DIS; | |
| 8535 | 8496 | /* WaSarbUnitClockGatingDisable:cnl (pre-prod) */ |
| 8536 | 8497 | if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) |
| 8537 | − I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, | |
| 8538 | − I915_READ(SLICE_UNIT_LEVEL_CLKGATE) | | |
| 8539 | − SARBUNIT_CLKGATE_DIS); | |
| 8540 | − | |
| 8541 | − /* Display WA #1133: WaFbcSkipSegments:cnl */ | |
| 8542 | − val = I915_READ(ILK_DPFC_CHICKEN); | |
| 8543 | − val &= ~GLK_SKIP_SEG_COUNT_MASK; | |
| 8544 | − val |= GLK_SKIP_SEG_EN | GLK_SKIP_SEG_COUNT(1); | |
| 8545 | − I915_WRITE(ILK_DPFC_CHICKEN, val); | |
| 8498 | + val |= SARBUNIT_CLKGATE_DIS; | |
| 8499 | + I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, val); | |
| 8546 | 8500 | } |
| 8547 | 8501 | |
| 8548 | 8502 | static void cfl_init_clock_gating(struct drm_i915_private *dev_priv) |
| @@ -9429,8 +9383,6 @@ void intel_pm_setup(struct drm_i915_private *dev_priv) · 880 unmodified lines | ||
| 9429 | 9383 | { |
| 9430 | 9384 | mutex_init(&dev_priv->pcu_lock); |
| 9431 | 9385 | |
| 9432 | − INIT_DELAYED_WORK(&dev_priv->gt_pm.autoenable_work, | |
| 9433 | − __intel_autoenable_gt_powersave); | |
| 9434 | 9386 | atomic_set(&dev_priv->gt_pm.rps.num_waiters, 0); |
| 9435 | 9387 | |
| 9436 | 9388 | dev_priv->runtime_pm.suspended = false; |
| @@ -163,7 +163,7 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) · 162 unmodified lines | ||
| 163 | 163 | [3] = 1 - 1, |
| 164 | 164 | [4] = DP_SET_POWER_D0, |
| 165 | 165 | }; |
| 166 | − enum port port = dig_port->port; | |
| 166 | + enum port port = dig_port->base.port; | |
| 167 | 167 | u32 aux_ctl; |
| 168 | 168 | int i; |
| 169 | 169 | |
| @@ -376,7 +376,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, · 206 unmodified lines | ||
| 376 | 376 | * ones. Since by Display design transcoder EDP is tied to port A |
| 377 | 377 | * we can safely escape based on the port A. |
| 378 | 378 | */ |
| 379 | − if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) { | |
| 379 | + if (HAS_DDI(dev_priv) && dig_port->base.port != PORT_A) { | |
| 380 | 380 | DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); |
| 381 | 381 | return; |
| 382 | 382 | } |
| @@ -28,9 +28,12 @@ · 27 unmodified lines | ||
| 28 | 28 | */ |
| 29 | 29 | |
| 30 | 30 | #include <linux/log2.h> |
| 31 | + | |
| 31 | 32 | #include <drm/drmP.h> |
| 32 | −#include "i915_drv.h" | |
| 33 | 33 | #include <drm/i915_drm.h> |
| 34 | + | |
| 35 | +#include "i915_drv.h" | |
| 36 | +#include "i915_gem_render_state.h" | |
| 34 | 37 | #include "i915_trace.h" |
| 35 | 38 | #include "intel_drv.h" |
| 36 | 39 | |
| @@ -480,10 +483,14 @@ static bool stop_ring(struct intel_engine_cs *engine) · 443 unmodified lines | ||
| 480 | 483 | } |
| 481 | 484 | } |
| 482 | 485 | |
| 483 | − I915_WRITE_CTL(engine, 0); | |
| 486 | + I915_WRITE_HEAD(engine, I915_READ_TAIL(engine)); | |
| 487 | + | |
| 484 | 488 | I915_WRITE_HEAD(engine, 0); |
| 485 | 489 | I915_WRITE_TAIL(engine, 0); |
| 486 | 490 | |
| 491 | + /* The ring must be empty before it is disabled */ | |
| 492 | + I915_WRITE_CTL(engine, 0); | |
| 493 | + | |
| 487 | 494 | return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; |
| 488 | 495 | } |
| 489 | 496 | |
| @@ -1359,12 +1366,13 @@ static int context_pin(struct i915_gem_context *ctx) · 869 unmodified lines | ||
| 1359 | 1366 | struct i915_vma *vma = ctx->engine[RCS].state; |
| 1360 | 1367 | int ret; |
| 1361 | 1368 | |
| 1362 | − /* Clear this page out of any CPU caches for coherent swap-in/out. | |
| 1369 | + /* | |
| 1370 | + * Clear this page out of any CPU caches for coherent swap-in/out. | |
| 1363 | 1371 | * We only want to do this on the first bind so that we do not stall |
| 1364 | 1372 | * on an active context (which by nature is already on the GPU). |
| 1365 | 1373 | */ |
| 1366 | 1374 | if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { |
| 1367 | − ret = i915_gem_object_set_to_gtt_domain(vma->obj, false); | |
| 1375 | + ret = i915_gem_object_set_to_gtt_domain(vma->obj, true); | |
| 1368 | 1376 | if (ret) |
| 1369 | 1377 | return ret; |
| 1370 | 1378 | } |
| @@ -1379,11 +1387,34 @@ alloc_context_vma(struct intel_engine_cs *engine) · 8 unmodified lines | ||
| 1379 | 1387 | struct drm_i915_private *i915 = engine->i915; |
| 1380 | 1388 | struct drm_i915_gem_object *obj; |
| 1381 | 1389 | struct i915_vma *vma; |
| 1390 | + int err; | |
| 1382 | 1391 | |
| 1383 | 1392 | obj = i915_gem_object_create(i915, engine->context_size); |
| 1384 | 1393 | if (IS_ERR(obj)) |
| 1385 | 1394 | return ERR_CAST(obj); |
| 1386 | 1395 | |
| 1396 | + if (engine->default_state) { | |
| 1397 | + void *defaults, *vaddr; | |
| 1398 | + | |
| 1399 | + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); | |
| 1400 | + if (IS_ERR(vaddr)) { | |
| 1401 | + err = PTR_ERR(vaddr); | |
| 1402 | + goto err_obj; | |
| 1403 | + } | |
| 1404 | + | |
| 1405 | + defaults = i915_gem_object_pin_map(engine->default_state, | |
| 1406 | + I915_MAP_WB); | |
| 1407 | + if (IS_ERR(defaults)) { | |
| 1408 | + err = PTR_ERR(defaults); | |
| 1409 | + goto err_map; | |
| 1410 | + } | |
| 1411 | + | |
| 1412 | + memcpy(vaddr, defaults, engine->context_size); | |
| 1413 | + | |
| 1414 | + i915_gem_object_unpin_map(engine->default_state); | |
| 1415 | + i915_gem_object_unpin_map(obj); | |
| 1416 | + } | |
| 1417 | + | |
| 1387 | 1418 | /* |
| 1388 | 1419 | * Try to make the context utilize L3 as well as LLC. |
| 1389 | 1420 | * |
| @@ -1405,10 +1436,18 @@ alloc_context_vma(struct intel_engine_cs *engine) · 15 unmodified lines | ||
| 1405 | 1436 | } |
| 1406 | 1437 | |
| 1407 | 1438 | vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); |
| 1408 | − if (IS_ERR(vma)) | |
| 1409 | − i915_gem_object_put(obj); | |
| 1439 | + if (IS_ERR(vma)) { | |
| 1440 | + err = PTR_ERR(vma); | |
| 1441 | + goto err_obj; | |
| 1442 | + } | |
| 1410 | 1443 | |
| 1411 | 1444 | return vma; |
| 1445 | + | |
| 1446 | +err_map: | |
| 1447 | + i915_gem_object_unpin_map(obj); | |
| 1448 | +err_obj: | |
| 1449 | + i915_gem_object_put(obj); | |
| 1450 | + return ERR_PTR(err); | |
| 1412 | 1451 | } |
| 1413 | 1452 | |
| 1414 | 1453 | static struct intel_ring * |
| @@ -1441,20 +1480,9 @@ intel_ring_context_pin(struct intel_engine_cs *engine, · 26 unmodified lines | ||
| 1441 | 1480 | if (ret) |
| 1442 | 1481 | goto err; |
| 1443 | 1482 | |
| 1444 | − ce->state->obj->mm.dirty = true; | |
| 1445 | 1483 | ce->state->obj->pin_global++; |
| 1446 | 1484 | } |
| 1447 | 1485 | |
| 1448 | − /* The kernel context is only used as a placeholder for flushing the | |
| 1449 | − * active context. It is never used for submitting user rendering and | |
| 1450 | − * as such never requires the golden render context, and so we can skip | |
| 1451 | − * emitting it when we switch to the kernel context. This is required | |
| 1452 | − * as during eviction we cannot allocate and pin the renderstate in | |
| 1453 | − * order to initialise the context. | |
| 1454 | − */ | |
| 1455 | − if (i915_gem_context_is_kernel(ctx)) | |
| 1456 | − ce->initialised = true; | |
| 1457 | − | |
| 1458 | 1486 | i915_gem_context_get(ctx); |
| 1459 | 1487 | |
| 1460 | 1488 | out: |
| @@ -1550,7 +1578,7 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) · 89 unmodified lines | ||
| 1550 | 1578 | |
| 1551 | 1579 | static int ring_request_alloc(struct drm_i915_gem_request *request) |
| 1552 | 1580 | { |
| 1553 | − u32 *cs; | |
| 1581 | + int ret; | |
| 1554 | 1582 | |
| 1555 | 1583 | GEM_BUG_ON(!request->ctx->engine[request->engine->id].pin_count); |
| 1556 | 1584 | |
| @@ -1560,37 +1588,24 @@ static int ring_request_alloc(struct drm_i915_gem_request *request) · 3 unmodified lines | ||
| 1560 | 1588 | */ |
| 1561 | 1589 | request->reserved_space += LEGACY_REQUEST_SIZE; |
| 1562 | 1590 | |
| 1563 | − cs = intel_ring_begin(request, 0); | |
| 1564 | − if (IS_ERR(cs)) | |
| 1565 | − return PTR_ERR(cs); | |
| 1591 | + ret = intel_ring_wait_for_space(request->ring, request->reserved_space); | |
| 1592 | + if (ret) | |
| 1593 | + return ret; | |
| 1566 | 1594 | |
| 1567 | 1595 | request->reserved_space -= LEGACY_REQUEST_SIZE; |
| 1568 | 1596 | return 0; |
| 1569 | 1597 | } |
| 1570 | 1598 | |
| 1571 | −static noinline int wait_for_space(struct drm_i915_gem_request *req, | |
| 1572 | − unsigned int bytes) | |
| 1599 | +static noinline int wait_for_space(struct intel_ring *ring, unsigned int bytes) | |
| 1573 | 1600 | { |
| 1574 | − struct intel_ring *ring = req->ring; | |
| 1575 | 1601 | struct drm_i915_gem_request *target; |
| 1576 | 1602 | long timeout; |
| 1577 | 1603 | |
| 1578 | − lockdep_assert_held(&req->i915->drm.struct_mutex); | |
| 1604 | + lockdep_assert_held(&ring->vma->vm->i915->drm.struct_mutex); | |
| 1579 | 1605 | |
| 1580 | 1606 | if (intel_ring_update_space(ring) >= bytes) |
| 1581 | 1607 | return 0; |
| 1582 | 1608 | |
| 1583 | − /* | |
| 1584 | − * Space is reserved in the ringbuffer for finalising the request, | |
| 1585 | − * as that cannot be allowed to fail. During request finalisation, | |
| 1586 | − * reserved_space is set to 0 to stop the overallocation and the | |
| 1587 | − * assumption is that then we never need to wait (which has the | |
| 1588 | − * risk of failing with EINTR). | |
| 1589 | − * | |
| 1590 | − * See also i915_gem_request_alloc() and i915_add_request(). | |
| 1591 | − */ | |
| 1592 | − GEM_BUG_ON(!req->reserved_space); | |
| 1593 | − | |
| 1594 | 1609 | list_for_each_entry(target, &ring->request_list, ring_link) { |
| 1595 | 1610 | /* Would completion of this request free enough space? */ |
| 1596 | 1611 | if (bytes <= __intel_ring_space(target->postfix, |
| @@ -1614,6 +1629,22 @@ static noinline int wait_for_space(struct drm_i915_gem_request *req, · 17 unmodified lines | ||
| 1614 | 1629 | return 0; |
| 1615 | 1630 | } |
| 1616 | 1631 | |
| 1632 | +int intel_ring_wait_for_space(struct intel_ring *ring, unsigned int bytes) | |
| 1633 | +{ | |
| 1634 | + GEM_BUG_ON(bytes > ring->effective_size); | |
| 1635 | + if (unlikely(bytes > ring->effective_size - ring->emit)) | |
| 1636 | + bytes += ring->size - ring->emit; | |
| 1637 | + | |
| 1638 | + if (unlikely(bytes > ring->space)) { | |
| 1639 | + int ret = wait_for_space(ring, bytes); | |
| 1640 | + if (unlikely(ret)) | |
| 1641 | + return ret; | |
| 1642 | + } | |
| 1643 | + | |
| 1644 | + GEM_BUG_ON(ring->space < bytes); | |
| 1645 | + return 0; | |
| 1646 | +} | |
| 1647 | + | |
| 1617 | 1648 | u32 *intel_ring_begin(struct drm_i915_gem_request *req, |
| 1618 | 1649 | unsigned int num_dwords) |
| 1619 | 1650 | { |
| @@ -1653,7 +1684,20 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, · 33 unmodified lines | ||
| 1653 | 1684 | } |
| 1654 | 1685 | |
| 1655 | 1686 | if (unlikely(total_bytes > ring->space)) { |
| 1656 | − int ret = wait_for_space(req, total_bytes); | |
| 1687 | + int ret; | |
| 1688 | + | |
| 1689 | + /* | |
| 1690 | + * Space is reserved in the ringbuffer for finalising the | |
| 1691 | + * request, as that cannot be allowed to fail. During request | |
| 1692 | + * finalisation, reserved_space is set to 0 to stop the | |
| 1693 | + * overallocation and the assumption is that then we never need | |
| 1694 | + * to wait (which has the risk of failing with EINTR). | |
| 1695 | + * | |
| 1696 | + * See also i915_gem_request_alloc() and i915_add_request(). | |
| 1697 | + */ | |
| 1698 | + GEM_BUG_ON(!req->reserved_space); | |
| 1699 | + | |
| 1700 | + ret = wait_for_space(ring, total_bytes); | |
| 1657 | 1701 | if (unlikely(ret)) |
| 1658 | 1702 | return ERR_PTR(ret); |
| 1659 | 1703 | } |
| @@ -2028,12 +2072,15 @@ static void i9xx_set_default_submission(struct intel_engine_cs *engine) · 368 unmodified lines | ||
| 2028 | 2072 | { |
| 2029 | 2073 | engine->submit_request = i9xx_submit_request; |
| 2030 | 2074 | engine->cancel_requests = cancel_requests; |
| 2075 | + | |
| 2076 | + engine->park = NULL; | |
| 2077 | + engine->unpark = NULL; | |
| 2031 | 2078 | } |
| 2032 | 2079 | |
| 2033 | 2080 | static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) |
| 2034 | 2081 | { |
| 2082 | + i9xx_set_default_submission(engine); | |
| 2035 | 2083 | engine->submit_request = gen6_bsd_submit_request; |
| 2036 | − engine->cancel_requests = cancel_requests; | |
| 2037 | 2084 | } |
| 2038 | 2085 | |
| 2039 | 2086 | static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, |
| @@ -166,7 +166,6 @@ struct i915_ctx_workarounds { · 165 unmodified lines | ||
| 166 | 166 | }; |
| 167 | 167 | |
| 168 | 168 | struct drm_i915_gem_request; |
| 169 | −struct intel_render_state; | |
| 170 | 169 | |
| 171 | 170 | /* |
| 172 | 171 | * Engine IDs definitions. |
| @@ -195,9 +194,9 @@ struct i915_priolist { · 22 unmodified lines | ||
| 195 | 194 | */ |
| 196 | 195 | struct intel_engine_execlists { |
| 197 | 196 | /** |
| 198 | − * @irq_tasklet: softirq tasklet for bottom handler | |
| 197 | + * @tasklet: softirq tasklet for bottom handler | |
| 199 | 198 | */ |
| 200 | − struct tasklet_struct irq_tasklet; | |
| 199 | + struct tasklet_struct tasklet; | |
| 201 | 200 | |
| 202 | 201 | /** |
| 203 | 202 | * @default_priolist: priority list for I915_PRIORITY_NORMAL |
| @@ -290,11 +289,14 @@ struct intel_engine_execlists { · 86 unmodified lines | ||
| 290 | 289 | struct intel_engine_cs { |
| 291 | 290 | struct drm_i915_private *i915; |
| 292 | 291 | char name[INTEL_ENGINE_CS_MAX_NAME]; |
| 292 | + | |
| 293 | 293 | enum intel_engine_id id; |
| 294 | − unsigned int uabi_id; | |
| 295 | 294 | unsigned int hw_id; |
| 296 | 295 | unsigned int guc_id; |
| 297 | 296 | |
| 297 | + u8 uabi_id; | |
| 298 | + u8 uabi_class; | |
| 299 | + | |
| 298 | 300 | u8 class; |
| 299 | 301 | u8 instance; |
| 300 | 302 | u32 context_size; |
| @@ -304,7 +306,7 @@ struct intel_engine_cs { · 3 unmodified lines | ||
| 304 | 306 | struct intel_ring *buffer; |
| 305 | 307 | struct intel_timeline *timeline; |
| 306 | 308 | |
| 307 | − struct intel_render_state *render_state; | |
| 309 | + struct drm_i915_gem_object *default_state; | |
| 308 | 310 | |
| 309 | 311 | atomic_t irq_count; |
| 310 | 312 | unsigned long irq_posted; |
| @@ -340,9 +342,9 @@ struct intel_engine_cs { · 29 unmodified lines | ||
| 340 | 342 | struct timer_list hangcheck; /* detect missed interrupts */ |
| 341 | 343 | |
| 342 | 344 | unsigned int hangcheck_interrupts; |
| 345 | + unsigned int irq_enabled; | |
| 343 | 346 | |
| 344 | 347 | bool irq_armed : 1; |
| 345 | − bool irq_enabled : 1; | |
| 346 | 348 | I915_SELFTEST_DECLARE(bool mock : 1); |
| 347 | 349 | } breadcrumbs; |
| 348 | 350 | |
| @@ -366,6 +368,9 @@ struct intel_engine_cs { · 17 unmodified lines | ||
| 366 | 368 | void (*reset_hw)(struct intel_engine_cs *engine, |
| 367 | 369 | struct drm_i915_gem_request *req); |
| 368 | 370 | |
| 371 | + void (*park)(struct intel_engine_cs *engine); | |
| 372 | + void (*unpark)(struct intel_engine_cs *engine); | |
| 373 | + | |
| 369 | 374 | void (*set_default_submission)(struct intel_engine_cs *engine); |
| 370 | 375 | |
| 371 | 376 | struct intel_ring *(*context_pin)(struct intel_engine_cs *engine, |
| @@ -555,6 +560,12 @@ execlists_is_active(const struct intel_engine_execlists *execlists, · 183 unmodified lines | ||
| 555 | 560 | return test_bit(bit, (unsigned long *)&execlists->active); |
| 556 | 561 | } |
| 557 | 562 | |
| 563 | +void | |
| 564 | +execlists_cancel_port_requests(struct intel_engine_execlists * const execlists); | |
| 565 | + | |
| 566 | +void | |
| 567 | +execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists); | |
| 568 | + | |
| 558 | 569 | static inline unsigned int |
| 559 | 570 | execlists_num_ports(const struct intel_engine_execlists * const execlists) |
| 560 | 571 | { |
| @@ -624,6 +635,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) · 63 unmodified lines | ||
| 624 | 635 | */ |
| 625 | 636 | #define I915_GEM_HWS_INDEX 0x30 |
| 626 | 637 | #define I915_GEM_HWS_INDEX_ADDR (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT) |
| 638 | +#define I915_GEM_HWS_PREEMPT_INDEX 0x32 | |
| 639 | +#define I915_GEM_HWS_PREEMPT_ADDR (I915_GEM_HWS_PREEMPT_INDEX << MI_STORE_DWORD_INDEX_SHIFT) | |
| 627 | 640 | #define I915_GEM_HWS_SCRATCH_INDEX 0x40 |
| 628 | 641 | #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) |
| 629 | 642 | |
| @@ -648,6 +661,7 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv); · 18 unmodified lines | ||
| 648 | 661 | |
| 649 | 662 | int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req); |
| 650 | 663 | |
| 664 | +int intel_ring_wait_for_space(struct intel_ring *ring, unsigned int bytes); | |
| 651 | 665 | u32 __must_check *intel_ring_begin(struct drm_i915_gem_request *req, |
| 652 | 666 | unsigned int n); |
| 653 | 667 | |
| @@ -776,6 +790,11 @@ static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine) · 122 unmodified lines | ||
| 776 | 790 | return engine->status_page.ggtt_offset + I915_GEM_HWS_INDEX_ADDR; |
| 777 | 791 | } |
| 778 | 792 | |
| 793 | +static inline u32 intel_hws_preempt_done_address(struct intel_engine_cs *engine) | |
| 794 | +{ | |
| 795 | + return engine->status_page.ggtt_offset + I915_GEM_HWS_PREEMPT_ADDR; | |
| 796 | +} | |
| 797 | + | |
| 779 | 798 | /* intel_breadcrumbs.c -- user interrupt bottom-half for waiters */ |
| 780 | 799 | int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine); |
| 781 | 800 | |
| @@ -846,6 +865,9 @@ unsigned int intel_engine_wakeup(struct intel_engine_cs *engine); · 64 unmodified lines | ||
| 846 | 865 | #define ENGINE_WAKEUP_WAITER BIT(0) |
| 847 | 866 | #define ENGINE_WAKEUP_ASLEEP BIT(1) |
| 848 | 867 | |
| 868 | +void intel_engine_pin_breadcrumbs_irq(struct intel_engine_cs *engine); | |
| 869 | +void intel_engine_unpin_breadcrumbs_irq(struct intel_engine_cs *engine); | |
| 870 | + | |
| 849 | 871 | void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); |
| 850 | 872 | void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); |
| 851 | 873 | |
| @@ -864,11 +886,54 @@ static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset) · 12 unmodified lines | ||
| 864 | 886 | return batch + 6; |
| 865 | 887 | } |
| 866 | 888 | |
| 889 | +static inline u32 * | |
| 890 | +gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset) | |
| 891 | +{ | |
| 892 | + /* We're using qword write, offset should be aligned to 8 bytes. */ | |
| 893 | + GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8)); | |
| 894 | + | |
| 895 | + /* w/a for post sync ops following a GPGPU operation we | |
| 896 | + * need a prior CS_STALL, which is emitted by the flush | |
| 897 | + * following the batch. | |
| 898 | + */ | |
| 899 | + *cs++ = GFX_OP_PIPE_CONTROL(6); | |
| 900 | + *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | | |
| 901 | + PIPE_CONTROL_QW_WRITE; | |
| 902 | + *cs++ = gtt_offset; | |
| 903 | + *cs++ = 0; | |
| 904 | + *cs++ = value; | |
| 905 | + /* We're thrashing one dword of HWS. */ | |
| 906 | + *cs++ = 0; | |
| 907 | + | |
| 908 | + return cs; | |
| 909 | +} | |
| 910 | + | |
| 911 | +static inline u32 * | |
| 912 | +gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset) | |
| 913 | +{ | |
| 914 | + /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */ | |
| 915 | + GEM_BUG_ON(gtt_offset & (1 << 5)); | |
| 916 | + /* Offset should be aligned to 8 bytes for both (QW/DW) write types */ | |
| 917 | + GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8)); | |
| 918 | + | |
| 919 | + *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; | |
| 920 | + *cs++ = gtt_offset | MI_FLUSH_DW_USE_GTT; | |
| 921 | + *cs++ = 0; | |
| 922 | + *cs++ = value; | |
| 923 | + | |
| 924 | + return cs; | |
| 925 | +} | |
| 926 | + | |
| 867 | 927 | bool intel_engine_is_idle(struct intel_engine_cs *engine); |
| 868 | 928 | bool intel_engines_are_idle(struct drm_i915_private *dev_priv); |
| 869 | 929 | |
| 870 | −void intel_engines_mark_idle(struct drm_i915_private *i915); | |
| 930 | +bool intel_engine_has_kernel_context(const struct intel_engine_cs *engine); | |
| 931 | + | |
| 932 | +void intel_engines_park(struct drm_i915_private *i915); | |
| 933 | +void intel_engines_unpark(struct drm_i915_private *i915); | |
| 934 | + | |
| 871 | 935 | void intel_engines_reset_default_submission(struct drm_i915_private *i915); |
| 936 | +unsigned int intel_engines_has_context_isolation(struct drm_i915_private *i915); | |
| 872 | 937 | |
| 873 | 938 | bool intel_engine_can_store_dword(struct intel_engine_cs *engine); |
| 874 | 939 | |
| @@ -705,7 +705,8 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, · 704 unmodified lines | ||
| 705 | 705 | gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); |
| 706 | 706 | |
| 707 | 707 | dev_priv->display.get_cdclk(dev_priv, &cdclk_state); |
| 708 | − WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state)); | |
| 708 | + /* Can't read out voltage_level so can't use intel_cdclk_changed() */ | |
| 709 | + WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state)); | |
| 709 | 710 | |
| 710 | 711 | gen9_assert_dbuf_enabled(dev_priv); |
| 711 | 712 | |
| @@ -1429,6 +1429,8 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, · 1428 unmodified lines | ||
| 1429 | 1429 | u8 val; |
| 1430 | 1430 | bool ret; |
| 1431 | 1431 | |
| 1432 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_SDVO); | |
| 1433 | + | |
| 1432 | 1434 | sdvox = I915_READ(intel_sdvo->sdvo_reg); |
| 1433 | 1435 | |
| 1434 | 1436 | ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); |
| @@ -1510,7 +1512,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder, · 75 unmodified lines | ||
| 1510 | 1512 | { |
| 1511 | 1513 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1512 | 1514 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
| 1513 | − struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | |
| 1515 | + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | |
| 1514 | 1516 | u32 temp; |
| 1515 | 1517 | |
| 1516 | 1518 | intel_sdvo_set_active_outputs(intel_sdvo, 0); |
| @@ -1569,7 +1571,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, · 52 unmodified lines | ||
| 1569 | 1571 | struct drm_device *dev = encoder->base.dev; |
| 1570 | 1572 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1571 | 1573 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
| 1572 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 1574 | + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 1573 | 1575 | u32 temp; |
| 1574 | 1576 | bool input1, input2; |
| 1575 | 1577 | int i; |
| @@ -263,13 +263,9 @@ skl_update_plane(struct intel_plane *plane, · 262 unmodified lines | ||
| 263 | 263 | |
| 264 | 264 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
| 265 | 265 | |
| 266 | − if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { | |
| 266 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | |
| 267 | 267 | I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), |
| 268 | − PLANE_COLOR_PIPE_GAMMA_ENABLE | | |
| 269 | − PLANE_COLOR_PIPE_CSC_ENABLE | | |
| 270 | − PLANE_COLOR_PLANE_GAMMA_DISABLE); | |
| 271 | − } | |
| 272 | − | |
| 268 | + plane_state->color_ctl); | |
| 273 | 269 | if (key->flags) { |
| 274 | 270 | I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); |
| 275 | 271 | I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value); |
| @@ -978,6 +974,9 @@ intel_check_sprite_plane(struct intel_plane *plane, · 702 unmodified lines | ||
| 978 | 974 | state->ctl = g4x_sprite_ctl(crtc_state, state); |
| 979 | 975 | } |
| 980 | 976 | |
| 977 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | |
| 978 | + state->color_ctl = glk_plane_color_ctl(crtc_state, state); | |
| 979 | + | |
| 981 | 980 | return 0; |
| 982 | 981 | } |
| 983 | 982 | |
| @@ -822,7 +822,7 @@ intel_enable_tv(struct intel_encoder *encoder, · 821 unmodified lines | ||
| 822 | 822 | |
| 823 | 823 | /* Prevents vblank waits from timing out in intel_tv_detect_type() */ |
| 824 | 824 | intel_wait_for_vblank(dev_priv, |
| 825 | − to_intel_crtc(encoder->base.crtc)->pipe); | |
| 825 | + to_intel_crtc(pipe_config->base.crtc)->pipe); | |
| 826 | 826 | |
| 827 | 827 | I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); |
| 828 | 828 | } |
| @@ -868,6 +868,8 @@ static void · 39 unmodified lines | ||
| 868 | 868 | intel_tv_get_config(struct intel_encoder *encoder, |
| 869 | 869 | struct intel_crtc_state *pipe_config) |
| 870 | 870 | { |
| 871 | + pipe_config->output_types |= BIT(INTEL_OUTPUT_TVOUT); | |
| 872 | + | |
| 871 | 873 | pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; |
| 872 | 874 | } |
| 873 | 875 | |
| @@ -980,7 +982,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder, · 106 unmodified lines | ||
| 980 | 982 | const struct drm_connector_state *conn_state) |
| 981 | 983 | { |
| 982 | 984 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 983 | − struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | |
| 985 | + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); | |
| 984 | 986 | struct intel_tv *intel_tv = enc_to_tv(encoder); |
| 985 | 987 | const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state); |
| 986 | 988 | u32 tv_ctl; |
| @@ -23,8 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | 25 | #include "intel_uc.h" |
| 26 | +#include "intel_guc_submission.h" | |
| 26 | 27 | #include "i915_drv.h" |
| 27 | −#include "i915_guc_submission.h" | |
| 28 | 28 | |
| 29 | 29 | /* Reset GuC providing us with fresh state for both GuC and HuC. |
| 30 | 30 | */ |
| @@ -33,9 +33,9 @@ static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv) · 2 unmodified lines | ||
| 33 | 33 | int ret; |
| 34 | 34 | u32 guc_status; |
| 35 | 35 | |
| 36 | − ret = intel_guc_reset(dev_priv); | |
| 36 | + ret = intel_reset_guc(dev_priv); | |
| 37 | 37 | if (ret) { |
| 38 | − DRM_ERROR("GuC reset failed, ret = %d\n", ret); | |
| 38 | + DRM_ERROR("Failed to reset GuC, ret = %d\n", ret); | |
| 39 | 39 | return ret; |
| 40 | 40 | } |
| 41 | 41 | |
| @@ -168,7 +168,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) · 126 unmodified lines | ||
| 168 | 168 | * This is stuff we need to have available at fw load time |
| 169 | 169 | * if we are planning to enable submission later |
| 170 | 170 | */ |
| 171 | − ret = i915_guc_submission_init(dev_priv); | |
| 171 | + ret = intel_guc_submission_init(guc); | |
| 172 | 172 | if (ret) |
| 173 | 173 | goto err_guc; |
| 174 | 174 | } |
| @@ -217,7 +217,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) · 42 unmodified lines | ||
| 217 | 217 | if (i915_modparams.guc_log_level >= 0) |
| 218 | 218 | gen9_enable_guc_interrupts(dev_priv); |
| 219 | 219 | |
| 220 | − ret = i915_guc_submission_enable(dev_priv); | |
| 220 | + ret = intel_guc_submission_enable(guc); | |
| 221 | 221 | if (ret) |
| 222 | 222 | goto err_interrupts; |
| 223 | 223 | } |
| @@ -246,7 +246,7 @@ err_log_capture: · 22 unmodified lines | ||
| 246 | 246 | guc_capture_load_err_log(guc); |
| 247 | 247 | err_submission: |
| 248 | 248 | if (i915_modparams.enable_guc_submission) |
| 249 | − i915_guc_submission_fini(dev_priv); | |
| 249 | + intel_guc_submission_fini(guc); | |
| 250 | 250 | err_guc: |
| 251 | 251 | i915_ggtt_disable_guc(dev_priv); |
| 252 | 252 | |
| @@ -271,19 +271,21 @@ err_guc: · 18 unmodified lines | ||
| 271 | 271 | |
| 272 | 272 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv) |
| 273 | 273 | { |
| 274 | − guc_free_load_err_log(&dev_priv->guc); | |
| 274 | + struct intel_guc *guc = &dev_priv->guc; | |
| 275 | + | |
| 276 | + guc_free_load_err_log(guc); | |
| 275 | 277 | |
| 276 | 278 | if (!i915_modparams.enable_guc_loading) |
| 277 | 279 | return; |
| 278 | 280 | |
| 279 | 281 | if (i915_modparams.enable_guc_submission) |
| 280 | − i915_guc_submission_disable(dev_priv); | |
| 282 | + intel_guc_submission_disable(guc); | |
| 281 | 283 | |
| 282 | − guc_disable_communication(&dev_priv->guc); | |
| 284 | + guc_disable_communication(guc); | |
| 283 | 285 | |
| 284 | 286 | if (i915_modparams.enable_guc_submission) { |
| 285 | 287 | gen9_disable_guc_interrupts(dev_priv); |
| 286 | − i915_guc_submission_fini(dev_priv); | |
| 288 | + intel_guc_submission_fini(guc); | |
| 287 | 289 | } |
| 288 | 290 | |
| 289 | 291 | i915_ggtt_disable_guc(dev_priv); |
| @@ -299,7 +299,7 @@ void intel_uc_fw_fini(struct intel_uc_fw *uc_fw) · 298 unmodified lines | ||
| 299 | 299 | * |
| 300 | 300 | * Pretty printer for uC firmware. |
| 301 | 301 | */ |
| 302 | −void intel_uc_fw_dump(struct intel_uc_fw *uc_fw, struct drm_printer *p) | |
| 302 | +void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p) | |
| 303 | 303 | { |
| 304 | 304 | drm_printf(p, "%s firmware: %s\n", |
| 305 | 305 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); |
| @@ -116,6 +116,6 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, · 115 unmodified lines | ||
| 116 | 116 | int (*xfer)(struct intel_uc_fw *uc_fw, |
| 117 | 117 | struct i915_vma *vma)); |
| 118 | 118 | void intel_uc_fw_fini(struct intel_uc_fw *uc_fw); |
| 119 | −void intel_uc_fw_dump(struct intel_uc_fw *uc_fw, struct drm_printer *p); | |
| 119 | +void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p); | |
| 120 | 120 | |
| 121 | 121 | #endif |
| @@ -69,17 +69,104 @@ fw_domain_arm_timer(struct intel_uncore_forcewake_domain *d) · 68 unmodified lines | ||
| 69 | 69 | HRTIMER_MODE_REL); |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | +static inline int | |
| 73 | +__wait_for_ack(const struct drm_i915_private *i915, | |
| 74 | + const struct intel_uncore_forcewake_domain *d, | |
| 75 | + const u32 ack, | |
| 76 | + const u32 value) | |
| 77 | +{ | |
| 78 | + return wait_for_atomic((__raw_i915_read32(i915, d->reg_ack) & ack) == value, | |
| 79 | + FORCEWAKE_ACK_TIMEOUT_MS); | |
| 80 | +} | |
| 81 | + | |
| 82 | +static inline int | |
| 83 | +wait_ack_clear(const struct drm_i915_private *i915, | |
| 84 | + const struct intel_uncore_forcewake_domain *d, | |
| 85 | + const u32 ack) | |
| 86 | +{ | |
| 87 | + return __wait_for_ack(i915, d, ack, 0); | |
| 88 | +} | |
| 89 | + | |
| 90 | +static inline int | |
| 91 | +wait_ack_set(const struct drm_i915_private *i915, | |
| 92 | + const struct intel_uncore_forcewake_domain *d, | |
| 93 | + const u32 ack) | |
| 94 | +{ | |
| 95 | + return __wait_for_ack(i915, d, ack, ack); | |
| 96 | +} | |
| 97 | + | |
| 72 | 98 | static inline void |
| 73 | 99 | fw_domain_wait_ack_clear(const struct drm_i915_private *i915, |
| 74 | 100 | const struct intel_uncore_forcewake_domain *d) |
| 75 | 101 | { |
| 76 | − if (wait_for_atomic((__raw_i915_read32(i915, d->reg_ack) & | |
| 77 | − FORCEWAKE_KERNEL) == 0, | |
| 78 | − FORCEWAKE_ACK_TIMEOUT_MS)) | |
| 102 | + if (wait_ack_clear(i915, d, FORCEWAKE_KERNEL)) | |
| 79 | 103 | DRM_ERROR("%s: timed out waiting for forcewake ack to clear.\n", |
| 80 | 104 | intel_uncore_forcewake_domain_to_str(d->id)); |
| 81 | 105 | } |
| 82 | 106 | |
| 107 | +enum ack_type { | |
| 108 | + ACK_CLEAR = 0, | |
| 109 | + ACK_SET | |
| 110 | +}; | |
| 111 | + | |
| 112 | +static int | |
| 113 | +fw_domain_wait_ack_with_fallback(const struct drm_i915_private *i915, | |
| 114 | + const struct intel_uncore_forcewake_domain *d, | |
| 115 | + const enum ack_type type) | |
| 116 | +{ | |
| 117 | + const u32 ack_bit = FORCEWAKE_KERNEL; | |
| 118 | + const u32 value = type == ACK_SET ? ack_bit : 0; | |
| 119 | + unsigned int pass; | |
| 120 | + bool ack_detected; | |
| 121 | + | |
| 122 | + /* | |
| 123 | + * There is a possibility of driver's wake request colliding | |
| 124 | + * with hardware's own wake requests and that can cause | |
| 125 | + * hardware to not deliver the driver's ack message. | |
| 126 | + * | |
| 127 | + * Use a fallback bit toggle to kick the gpu state machine | |
| 128 | + * in the hope that the original ack will be delivered along with | |
| 129 | + * the fallback ack. | |
| 130 | + * | |
| 131 | + * This workaround is described in HSDES #1604254524 | |
| 132 | + */ | |
| 133 | + | |
| 134 | + pass = 1; | |
| 135 | + do { | |
| 136 | + wait_ack_clear(i915, d, FORCEWAKE_KERNEL_FALLBACK); | |
| 137 | + | |
| 138 | + __raw_i915_write32(i915, d->reg_set, | |
| 139 | + _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL_FALLBACK)); | |
| 140 | + /* Give gt some time to relax before the polling frenzy */ | |
| 141 | + udelay(10 * pass); | |
| 142 | + wait_ack_set(i915, d, FORCEWAKE_KERNEL_FALLBACK); | |
| 143 | + | |
| 144 | + ack_detected = (__raw_i915_read32(i915, d->reg_ack) & ack_bit) == value; | |
| 145 | + | |
| 146 | + __raw_i915_write32(i915, d->reg_set, | |
| 147 | + _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL_FALLBACK)); | |
| 148 | + } while (!ack_detected && pass++ < 10); | |
| 149 | + | |
| 150 | + DRM_DEBUG_DRIVER("%s had to use fallback to %s ack, 0x%x (passes %u)\n", | |
| 151 | + intel_uncore_forcewake_domain_to_str(d->id), | |
| 152 | + type == ACK_SET ? "set" : "clear", | |
| 153 | + __raw_i915_read32(i915, d->reg_ack), | |
| 154 | + pass); | |
| 155 | + | |
| 156 | + return ack_detected ? 0 : -ETIMEDOUT; | |
| 157 | +} | |
| 158 | + | |
| 159 | +static inline void | |
| 160 | +fw_domain_wait_ack_clear_fallback(const struct drm_i915_private *i915, | |
| 161 | + const struct intel_uncore_forcewake_domain *d) | |
| 162 | +{ | |
| 163 | + if (likely(!wait_ack_clear(i915, d, FORCEWAKE_KERNEL))) | |
| 164 | + return; | |
| 165 | + | |
| 166 | + if (fw_domain_wait_ack_with_fallback(i915, d, ACK_CLEAR)) | |
| 167 | + fw_domain_wait_ack_clear(i915, d); | |
| 168 | +} | |
| 169 | + | |
| 83 | 170 | static inline void |
| 84 | 171 | fw_domain_get(struct drm_i915_private *i915, |
| 85 | 172 | const struct intel_uncore_forcewake_domain *d) |
| @@ -88,16 +175,25 @@ fw_domain_get(struct drm_i915_private *i915, · 2 unmodified lines | ||
| 88 | 175 | } |
| 89 | 176 | |
| 90 | 177 | static inline void |
| 91 | −fw_domain_wait_ack(const struct drm_i915_private *i915, | |
| 92 | − const struct intel_uncore_forcewake_domain *d) | |
| 178 | +fw_domain_wait_ack_set(const struct drm_i915_private *i915, | |
| 179 | + const struct intel_uncore_forcewake_domain *d) | |
| 93 | 180 | { |
| 94 | − if (wait_for_atomic((__raw_i915_read32(i915, d->reg_ack) & | |
| 95 | − FORCEWAKE_KERNEL), | |
| 96 | − FORCEWAKE_ACK_TIMEOUT_MS)) | |
| 181 | + if (wait_ack_set(i915, d, FORCEWAKE_KERNEL)) | |
| 97 | 182 | DRM_ERROR("%s: timed out waiting for forcewake ack request.\n", |
| 98 | 183 | intel_uncore_forcewake_domain_to_str(d->id)); |
| 99 | 184 | } |
| 100 | 185 | |
| 186 | +static inline void | |
| 187 | +fw_domain_wait_ack_set_fallback(const struct drm_i915_private *i915, | |
| 188 | + const struct intel_uncore_forcewake_domain *d) | |
| 189 | +{ | |
| 190 | + if (likely(!wait_ack_set(i915, d, FORCEWAKE_KERNEL))) | |
| 191 | + return; | |
| 192 | + | |
| 193 | + if (fw_domain_wait_ack_with_fallback(i915, d, ACK_SET)) | |
| 194 | + fw_domain_wait_ack_set(i915, d); | |
| 195 | +} | |
| 196 | + | |
| 101 | 197 | static inline void |
| 102 | 198 | fw_domain_put(const struct drm_i915_private *i915, |
| 103 | 199 | const struct intel_uncore_forcewake_domain *d) |
| @@ -119,7 +215,27 @@ fw_domains_get(struct drm_i915_private *i915, enum forcewake_domains fw_domains) · 15 unmodified lines | ||
| 119 | 215 | } |
| 120 | 216 | |
| 121 | 217 | for_each_fw_domain_masked(d, fw_domains, i915, tmp) |
| 122 | − fw_domain_wait_ack(i915, d); | |
| 218 | + fw_domain_wait_ack_set(i915, d); | |
| 219 | + | |
| 220 | + i915->uncore.fw_domains_active |= fw_domains; | |
| 221 | +} | |
| 222 | + | |
| 223 | +static void | |
| 224 | +fw_domains_get_with_fallback(struct drm_i915_private *i915, | |
| 225 | + enum forcewake_domains fw_domains) | |
| 226 | +{ | |
| 227 | + struct intel_uncore_forcewake_domain *d; | |
| 228 | + unsigned int tmp; | |
| 229 | + | |
| 230 | + GEM_BUG_ON(fw_domains & ~i915->uncore.fw_domains); | |
| 231 | + | |
| 232 | + for_each_fw_domain_masked(d, fw_domains, i915, tmp) { | |
| 233 | + fw_domain_wait_ack_clear_fallback(i915, d); | |
| 234 | + fw_domain_get(i915, d); | |
| 235 | + } | |
| 236 | + | |
| 237 | + for_each_fw_domain_masked(d, fw_domains, i915, tmp) | |
| 238 | + fw_domain_wait_ack_set_fallback(i915, d); | |
| 123 | 239 | |
| 124 | 240 | i915->uncore.fw_domains_active |= fw_domains; |
| 125 | 241 | } |
| @@ -229,6 +345,7 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) · 103 unmodified lines | ||
| 229 | 345 | return HRTIMER_NORESTART; |
| 230 | 346 | } |
| 231 | 347 | |
| 348 | +/* Note callers must have acquired the PUNIT->PMIC bus, before calling this. */ | |
| 232 | 349 | static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, |
| 233 | 350 | bool restore) |
| 234 | 351 | { |
| @@ -237,6 +354,8 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, · 2 unmodified lines | ||
| 237 | 354 | int retry_count = 100; |
| 238 | 355 | enum forcewake_domains fw, active_domains; |
| 239 | 356 | |
| 357 | + iosf_mbi_assert_punit_acquired(); | |
| 358 | + | |
| 240 | 359 | /* Hold uncore.lock across reset to prevent any register access |
| 241 | 360 | * with forcewake not set correctly. Wait until all pending |
| 242 | 361 | * timers are run before holding. |
| @@ -416,14 +535,18 @@ static void __intel_uncore_early_sanitize(struct drm_i915_private *dev_priv, · 173 unmodified lines | ||
| 416 | 535 | GT_FIFO_CTL_RC6_POLICY_STALL); |
| 417 | 536 | } |
| 418 | 537 | |
| 538 | + iosf_mbi_punit_acquire(); | |
| 419 | 539 | intel_uncore_forcewake_reset(dev_priv, restore_forcewake); |
| 540 | + iosf_mbi_punit_release(); | |
| 420 | 541 | } |
| 421 | 542 | |
| 422 | 543 | void intel_uncore_suspend(struct drm_i915_private *dev_priv) |
| 423 | 544 | { |
| 424 | − iosf_mbi_unregister_pmic_bus_access_notifier( | |
| 545 | + iosf_mbi_punit_acquire(); | |
| 546 | + iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( | |
| 425 | 547 | &dev_priv->uncore.pmic_bus_access_nb); |
| 426 | 548 | intel_uncore_forcewake_reset(dev_priv, false); |
| 549 | + iosf_mbi_punit_release(); | |
| 427 | 550 | } |
| 428 | 551 | |
| 429 | 552 | void intel_uncore_resume_early(struct drm_i915_private *dev_priv) |
| @@ -1148,7 +1271,8 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) · 718 unmodified lines | ||
| 1148 | 1271 | } |
| 1149 | 1272 | |
| 1150 | 1273 | if (INTEL_GEN(dev_priv) >= 9) { |
| 1151 | − dev_priv->uncore.funcs.force_wake_get = fw_domains_get; | |
| 1274 | + dev_priv->uncore.funcs.force_wake_get = | |
| 1275 | + fw_domains_get_with_fallback; | |
| 1152 | 1276 | dev_priv->uncore.funcs.force_wake_put = fw_domains_put; |
| 1153 | 1277 | fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, |
| 1154 | 1278 | FORCEWAKE_RENDER_GEN9, |
| @@ -1309,18 +1433,18 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) · 154 unmodified lines | ||
| 1309 | 1433 | |
| 1310 | 1434 | iosf_mbi_register_pmic_bus_access_notifier( |
| 1311 | 1435 | &dev_priv->uncore.pmic_bus_access_nb); |
| 1312 | − | |
| 1313 | − i915_check_and_clear_faults(dev_priv); | |
| 1314 | 1436 | } |
| 1315 | 1437 | |
| 1316 | 1438 | void intel_uncore_fini(struct drm_i915_private *dev_priv) |
| 1317 | 1439 | { |
| 1318 | − iosf_mbi_unregister_pmic_bus_access_notifier( | |
| 1319 | − &dev_priv->uncore.pmic_bus_access_nb); | |
| 1320 | − | |
| 1321 | 1440 | /* Paranoia: make sure we have disabled everything before we exit. */ |
| 1322 | 1441 | intel_uncore_sanitize(dev_priv); |
| 1442 | + | |
| 1443 | + iosf_mbi_punit_acquire(); | |
| 1444 | + iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( | |
| 1445 | + &dev_priv->uncore.pmic_bus_access_nb); | |
| 1323 | 1446 | intel_uncore_forcewake_reset(dev_priv, false); |
| 1447 | + iosf_mbi_punit_release(); | |
| 1324 | 1448 | } |
| 1325 | 1449 | |
| 1326 | 1450 | static const struct reg_whitelist { |
| @@ -1400,10 +1524,14 @@ static void gen3_stop_engine(struct intel_engine_cs *engine) · 73 unmodified lines | ||
| 1400 | 1524 | DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", |
| 1401 | 1525 | engine->name); |
| 1402 | 1526 | |
| 1403 | − I915_WRITE_FW(RING_CTL(base), 0); | |
| 1527 | + I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base))); | |
| 1528 | + | |
| 1404 | 1529 | I915_WRITE_FW(RING_HEAD(base), 0); |
| 1405 | 1530 | I915_WRITE_FW(RING_TAIL(base), 0); |
| 1406 | 1531 | |
| 1532 | + /* The ring must be empty before it is disabled */ | |
| 1533 | + I915_WRITE_FW(RING_CTL(base), 0); | |
| 1534 | + | |
| 1407 | 1535 | /* Check acts as a post */ |
| 1408 | 1536 | if (I915_READ_FW(RING_HEAD(base)) != 0) |
| 1409 | 1537 | DRM_DEBUG_DRIVER("%s: ring head not parked\n", |
| @@ -1801,18 +1929,13 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv) · 391 unmodified lines | ||
| 1801 | 1929 | return intel_get_gpu_reset(dev_priv) != NULL; |
| 1802 | 1930 | } |
| 1803 | 1931 | |
| 1804 | −/* | |
| 1805 | − * When GuC submission is enabled, GuC manages ELSP and can initiate the | |
| 1806 | − * engine reset too. For now, fall back to full GPU reset if it is enabled. | |
| 1807 | − */ | |
| 1808 | 1932 | bool intel_has_reset_engine(struct drm_i915_private *dev_priv) |
| 1809 | 1933 | { |
| 1810 | 1934 | return (dev_priv->info.has_reset_engine && |
| 1811 | − !dev_priv->guc.execbuf_client && | |
| 1812 | 1935 | i915_modparams.reset >= 2); |
| 1813 | 1936 | } |
| 1814 | 1937 | |
| 1815 | −int intel_guc_reset(struct drm_i915_private *dev_priv) | |
| 1938 | +int intel_reset_guc(struct drm_i915_private *dev_priv) | |
| 1816 | 1939 | { |
| 1817 | 1940 | int ret; |
| 1818 | 1941 | |
| @@ -304,6 +304,10 @@ struct bdb_general_features { · 303 unmodified lines | ||
| 304 | 304 | #define DVO_PORT_MIPIC 23 /* 171 */ |
| 305 | 305 | #define DVO_PORT_MIPID 24 /* 171 */ |
| 306 | 306 | |
| 307 | +#define HDMI_MAX_DATA_RATE_PLATFORM 0 /* 204 */ | |
| 308 | +#define HDMI_MAX_DATA_RATE_297 1 /* 204 */ | |
| 309 | +#define HDMI_MAX_DATA_RATE_165 2 /* 204 */ | |
| 310 | + | |
| 307 | 311 | #define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 |
| 308 | 312 | |
| 309 | 313 | /* DDC Bus DDI Type 155+ */ |
| @@ -342,8 +346,8 @@ struct child_device_config { · 32 unmodified lines | ||
| 342 | 346 | u8 i2c_speed; |
| 343 | 347 | u8 dp_onboard_redriver; /* 158 */ |
| 344 | 348 | u8 dp_ondock_redriver; /* 158 */ |
| 345 | − u8 hdmi_level_shifter_value:4; /* 169 */ | |
| 346 | − u8 hdmi_max_data_rate:4; /* 204 */ | |
| 349 | + u8 hdmi_level_shifter_value:5; /* 169 */ | |
| 350 | + u8 hdmi_max_data_rate:3; /* 204 */ | |
| 347 | 351 | u16 dtd_buf_ptr; /* 161 */ |
| 348 | 352 | u8 edidless_efp:1; /* 161 */ |
| 349 | 353 | u8 compression_enable:1; /* 198 */ |
| @@ -1159,6 +1159,9 @@ static int igt_ppgtt_exhaust_huge(void *arg) · 1158 unmodified lines | ||
| 1159 | 1159 | int n, i; |
| 1160 | 1160 | int err = -ENODEV; |
| 1161 | 1161 | |
| 1162 | + if (supported == I915_GTT_PAGE_SIZE_4K) | |
| 1163 | + return 0; | |
| 1164 | + | |
| 1162 | 1165 | /* |
| 1163 | 1166 | * Sanity check creating objects with a varying mix of page sizes -- |
| 1164 | 1167 | * ensuring that our writes lands in the right place. |
| @@ -33,7 +33,7 @@ static int cpu_set(struct drm_i915_gem_object *obj, · 32 unmodified lines | ||
| 33 | 33 | { |
| 34 | 34 | unsigned int needs_clflush; |
| 35 | 35 | struct page *page; |
| 36 | − typeof(v) *map; | |
| 36 | + u32 *map; | |
| 37 | 37 | int err; |
| 38 | 38 | |
| 39 | 39 | err = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush); |
| @@ -59,7 +59,7 @@ static int cpu_get(struct drm_i915_gem_object *obj, · 19 unmodified lines | ||
| 59 | 59 | { |
| 60 | 60 | unsigned int needs_clflush; |
| 61 | 61 | struct page *page; |
| 62 | − typeof(v) map; | |
| 62 | + u32 *map; | |
| 63 | 63 | int err; |
| 64 | 64 | |
| 65 | 65 | err = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush); |
| @@ -82,7 +82,7 @@ static int gtt_set(struct drm_i915_gem_object *obj, · 16 unmodified lines | ||
| 82 | 82 | u32 v) |
| 83 | 83 | { |
| 84 | 84 | struct i915_vma *vma; |
| 85 | − typeof(v) *map; | |
| 85 | + u32 __iomem *map; | |
| 86 | 86 | int err; |
| 87 | 87 | |
| 88 | 88 | err = i915_gem_object_set_to_gtt_domain(obj, true); |
| @@ -98,7 +98,7 @@ static int gtt_set(struct drm_i915_gem_object *obj, · 9 unmodified lines | ||
| 98 | 98 | if (IS_ERR(map)) |
| 99 | 99 | return PTR_ERR(map); |
| 100 | 100 | |
| 101 | − map[offset / sizeof(*map)] = v; | |
| 101 | + iowrite32(v, &map[offset / sizeof(*map)]); | |
| 102 | 102 | i915_vma_unpin_iomap(vma); |
| 103 | 103 | |
| 104 | 104 | return 0; |
| @@ -109,7 +109,7 @@ static int gtt_get(struct drm_i915_gem_object *obj, · 4 unmodified lines | ||
| 109 | 109 | u32 *v) |
| 110 | 110 | { |
| 111 | 111 | struct i915_vma *vma; |
| 112 | − typeof(v) map; | |
| 112 | + u32 __iomem *map; | |
| 113 | 113 | int err; |
| 114 | 114 | |
| 115 | 115 | err = i915_gem_object_set_to_gtt_domain(obj, false); |
| @@ -125,7 +125,7 @@ static int gtt_get(struct drm_i915_gem_object *obj, · 9 unmodified lines | ||
| 125 | 125 | if (IS_ERR(map)) |
| 126 | 126 | return PTR_ERR(map); |
| 127 | 127 | |
| 128 | − *v = map[offset / sizeof(*map)]; | |
| 128 | + *v = ioread32(&map[offset / sizeof(*map)]); | |
| 129 | 129 | i915_vma_unpin_iomap(vma); |
| 130 | 130 | |
| 131 | 131 | return 0; |
| @@ -135,7 +135,7 @@ static int wc_set(struct drm_i915_gem_object *obj, · 3 unmodified lines | ||
| 135 | 135 | unsigned long offset, |
| 136 | 136 | u32 v) |
| 137 | 137 | { |
| 138 | − typeof(v) *map; | |
| 138 | + u32 *map; | |
| 139 | 139 | int err; |
| 140 | 140 | |
| 141 | 141 | err = i915_gem_object_set_to_wc_domain(obj, true); |
| @@ -156,7 +156,7 @@ static int wc_get(struct drm_i915_gem_object *obj, · 14 unmodified lines | ||
| 156 | 156 | unsigned long offset, |
| 157 | 157 | u32 *v) |
| 158 | 158 | { |
| 159 | − typeof(v) map; | |
| 159 | + u32 *map; | |
| 160 | 160 | int err; |
| 161 | 161 | |
| 162 | 162 | err = i915_gem_object_set_to_wc_domain(obj, false); |
| @@ -325,7 +325,7 @@ static int igt_ctx_exec(void *arg) · 324 unmodified lines | ||
| 325 | 325 | LIST_HEAD(objects); |
| 326 | 326 | unsigned long ncontexts, ndwords, dw; |
| 327 | 327 | bool first_shared_gtt = true; |
| 328 | − int err; | |
| 328 | + int err = -ENODEV; | |
| 329 | 329 | |
| 330 | 330 | /* Create a few different contexts (with different mm) and write |
| 331 | 331 | * through each ctx/mm using the GPU making sure those writes end |
| @@ -216,13 +216,21 @@ static int lowlevel_hole(struct drm_i915_private *i915, · 215 unmodified lines | ||
| 216 | 216 | hole_size = (hole_end - hole_start) >> size; |
| 217 | 217 | if (hole_size > KMALLOC_MAX_SIZE / sizeof(u32)) |
| 218 | 218 | hole_size = KMALLOC_MAX_SIZE / sizeof(u32); |
| 219 | − count = hole_size; | |
| 219 | + count = hole_size >> 1; | |
| 220 | + if (!count) { | |
| 221 | + pr_debug("%s: hole is too small [%llx - %llx] >> %d: %lld\n", | |
| 222 | + __func__, hole_start, hole_end, size, hole_size); | |
| 223 | + break; | |
| 224 | + } | |
| 225 | + | |
| 220 | 226 | do { |
| 221 | − count >>= 1; | |
| 222 | 227 | order = i915_random_order(count, &prng); |
| 223 | − } while (!order && count); | |
| 224 | − if (!order) | |
| 225 | − break; | |
| 228 | + if (order) | |
| 229 | + break; | |
| 230 | + } while (count >>= 1); | |
| 231 | + if (!count) | |
| 232 | + return -ENOMEM; | |
| 233 | + GEM_BUG_ON(!order); | |
| 226 | 234 | |
| 227 | 235 | GEM_BUG_ON(count * BIT_ULL(size) > vm->total); |
| 228 | 236 | GEM_BUG_ON(hole_start + count * BIT_ULL(size) > hole_end); |
| @@ -267,7 +275,9 @@ static int lowlevel_hole(struct drm_i915_private *i915, · 38 unmodified lines | ||
| 267 | 275 | mock_vma.node.size = BIT_ULL(size); |
| 268 | 276 | mock_vma.node.start = addr; |
| 269 | 277 | |
| 278 | + intel_runtime_pm_get(i915); | |
| 270 | 279 | vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0); |
| 280 | + intel_runtime_pm_put(i915); | |
| 271 | 281 | } |
| 272 | 282 | count = n; |
| 273 | 283 | |
| @@ -697,18 +707,26 @@ static int drunk_hole(struct drm_i915_private *i915, · 423 unmodified lines | ||
| 697 | 707 | unsigned int *order, count, n; |
| 698 | 708 | struct i915_vma *vma; |
| 699 | 709 | u64 hole_size; |
| 700 | − int err; | |
| 710 | + int err = -ENODEV; | |
| 701 | 711 | |
| 702 | 712 | hole_size = (hole_end - hole_start) >> size; |
| 703 | 713 | if (hole_size > KMALLOC_MAX_SIZE / sizeof(u32)) |
| 704 | 714 | hole_size = KMALLOC_MAX_SIZE / sizeof(u32); |
| 705 | − count = hole_size; | |
| 715 | + count = hole_size >> 1; | |
| 716 | + if (!count) { | |
| 717 | + pr_debug("%s: hole is too small [%llx - %llx] >> %d: %lld\n", | |
| 718 | + __func__, hole_start, hole_end, size, hole_size); | |
| 719 | + break; | |
| 720 | + } | |
| 721 | + | |
| 706 | 722 | do { |
| 707 | − count >>= 1; | |
| 708 | 723 | order = i915_random_order(count, &prng); |
| 709 | − } while (!order && count); | |
| 710 | − if (!order) | |
| 711 | − break; | |
| 724 | + if (order) | |
| 725 | + break; | |
| 726 | + } while (count >>= 1); | |
| 727 | + if (!count) | |
| 728 | + return -ENOMEM; | |
| 729 | + GEM_BUG_ON(!order); | |
| 712 | 730 | |
| 713 | 731 | /* Ignore allocation failures (i.e. don't report them as |
| 714 | 732 | * a test failure) as we are purposefully allocating very |
| @@ -956,7 +974,7 @@ static int exercise_ggtt(struct drm_i915_private *i915, · 241 unmodified lines | ||
| 956 | 974 | u64 hole_start, hole_end, last = 0; |
| 957 | 975 | struct drm_mm_node *node; |
| 958 | 976 | IGT_TIMEOUT(end_time); |
| 959 | − int err; | |
| 977 | + int err = 0; | |
| 960 | 978 | |
| 961 | 979 | mutex_lock(&i915->drm.struct_mutex); |
| 962 | 980 | restart: |
| @@ -1047,6 +1065,7 @@ static int igt_ggtt_page(void *arg) · 84 unmodified lines | ||
| 1047 | 1065 | goto out_remove; |
| 1048 | 1066 | } |
| 1049 | 1067 | |
| 1068 | + intel_runtime_pm_get(i915); | |
| 1050 | 1069 | for (n = 0; n < count; n++) { |
| 1051 | 1070 | u64 offset = tmp.start + order[n] * PAGE_SIZE; |
| 1052 | 1071 | u32 __iomem *vaddr; |
| @@ -1086,6 +1105,7 @@ static int igt_ggtt_page(void *arg) · 33 unmodified lines | ||
| 1086 | 1105 | break; |
| 1087 | 1106 | } |
| 1088 | 1107 | } |
| 1108 | + intel_runtime_pm_put(i915); | |
| 1089 | 1109 | |
| 1090 | 1110 | kfree(order); |
| 1091 | 1111 | out_remove: |
| @@ -1160,7 +1180,7 @@ static int igt_gtt_reserve(void *arg) · 68 unmodified lines | ||
| 1160 | 1180 | struct drm_i915_gem_object *obj, *on; |
| 1161 | 1181 | LIST_HEAD(objects); |
| 1162 | 1182 | u64 total; |
| 1163 | − int err; | |
| 1183 | + int err = -ENODEV; | |
| 1164 | 1184 | |
| 1165 | 1185 | /* i915_gem_gtt_reserve() tries to reserve the precise range |
| 1166 | 1186 | * for the node, and evicts if it has to. So our test checks that |
| @@ -1351,7 +1371,7 @@ static int igt_gtt_insert(void *arg) · 184 unmodified lines | ||
| 1351 | 1371 | }, *ii; |
| 1352 | 1372 | LIST_HEAD(objects); |
| 1353 | 1373 | u64 total; |
| 1354 | − int err; | |
| 1374 | + int err = -ENODEV; | |
| 1355 | 1375 | |
| 1356 | 1376 | /* i915_gem_gtt_insert() tries to allocate some free space in the GTT |
| 1357 | 1377 | * to the node, evicting if required. |
| @@ -317,6 +317,7 @@ static int igt_partial_tiling(void *arg) · 316 unmodified lines | ||
| 317 | 317 | } |
| 318 | 318 | |
| 319 | 319 | mutex_lock(&i915->drm.struct_mutex); |
| 320 | + intel_runtime_pm_get(i915); | |
| 320 | 321 | |
| 321 | 322 | if (1) { |
| 322 | 323 | IGT_TIMEOUT(end); |
| @@ -418,6 +419,7 @@ next_tiling: ; · 95 unmodified lines | ||
| 418 | 419 | } |
| 419 | 420 | |
| 420 | 421 | out_unlock: |
| 422 | + intel_runtime_pm_put(i915); | |
| 421 | 423 | mutex_unlock(&i915->drm.struct_mutex); |
| 422 | 424 | i915_gem_object_unpin_pages(obj); |
| 423 | 425 | out: |
| @@ -332,7 +332,7 @@ static int live_nop_request(void *arg) · 331 unmodified lines | ||
| 332 | 332 | struct intel_engine_cs *engine; |
| 333 | 333 | struct live_test t; |
| 334 | 334 | unsigned int id; |
| 335 | − int err; | |
| 335 | + int err = -ENODEV; | |
| 336 | 336 | |
| 337 | 337 | /* Submit various sized batches of empty requests, to each engine |
| 338 | 338 | * (individually), and wait for the batch to complete. We can check |
| @@ -79,7 +79,7 @@ static int igt_sync(void *arg) · 78 unmodified lines | ||
| 79 | 79 | }, *p; |
| 80 | 80 | struct intel_timeline *tl; |
| 81 | 81 | int order, offset; |
| 82 | − int ret; | |
| 82 | + int ret = -ENODEV; | |
| 83 | 83 | |
| 84 | 84 | tl = mock_timeline(0); |
| 85 | 85 | if (!tl) |
| @@ -20,3 +20,4 @@ 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(guc, intel_guc_live_selftest) | |
| @@ -333,7 +333,7 @@ static int igt_syncmap_join_below(void *arg) · 332 unmodified lines | ||
| 333 | 333 | { |
| 334 | 334 | struct i915_syncmap *sync; |
| 335 | 335 | unsigned int step, order, idx; |
| 336 | − int err; | |
| 336 | + int err = -ENODEV; | |
| 337 | 337 | |
| 338 | 338 | i915_syncmap_init(&sync); |
| 339 | 339 | |
| @@ -402,7 +402,7 @@ static int igt_syncmap_neighbours(void *arg) · 62 unmodified lines | ||
| 402 | 402 | I915_RND_STATE(prng); |
| 403 | 403 | IGT_TIMEOUT(end_time); |
| 404 | 404 | struct i915_syncmap *sync; |
| 405 | − int err; | |
| 405 | + int err = -ENODEV; | |
| 406 | 406 | |
| 407 | 407 | /* |
| 408 | 408 | * Each leaf holds KSYNCMAP seqno. Check that when we create KSYNCMAP |
| @@ -447,7 +447,7 @@ static int igt_syncmap_compact(void *arg) · 38 unmodified lines | ||
| 447 | 447 | { |
| 448 | 448 | struct i915_syncmap *sync; |
| 449 | 449 | unsigned int idx, order; |
| 450 | − int err; | |
| 450 | + int err = -ENODEV; | |
| 451 | 451 | |
| 452 | 452 | i915_syncmap_init(&sync); |
| 453 | 453 | |
| @@ -150,7 +150,7 @@ static int igt_vma_create(void *arg) · 149 unmodified lines | ||
| 150 | 150 | IGT_TIMEOUT(end_time); |
| 151 | 151 | LIST_HEAD(contexts); |
| 152 | 152 | LIST_HEAD(objects); |
| 153 | − int err; | |
| 153 | + int err = -ENOMEM; | |
| 154 | 154 | |
| 155 | 155 | /* Exercise creating many vma amonst many objections, checking the |
| 156 | 156 | * vma creation and lookup routines. |
| @@ -0,0 +1,367 @@ | ||
| 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. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#include "../i915_selftest.h" | |
| 26 | + | |
| 27 | +/* max doorbell number + negative test for each client type */ | |
| 28 | +#define ATTEMPTS (GUC_NUM_DOORBELLS + GUC_CLIENT_PRIORITY_NUM) | |
| 29 | + | |
| 30 | +struct intel_guc_client *clients[ATTEMPTS]; | |
| 31 | + | |
| 32 | +static bool available_dbs(struct intel_guc *guc, u32 priority) | |
| 33 | +{ | |
| 34 | + unsigned long offset; | |
| 35 | + unsigned long end; | |
| 36 | + u16 id; | |
| 37 | + | |
| 38 | + /* first half is used for normal priority, second half for high */ | |
| 39 | + offset = 0; | |
| 40 | + end = GUC_NUM_DOORBELLS / 2; | |
| 41 | + if (priority <= GUC_CLIENT_PRIORITY_HIGH) { | |
| 42 | + offset = end; | |
| 43 | + end += offset; | |
| 44 | + } | |
| 45 | + | |
| 46 | + id = find_next_zero_bit(guc->doorbell_bitmap, end, offset); | |
| 47 | + if (id < end) | |
| 48 | + return true; | |
| 49 | + | |
| 50 | + return false; | |
| 51 | +} | |
| 52 | + | |
| 53 | +static int check_all_doorbells(struct intel_guc *guc) | |
| 54 | +{ | |
| 55 | + u16 db_id; | |
| 56 | + | |
| 57 | + pr_info_once("Max number of doorbells: %d", GUC_NUM_DOORBELLS); | |
| 58 | + for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) { | |
| 59 | + if (!doorbell_ok(guc, db_id)) { | |
| 60 | + pr_err("doorbell %d, not ok\n", db_id); | |
| 61 | + return -EIO; | |
| 62 | + } | |
| 63 | + } | |
| 64 | + | |
| 65 | + return 0; | |
| 66 | +} | |
| 67 | + | |
| 68 | +/* | |
| 69 | + * Basic client sanity check, handy to validate create_clients. | |
| 70 | + */ | |
| 71 | +static int validate_client(struct intel_guc_client *client, | |
| 72 | + int client_priority, | |
| 73 | + bool is_preempt_client) | |
| 74 | +{ | |
| 75 | + struct drm_i915_private *dev_priv = guc_to_i915(client->guc); | |
| 76 | + struct i915_gem_context *ctx_owner = is_preempt_client ? | |
| 77 | + dev_priv->preempt_context : dev_priv->kernel_context; | |
| 78 | + | |
| 79 | + if (client->owner != ctx_owner || | |
| 80 | + client->engines != INTEL_INFO(dev_priv)->ring_mask || | |
| 81 | + client->priority != client_priority || | |
| 82 | + client->doorbell_id == GUC_DOORBELL_INVALID) | |
| 83 | + return -EINVAL; | |
| 84 | + else | |
| 85 | + return 0; | |
| 86 | +} | |
| 87 | + | |
| 88 | +/* | |
| 89 | + * Check that guc_init_doorbell_hw is doing what it should. | |
| 90 | + * | |
| 91 | + * During GuC submission enable, we create GuC clients and their doorbells, | |
| 92 | + * but after resetting the microcontroller (resume & gpu reset), these | |
| 93 | + * GuC clients are still around, but the status of their doorbells may be | |
| 94 | + * incorrect. This is the reason behind validating that the doorbells status | |
| 95 | + * expected by the driver matches what the GuC/HW have. | |
| 96 | + */ | |
| 97 | +static int igt_guc_init_doorbell_hw(void *args) | |
| 98 | +{ | |
| 99 | + struct drm_i915_private *dev_priv = args; | |
| 100 | + struct intel_guc *guc; | |
| 101 | + DECLARE_BITMAP(db_bitmap_bk, GUC_NUM_DOORBELLS); | |
| 102 | + int i, err = 0; | |
| 103 | + | |
| 104 | + GEM_BUG_ON(!HAS_GUC(dev_priv)); | |
| 105 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 106 | + | |
| 107 | + guc = &dev_priv->guc; | |
| 108 | + if (!guc) { | |
| 109 | + pr_err("No guc object!\n"); | |
| 110 | + err = -EINVAL; | |
| 111 | + goto unlock; | |
| 112 | + } | |
| 113 | + | |
| 114 | + err = check_all_doorbells(guc); | |
| 115 | + if (err) | |
| 116 | + goto unlock; | |
| 117 | + | |
| 118 | + /* | |
| 119 | + * Get rid of clients created during driver load because the test will | |
| 120 | + * recreate them. | |
| 121 | + */ | |
| 122 | + guc_clients_destroy(guc); | |
| 123 | + if (guc->execbuf_client || guc->preempt_client) { | |
| 124 | + pr_err("guc_clients_destroy lied!\n"); | |
| 125 | + err = -EINVAL; | |
| 126 | + goto unlock; | |
| 127 | + } | |
| 128 | + | |
| 129 | + err = guc_clients_create(guc); | |
| 130 | + if (err) { | |
| 131 | + pr_err("Failed to create clients\n"); | |
| 132 | + goto unlock; | |
| 133 | + } | |
| 134 | + | |
| 135 | + err = validate_client(guc->execbuf_client, | |
| 136 | + GUC_CLIENT_PRIORITY_KMD_NORMAL, false); | |
| 137 | + if (err) { | |
| 138 | + pr_err("execbug client validation failed\n"); | |
| 139 | + goto out; | |
| 140 | + } | |
| 141 | + | |
| 142 | + err = validate_client(guc->preempt_client, | |
| 143 | + GUC_CLIENT_PRIORITY_KMD_HIGH, true); | |
| 144 | + if (err) { | |
| 145 | + pr_err("preempt client validation failed\n"); | |
| 146 | + goto out; | |
| 147 | + } | |
| 148 | + | |
| 149 | + /* each client should have received a doorbell during alloc */ | |
| 150 | + if (!has_doorbell(guc->execbuf_client) || | |
| 151 | + !has_doorbell(guc->preempt_client)) { | |
| 152 | + pr_err("guc_clients_create didn't create doorbells\n"); | |
| 153 | + err = -EINVAL; | |
| 154 | + goto out; | |
| 155 | + } | |
| 156 | + | |
| 157 | + /* | |
| 158 | + * Basic test - an attempt to reallocate a valid doorbell to the | |
| 159 | + * client it is currently assigned should not cause a failure. | |
| 160 | + */ | |
| 161 | + err = guc_init_doorbell_hw(guc); | |
| 162 | + if (err) | |
| 163 | + goto out; | |
| 164 | + | |
| 165 | + /* | |
| 166 | + * Negative test - a client with no doorbell (invalid db id). | |
| 167 | + * Each client gets a doorbell when it is created, after destroying | |
| 168 | + * the doorbell, the db id is changed to GUC_DOORBELL_INVALID and the | |
| 169 | + * firmware will reject any attempt to allocate a doorbell with an | |
| 170 | + * invalid id (db has to be reserved before allocation). | |
| 171 | + */ | |
| 172 | + destroy_doorbell(guc->execbuf_client); | |
| 173 | + if (has_doorbell(guc->execbuf_client)) { | |
| 174 | + pr_err("destroy db did not work\n"); | |
| 175 | + err = -EINVAL; | |
| 176 | + goto out; | |
| 177 | + } | |
| 178 | + | |
| 179 | + err = guc_init_doorbell_hw(guc); | |
| 180 | + if (err != -EIO) { | |
| 181 | + pr_err("unexpected (err = %d)", err); | |
| 182 | + goto out; | |
| 183 | + } | |
| 184 | + | |
| 185 | + if (!available_dbs(guc, guc->execbuf_client->priority)) { | |
| 186 | + pr_err("doorbell not available when it should\n"); | |
| 187 | + err = -EIO; | |
| 188 | + goto out; | |
| 189 | + } | |
| 190 | + | |
| 191 | + /* clean after test */ | |
| 192 | + err = create_doorbell(guc->execbuf_client); | |
| 193 | + if (err) { | |
| 194 | + pr_err("recreate doorbell failed\n"); | |
| 195 | + goto out; | |
| 196 | + } | |
| 197 | + | |
| 198 | + /* | |
| 199 | + * Negative test - doorbell_bitmap out of sync, will trigger a few of | |
| 200 | + * WARN_ON(!doorbell_ok(guc, db_id)) but that's ok as long as the | |
| 201 | + * doorbells from our clients don't fail. | |
| 202 | + */ | |
| 203 | + bitmap_copy(db_bitmap_bk, guc->doorbell_bitmap, GUC_NUM_DOORBELLS); | |
| 204 | + for (i = 0; i < GUC_NUM_DOORBELLS; i++) | |
| 205 | + if (i % 2) | |
| 206 | + test_and_change_bit(i, guc->doorbell_bitmap); | |
| 207 | + | |
| 208 | + err = guc_init_doorbell_hw(guc); | |
| 209 | + if (err) { | |
| 210 | + pr_err("out of sync doorbell caused an error\n"); | |
| 211 | + goto out; | |
| 212 | + } | |
| 213 | + | |
| 214 | + /* restore 'correct' db bitmap */ | |
| 215 | + bitmap_copy(guc->doorbell_bitmap, db_bitmap_bk, GUC_NUM_DOORBELLS); | |
| 216 | + err = guc_init_doorbell_hw(guc); | |
| 217 | + if (err) { | |
| 218 | + pr_err("restored doorbell caused an error\n"); | |
| 219 | + goto out; | |
| 220 | + } | |
| 221 | + | |
| 222 | +out: | |
| 223 | + /* | |
| 224 | + * Leave clean state for other test, plus the driver always destroy the | |
| 225 | + * clients during unload. | |
| 226 | + */ | |
| 227 | + guc_clients_destroy(guc); | |
| 228 | + guc_clients_create(guc); | |
| 229 | +unlock: | |
| 230 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 231 | + return err; | |
| 232 | +} | |
| 233 | + | |
| 234 | +/* | |
| 235 | + * Create as many clients as number of doorbells. Note that there's already | |
| 236 | + * client(s)/doorbell(s) created during driver load, but this test creates | |
| 237 | + * its own and do not interact with the existing ones. | |
| 238 | + */ | |
| 239 | +static int igt_guc_doorbells(void *arg) | |
| 240 | +{ | |
| 241 | + struct drm_i915_private *dev_priv = arg; | |
| 242 | + struct intel_guc *guc; | |
| 243 | + int i, err = 0; | |
| 244 | + u16 db_id; | |
| 245 | + | |
| 246 | + GEM_BUG_ON(!HAS_GUC(dev_priv)); | |
| 247 | + mutex_lock(&dev_priv->drm.struct_mutex); | |
| 248 | + | |
| 249 | + guc = &dev_priv->guc; | |
| 250 | + if (!guc) { | |
| 251 | + pr_err("No guc object!\n"); | |
| 252 | + err = -EINVAL; | |
| 253 | + goto unlock; | |
| 254 | + } | |
| 255 | + | |
| 256 | + err = check_all_doorbells(guc); | |
| 257 | + if (err) | |
| 258 | + goto unlock; | |
| 259 | + | |
| 260 | + for (i = 0; i < ATTEMPTS; i++) { | |
| 261 | + clients[i] = guc_client_alloc(dev_priv, | |
| 262 | + INTEL_INFO(dev_priv)->ring_mask, | |
| 263 | + i % GUC_CLIENT_PRIORITY_NUM, | |
| 264 | + dev_priv->kernel_context); | |
| 265 | + | |
| 266 | + if (!clients[i]) { | |
| 267 | + pr_err("[%d] No guc client\n", i); | |
| 268 | + err = -EINVAL; | |
| 269 | + goto out; | |
| 270 | + } | |
| 271 | + | |
| 272 | + if (IS_ERR(clients[i])) { | |
| 273 | + if (PTR_ERR(clients[i]) != -ENOSPC) { | |
| 274 | + pr_err("[%d] unexpected error\n", i); | |
| 275 | + err = PTR_ERR(clients[i]); | |
| 276 | + goto out; | |
| 277 | + } | |
| 278 | + | |
| 279 | + if (available_dbs(guc, i % GUC_CLIENT_PRIORITY_NUM)) { | |
| 280 | + pr_err("[%d] non-db related alloc fail\n", i); | |
| 281 | + err = -EINVAL; | |
| 282 | + goto out; | |
| 283 | + } | |
| 284 | + | |
| 285 | + /* expected, ran out of dbs for this client type */ | |
| 286 | + continue; | |
| 287 | + } | |
| 288 | + | |
| 289 | + /* | |
| 290 | + * The check below is only valid because we keep a doorbell | |
| 291 | + * assigned during the whole life of the client. | |
| 292 | + */ | |
| 293 | + if (clients[i]->stage_id >= GUC_NUM_DOORBELLS) { | |
| 294 | + pr_err("[%d] more clients than doorbells (%d >= %d)\n", | |
| 295 | + i, clients[i]->stage_id, GUC_NUM_DOORBELLS); | |
| 296 | + err = -EINVAL; | |
| 297 | + goto out; | |
| 298 | + } | |
| 299 | + | |
| 300 | + err = validate_client(clients[i], | |
| 301 | + i % GUC_CLIENT_PRIORITY_NUM, false); | |
| 302 | + if (err) { | |
| 303 | + pr_err("[%d] client_alloc sanity check failed!\n", i); | |
| 304 | + err = -EINVAL; | |
| 305 | + goto out; | |
| 306 | + } | |
| 307 | + | |
| 308 | + db_id = clients[i]->doorbell_id; | |
| 309 | + | |
| 310 | + /* | |
| 311 | + * Client alloc gives us a doorbell, but we want to exercise | |
| 312 | + * this ourselves (this resembles guc_init_doorbell_hw) | |
| 313 | + */ | |
| 314 | + destroy_doorbell(clients[i]); | |
| 315 | + if (clients[i]->doorbell_id != GUC_DOORBELL_INVALID) { | |
| 316 | + pr_err("[%d] destroy db did not work!\n", i); | |
| 317 | + err = -EINVAL; | |
| 318 | + goto out; | |
| 319 | + } | |
| 320 | + | |
| 321 | + err = __reserve_doorbell(clients[i]); | |
| 322 | + if (err) { | |
| 323 | + pr_err("[%d] Failed to reserve a doorbell\n", i); | |
| 324 | + goto out; | |
| 325 | + } | |
| 326 | + | |
| 327 | + __update_doorbell_desc(clients[i], clients[i]->doorbell_id); | |
| 328 | + err = __create_doorbell(clients[i]); | |
| 329 | + if (err) { | |
| 330 | + pr_err("[%d] Failed to create a doorbell\n", i); | |
| 331 | + goto out; | |
| 332 | + } | |
| 333 | + | |
| 334 | + /* doorbell id shouldn't change, we are holding the mutex */ | |
| 335 | + if (db_id != clients[i]->doorbell_id) { | |
| 336 | + pr_err("[%d] doorbell id changed (%d != %d)\n", | |
| 337 | + i, db_id, clients[i]->doorbell_id); | |
| 338 | + err = -EINVAL; | |
| 339 | + goto out; | |
| 340 | + } | |
| 341 | + | |
| 342 | + err = check_all_doorbells(guc); | |
| 343 | + if (err) | |
| 344 | + goto out; | |
| 345 | + } | |
| 346 | + | |
| 347 | +out: | |
| 348 | + for (i = 0; i < ATTEMPTS; i++) | |
| 349 | + if (!IS_ERR_OR_NULL(clients[i])) | |
| 350 | + guc_client_free(clients[i]); | |
| 351 | +unlock: | |
| 352 | + mutex_unlock(&dev_priv->drm.struct_mutex); | |
| 353 | + return err; | |
| 354 | +} | |
| 355 | + | |
| 356 | +int intel_guc_live_selftest(struct drm_i915_private *dev_priv) | |
| 357 | +{ | |
| 358 | + static const struct i915_subtest tests[] = { | |
| 359 | + SUBTEST(igt_guc_init_doorbell_hw), | |
| 360 | + SUBTEST(igt_guc_doorbells), | |
| 361 | + }; | |
| 362 | + | |
| 363 | + if (!i915_modparams.enable_guc_submission) | |
| 364 | + return 0; | |
| 365 | + | |
| 366 | + return i915_subtests(tests, dev_priv); | |
| 367 | +} | |
| @@ -120,10 +120,10 @@ static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_pri · 119 unmodified lines | ||
| 120 | 120 | !IS_CHERRYVIEW(dev_priv)) |
| 121 | 121 | return 0; |
| 122 | 122 | |
| 123 | − if (IS_VALLEYVIEW(dev_priv)) /* XXX system lockup! */ | |
| 124 | − return 0; | |
| 125 | − | |
| 126 | − if (IS_BROADWELL(dev_priv)) /* XXX random GPU hang afterwards! */ | |
| 123 | + /* | |
| 124 | + * This test may lockup the machine or cause GPU hangs afterwards. | |
| 125 | + */ | |
| 126 | + if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN)) | |
| 127 | 127 | return 0; |
| 128 | 128 | |
| 129 | 129 | valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid), |
| @@ -148,7 +148,10 @@ static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_pri · 18 unmodified lines | ||
| 148 | 148 | for_each_set_bit(offset, valid, FW_RANGE) { |
| 149 | 149 | i915_reg_t reg = { offset }; |
| 150 | 150 | |
| 151 | + iosf_mbi_punit_acquire(); | |
| 151 | 152 | intel_uncore_forcewake_reset(dev_priv, false); |
| 153 | + iosf_mbi_punit_release(); | |
| 154 | + | |
| 152 | 155 | check_for_unclaimed_mmio(dev_priv); |
| 153 | 156 | |
| 154 | 157 | (void)I915_READ(reg); |
| @@ -32,6 +32,13 @@ static struct mock_request *first_request(struct mock_engine *engine) · 31 unmodified lines | ||
| 32 | 32 | link); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | +static void advance(struct mock_engine *engine, | |
| 36 | + struct mock_request *request) | |
| 37 | +{ | |
| 38 | + list_del_init(&request->link); | |
| 39 | + mock_seqno_advance(&engine->base, request->base.global_seqno); | |
| 40 | +} | |
| 41 | + | |
| 35 | 42 | static void hw_delay_complete(struct timer_list *t) |
| 36 | 43 | { |
| 37 | 44 | struct mock_engine *engine = from_timer(engine, t, hw_delay); |
| @@ -39,15 +46,23 @@ static void hw_delay_complete(struct timer_list *t) · 1 unmodified line | ||
| 39 | 46 | |
| 40 | 47 | spin_lock(&engine->hw_lock); |
| 41 | 48 | |
| 42 | − request = first_request(engine); | |
| 43 | − if (request) { | |
| 44 | − list_del_init(&request->link); | |
| 45 | − mock_seqno_advance(&engine->base, request->base.global_seqno); | |
| 46 | − } | |
| 47 | − | |
| 49 | + /* Timer fired, first request is complete */ | |
| 48 | 50 | request = first_request(engine); |
| 49 | 51 | if (request) |
| 50 | − mod_timer(&engine->hw_delay, jiffies + request->delay); | |
| 52 | + advance(engine, request); | |
| 53 | + | |
| 54 | + /* | |
| 55 | + * Also immediately signal any subsequent 0-delay requests, but | |
| 56 | + * requeue the timer for the next delayed request. | |
| 57 | + */ | |
| 58 | + while ((request = first_request(engine))) { | |
| 59 | + if (request->delay) { | |
| 60 | + mod_timer(&engine->hw_delay, jiffies + request->delay); | |
| 61 | + break; | |
| 62 | + } | |
| 63 | + | |
| 64 | + advance(engine, request); | |
| 65 | + } | |
| 51 | 66 | |
| 52 | 67 | spin_unlock(&engine->hw_lock); |
| 53 | 68 | } |
| @@ -98,16 +113,22 @@ static void mock_submit_request(struct drm_i915_gem_request *request) · 44 unmodified lines | ||
| 98 | 113 | |
| 99 | 114 | spin_lock_irq(&engine->hw_lock); |
| 100 | 115 | list_add_tail(&mock->link, &engine->hw_queue); |
| 101 | − if (mock->link.prev == &engine->hw_queue) | |
| 102 | − mod_timer(&engine->hw_delay, jiffies + mock->delay); | |
| 116 | + if (mock->link.prev == &engine->hw_queue) { | |
| 117 | + if (mock->delay) | |
| 118 | + mod_timer(&engine->hw_delay, jiffies + mock->delay); | |
| 119 | + else | |
| 120 | + advance(engine, mock); | |
| 121 | + } | |
| 103 | 122 | spin_unlock_irq(&engine->hw_lock); |
| 104 | 123 | } |
| 105 | 124 | |
| 106 | 125 | static struct intel_ring *mock_ring(struct intel_engine_cs *engine) |
| 107 | 126 | { |
| 108 | − const unsigned long sz = roundup_pow_of_two(sizeof(struct intel_ring)); | |
| 127 | + const unsigned long sz = PAGE_SIZE / 2; | |
| 109 | 128 | struct intel_ring *ring; |
| 110 | 129 | |
| 130 | + BUILD_BUG_ON(MIN_SPACE_FOR_ADD_REQUEST > sz); | |
| 131 | + | |
| 111 | 132 | ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL); |
| 112 | 133 | if (!ring) |
| 113 | 134 | return NULL; |
| @@ -179,8 +179,8 @@ struct drm_i915_private *mock_gem_device(void) · 178 unmodified lines | ||
| 179 | 179 | I915_GTT_PAGE_SIZE_64K | |
| 180 | 180 | I915_GTT_PAGE_SIZE_2M; |
| 181 | 181 | |
| 182 | − spin_lock_init(&i915->mm.object_stat_lock); | |
| 183 | 182 | mock_uncore_init(i915); |
| 183 | + i915_gem_init__mm(i915); | |
| 184 | 184 | |
| 185 | 185 | init_waitqueue_head(&i915->gpu_error.wait_queue); |
| 186 | 186 | init_waitqueue_head(&i915->gpu_error.reset_queue); |
| @@ -189,11 +189,6 @@ struct drm_i915_private *mock_gem_device(void) · 2 unmodified lines | ||
| 189 | 189 | if (!i915->wq) |
| 190 | 190 | goto put_device; |
| 191 | 191 | |
| 192 | − INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); | |
| 193 | − init_llist_head(&i915->mm.free_list); | |
| 194 | − INIT_LIST_HEAD(&i915->mm.unbound_list); | |
| 195 | − INIT_LIST_HEAD(&i915->mm.bound_list); | |
| 196 | − | |
| 197 | 192 | mock_init_contexts(i915); |
| 198 | 193 | |
| 199 | 194 | INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler); |
| @@ -86,6 +86,22 @@ enum i915_mocs_table_index { · 85 unmodified lines | ||
| 86 | 86 | I915_MOCS_CACHED, |
| 87 | 87 | }; |
| 88 | 88 | |
| 89 | +/* | |
| 90 | + * Different engines serve different roles, and there may be more than one | |
| 91 | + * engine serving each role. enum drm_i915_gem_engine_class provides a | |
| 92 | + * classification of the role of the engine, which may be used when requesting | |
| 93 | + * operations to be performed on a certain subset of engines, or for providing | |
| 94 | + * information about that group. | |
| 95 | + */ | |
| 96 | +enum drm_i915_gem_engine_class { | |
| 97 | + I915_ENGINE_CLASS_RENDER = 0, | |
| 98 | + I915_ENGINE_CLASS_COPY = 1, | |
| 99 | + I915_ENGINE_CLASS_VIDEO = 2, | |
| 100 | + I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, | |
| 101 | + | |
| 102 | + I915_ENGINE_CLASS_INVALID = -1 | |
| 103 | +}; | |
| 104 | + | |
| 89 | 105 | /* Each region is a minimum of 16k, and there are at most 255 of them. |
| 90 | 106 | */ |
| 91 | 107 | #define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use |
| @@ -450,6 +466,27 @@ typedef struct drm_i915_irq_wait { · 358 unmodified lines | ||
| 450 | 466 | */ |
| 451 | 467 | #define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 |
| 452 | 468 | |
| 469 | +/* | |
| 470 | + * Query whether every context (both per-file default and user created) is | |
| 471 | + * isolated (insofar as HW supports). If this parameter is not true, then | |
| 472 | + * freshly created contexts may inherit values from an existing context, | |
| 473 | + * rather than default HW values. If true, it also ensures (insofar as HW | |
| 474 | + * supports) that all state set by this context will not leak to any other | |
| 475 | + * context. | |
| 476 | + * | |
| 477 | + * As not every engine across every gen support contexts, the returned | |
| 478 | + * value reports the support of context isolation for individual engines by | |
| 479 | + * returning a bitmask of each engine class set to true if that class supports | |
| 480 | + * isolation. | |
| 481 | + */ | |
| 482 | +#define I915_PARAM_HAS_CONTEXT_ISOLATION 50 | |
| 483 | + | |
| 484 | +/* Frequency of the command streamer timestamps given by the *_TIMESTAMP | |
| 485 | + * registers. This used to be fixed per platform but from CNL onwards, this | |
| 486 | + * might vary depending on the parts. | |
| 487 | + */ | |
| 488 | +#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51 | |
| 489 | + | |
| 453 | 490 | typedef struct drm_i915_getparam { |
| 454 | 491 | __s32 param; |
| 455 | 492 | /* |