From 4f8207469094bd04aad952258ceb9ff4c77b6bfa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Mar 2025 14:47:39 +0200 Subject: [PATCH 01/16] drm/i915/gvt: fix unterminated-string-initialization warning Initializing const char opregion_signature[16] = OPREGION_SIGNATURE (which is "IntelGraphicsMem") drops the NUL termination of the string. This is intentional, but the compiler doesn't know this. Switch to initializing header->signature directly from the string litaral, with sizeof destination rather than source. We don't treat the signature as a string other than for initialization; it's really just a blob of binary data. Add a static assert for good measure to cross-check the sizes. Reported-by: Kees Cook Closes: https://lore.kernel.org/r/20250310222355.work.417-kees@kernel.org Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13934 Tested-by: Nicolas Chauvet Tested-by: Damian Tometzki Cc: stable@vger.kernel.org Reviewed-by: Zhenyu Wang Link: https://lore.kernel.org/r/20250327124739.2609656-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gvt/opregion.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index 509f9ccae3a9..dbad4d853d3a 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -222,7 +222,6 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu) u8 *buf; struct opregion_header *header; struct vbt v; - const char opregion_signature[16] = OPREGION_SIGNATURE; gvt_dbg_core("init vgpu%d opregion\n", vgpu->id); vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL | @@ -236,8 +235,10 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu) /* emulated opregion with VBT mailbox only */ buf = (u8 *)vgpu_opregion(vgpu)->va; header = (struct opregion_header *)buf; - memcpy(header->signature, opregion_signature, - sizeof(opregion_signature)); + + static_assert(sizeof(header->signature) == sizeof(OPREGION_SIGNATURE) - 1); + memcpy(header->signature, OPREGION_SIGNATURE, sizeof(header->signature)); + header->size = 0x8; header->opregion_ver = 0x02000000; header->mboxes = MBOX_VBT; -- 2.51.0 From 6f5a3b9d6dc41f30b685aa9e9181f9ae2b8ff79b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Feb 2025 11:38:05 +0200 Subject: [PATCH 02/16] drm/i915/gvt: update MAINTAINERS Update GVT-g MAINTAINERS entry to reflect the current status of maintenance and repositories. Cc: Dave Airlie Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Simona Vetter Cc: Tvrtko Ursulin Cc: Zhenyu Wang Cc: Zhi Wang Acked-by: Zhi Wang Acked-by: Zhenyu Wang Acked-by: Simona Vetter Link: https://lore.kernel.org/r/20250227093805.2217658-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- MAINTAINERS | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index cddcb097f7f3..4fb701378ae1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11636,13 +11636,10 @@ F: drivers/gpio/gpio-tangier.c F: drivers/gpio/gpio-tangier.h INTEL GVT-g DRIVERS (Intel GPU Virtualization) -M: Zhenyu Wang -M: Zhi Wang -L: intel-gvt-dev@lists.freedesktop.org -L: intel-gfx@lists.freedesktop.org -S: Supported +R: Zhenyu Wang +R: Zhi Wang +S: Odd Fixes W: https://github.com/intel/gvt-linux/wiki -T: git https://github.com/intel/gvt-linux.git F: drivers/gpu/drm/i915/gvt/ INTEL HID EVENT DRIVER -- 2.51.0 From 513c1a2ec4c6e520798f17b6d8af7a9881fdd69a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Mar 2025 13:54:52 +0200 Subject: [PATCH 03/16] drm/i915: reduce intel_wakeref.h dependencies Forward declare struct drm_printer instead of including drm/drm_print.h, as we only need the pointer. Turns out quite a few places depend on this include implicitly. Make them explicit. Some of the includes are just stale and unnecessary. Group the forward declarations together while at it. Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250326115452.2090275-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_ch7017.c | 2 ++ drivers/gpu/drm/i915/display/dvo_ch7xxx.c | 2 ++ drivers/gpu/drm/i915/display/dvo_ivch.c | 2 ++ drivers/gpu/drm/i915/display/dvo_ns2501.c | 2 ++ drivers/gpu/drm/i915/display/dvo_sil164.c | 2 ++ drivers/gpu/drm/i915/display/dvo_tfp410.c | 2 ++ drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/intel_color.c | 2 ++ drivers/gpu/drm/i915/display/intel_combo_phy.c | 2 ++ drivers/gpu/drm/i915/display/intel_dkl_phy.c | 1 + drivers/gpu/drm/i915/display/intel_dvo.c | 1 + drivers/gpu/drm/i915/display/intel_hti.c | 1 + drivers/gpu/drm/i915/display/intel_load_detect.c | 1 + drivers/gpu/drm/i915/display/intel_lspcon.c | 1 + drivers/gpu/drm/i915/display/intel_pmdemand.c | 2 ++ drivers/gpu/drm/i915/display/intel_snps_phy.c | 2 ++ drivers/gpu/drm/i915/display/intel_tc.c | 2 ++ drivers/gpu/drm/i915/display/intel_vdsc.c | 1 + drivers/gpu/drm/i915/display/intel_vrr.c | 2 ++ drivers/gpu/drm/i915/intel_wakeref.h | 11 ++++------- 20 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/dvo_ch7017.c b/drivers/gpu/drm/i915/display/dvo_ch7017.c index 206818f9ad49..f10c0fb8d2c8 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7017.c @@ -25,6 +25,8 @@ * */ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c index 10ab3cc73e58..49f02aca818b 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c @@ -26,6 +26,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/dvo_ivch.c b/drivers/gpu/drm/i915/display/dvo_ivch.c index d9c3152d4338..0713b2709412 100644 --- a/drivers/gpu/drm/i915/display/dvo_ivch.c +++ b/drivers/gpu/drm/i915/display/dvo_ivch.c @@ -29,6 +29,8 @@ * */ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index 92d32d6b5bce..80b71bd6a837 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -26,6 +26,8 @@ * */ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index b42c717085f3..017b617a8069 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -26,6 +26,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/dvo_tfp410.c b/drivers/gpu/drm/i915/display/dvo_tfp410.c index 280699438526..ed560e3438db 100644 --- a/drivers/gpu/drm/i915/display/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/display/dvo_tfp410.c @@ -25,6 +25,8 @@ * */ +#include + #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ef9a9d780bfc..b69c713fb79a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index bbf6df7ebb95..98dddf72c0eb 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,6 +22,8 @@ * */ +#include + #include "i915_utils.h" #include "i9xx_plane_regs.h" #include "intel_color.h" diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 17eea244cc83..f5cc38dbe559 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -3,6 +3,8 @@ * Copyright © 2018 Intel Corporation */ +#include + #include "i915_reg.h" #include "i915_utils.h" #include "intel_combo_phy.h" diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c index 0813fb9b5823..dad7192132ad 100644 --- a/drivers/gpu/drm/i915/display/intel_dkl_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c @@ -4,6 +4,7 @@ */ #include +#include #include "intel_de.h" #include "intel_display.h" diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 602e76ddf788..b61520353c92 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/display/intel_hti.c b/drivers/gpu/drm/i915/display/intel_hti.c index fb6b84f6a81d..dc454420c134 100644 --- a/drivers/gpu/drm/i915/display/intel_hti.c +++ b/drivers/gpu/drm/i915/display/intel_hti.c @@ -4,6 +4,7 @@ */ #include +#include #include "intel_de.h" #include "intel_display.h" diff --git a/drivers/gpu/drm/i915/display/intel_load_detect.c b/drivers/gpu/drm/i915/display/intel_load_detect.c index 86cc03a4413c..aad52d0d83e1 100644 --- a/drivers/gpu/drm/i915/display/intel_load_detect.c +++ b/drivers/gpu/drm/i915/display/intel_load_detect.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "intel_atomic.h" #include "intel_crtc.h" diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 63c1afa30b05..f94b7eeae20f 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "i915_reg.h" #include "i915_utils.h" diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 63301a01906c..d22b5469672d 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -5,6 +5,8 @@ #include +#include + #include "i915_reg.h" #include "i915_utils.h" #include "intel_atomic.h" diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index b9acd9fe160c..2b53ac9f4935 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -5,6 +5,8 @@ #include +#include + #include "i915_reg.h" #include "i915_utils.h" #include "intel_ddi.h" diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 426a3c8529a3..2c6c18434a4c 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "i915_reg.h" #include "i915_utils.h" #include "intel_atomic.h" diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 470c170897e5..8e799e225af1 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -9,6 +9,7 @@ #include #include +#include #include "i915_utils.h" #include "intel_crtc.h" diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 7359d66fc091..633a66f6b73b 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -4,6 +4,8 @@ * */ +#include + #include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 48836ef52d40..a2894a56e18f 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -7,8 +7,6 @@ #ifndef INTEL_WAKEREF_H #define INTEL_WAKEREF_H -#include - #include #include #include @@ -16,11 +14,13 @@ #include #include #include -#include -#include #include #include +struct drm_printer; +struct intel_runtime_pm; +struct intel_wakeref; + typedef struct ref_tracker *intel_wakeref_t; #define INTEL_REFTRACK_DEAD_COUNT 16 @@ -32,9 +32,6 @@ typedef struct ref_tracker *intel_wakeref_t; #define INTEL_WAKEREF_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) #endif -struct intel_runtime_pm; -struct intel_wakeref; - struct intel_wakeref_ops { int (*get)(struct intel_wakeref *wf); int (*put)(struct intel_wakeref *wf); -- 2.51.0 From da1d515eb1692e87422caefb80799bd716070bbc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 21 Mar 2025 14:51:14 +0200 Subject: [PATCH 04/16] drm/i915/gvt: use hardcoded reference clocks MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Usually I'd argue hardcoding values is the wrong thing to do, but in this case, GVT looking deep into the guts of the DPLL manager for the reference clocks is worse. This is done for BDW and BXT only, and there shouldn't be any reason to try to be so dynamic about it. This helps reduce the direct pokes at display guts from non-display code. Cc: Ville Syrjälä Reviewed-by: Zhenyu Wang Link: https://lore.kernel.org/r/20250321125114.750062-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gvt/handlers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 02f45929592e..e6e9010462e3 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -514,7 +514,7 @@ static u32 bdw_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) switch (wrpll_ctl & WRPLL_REF_MASK) { case WRPLL_REF_PCH_SSC: - refclk = vgpu->gvt->gt->i915->display.dpll.ref_clks.ssc; + refclk = 135000; break; case WRPLL_REF_LCPLL: refclk = 2700000; @@ -545,7 +545,7 @@ out: static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) { u32 dp_br = 0; - int refclk = vgpu->gvt->gt->i915->display.dpll.ref_clks.nssc; + int refclk = 100000; enum dpio_phy phy = DPIO_PHY0; enum dpio_channel ch = DPIO_CH0; struct dpll clock = {}; -- 2.51.0 From 33b3c4791eeacdafdb96ba95dbe24142b73be4da Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:29 +0200 Subject: [PATCH 05/16] drm/i915: Extract intel_memory_type_is_local() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Extract the "is this memory region local?" check into a helper. I'll have another use for this in the BIOS FB takeover. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-2-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 3 +-- drivers/gpu/drm/i915/intel_memory_region.c | 11 +++++++++++ drivers/gpu/drm/i915/intel_memory_region.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index 388f90784d8a..f566191d843b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -48,8 +48,7 @@ bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj) i915_gem_object_evictable(obj)) assert_object_held(obj); #endif - return mr && (mr->type == INTEL_MEMORY_LOCAL || - mr->type == INTEL_MEMORY_STOLEN_LOCAL); + return mr && intel_memory_type_is_local(mr->type); } /** diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index d40ee1b42110..d2abc0315ba1 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -171,6 +171,17 @@ intel_memory_region_by_type(struct drm_i915_private *i915, return NULL; } +bool intel_memory_type_is_local(enum intel_memory_type mem_type) +{ + switch (mem_type) { + case INTEL_MEMORY_LOCAL: + case INTEL_MEMORY_STOLEN_LOCAL: + return true; + default: + return false; + } +} + /** * intel_memory_region_reserve - Reserve a memory range * @mem: The region for which we want to reserve a range. diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 5973b6fe13cf..bfa1697b9566 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -85,6 +85,8 @@ struct intel_memory_region { void *region_private; }; +bool intel_memory_type_is_local(enum intel_memory_type mem_type); + struct intel_memory_region * intel_memory_region_lookup(struct drm_i915_private *i915, u16 class, u16 instance); -- 2.51.0 From 9e2434f32d2894e726c091f89ce0fd05e415d354 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:30 +0200 Subject: [PATCH 06/16] drm/i915: Expose intel_memory_type_str() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Rename region_type_str() into intel_memory_type_str() and expose it outside intel_memory_region.c. I'll have another use for this in the BIOS FB takeover code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-3-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/intel_memory_region.c | 4 ++-- drivers/gpu/drm/i915/intel_memory_region.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index d2abc0315ba1..59bd603e6deb 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -227,7 +227,7 @@ static int intel_memory_region_memtest(struct intel_memory_region *mem, return err; } -static const char *region_type_str(u16 type) +const char *intel_memory_type_str(enum intel_memory_type type) { switch (type) { case INTEL_MEMORY_SYSTEM: @@ -271,7 +271,7 @@ intel_memory_region_create(struct drm_i915_private *i915, mem->instance = instance; snprintf(mem->uabi_name, sizeof(mem->uabi_name), "%s%u", - region_type_str(type), instance); + intel_memory_type_str(type), instance); mutex_init(&mem->objects.lock); INIT_LIST_HEAD(&mem->objects.list); diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index bfa1697b9566..b3b75be9ced5 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -109,6 +109,7 @@ void intel_memory_regions_driver_release(struct drm_i915_private *i915); struct intel_memory_region * intel_memory_region_by_type(struct drm_i915_private *i915, enum intel_memory_type mem_type); +const char *intel_memory_type_str(enum intel_memory_type type); __printf(2, 3) void intel_memory_region_set_name(struct intel_memory_region *mem, -- 2.51.0 From 8f0d3618c6b31b1f8ff0c6c08cf6b101e56d6f8b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:31 +0200 Subject: [PATCH 07/16] agp/intel-gtt: Add intel_gmch_gtt_read_entry() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit i915 wants to read out the PTE(s) populated by the BIOS/GOP to verify that the framebuffer is in the correct location. Introduce intel_gmch_gtt_read_entry() that reads out the PTE and decodes it to a somewhat abstract form. For now we just return the dma_addr, present bit, and local memory bit. I didn't bother with the snoop bit/etc. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-4-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/char/agp/intel-gtt.c | 55 +++++++++++++++++++++++++++++++++++ include/drm/intel/intel-gtt.h | 2 ++ 2 files changed, 57 insertions(+) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index ef30445527a2..bcc26785175d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -53,6 +53,7 @@ struct intel_gtt_driver { * of the mmio register file, that's done in the generic code. */ void (*cleanup)(void); void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); + dma_addr_t (*read_entry)(unsigned int entry, bool *is_present, bool *is_local); /* Flags is a more or less chipset specific opaque value. * For chipsets that need to support old ums (non-gem) code, this * needs to be identical to the various supported agp memory types! */ @@ -336,6 +337,19 @@ static void i810_write_entry(dma_addr_t addr, unsigned int entry, writel_relaxed(addr | pte_flags, intel_private.gtt + entry); } +static dma_addr_t i810_read_entry(unsigned int entry, + bool *is_present, bool *is_local) +{ + u32 val; + + val = readl(intel_private.gtt + entry); + + *is_present = val & I810_PTE_VALID; + *is_local = val & I810_PTE_LOCAL; + + return val & ~0xfff; +} + static resource_size_t intel_gtt_stolen_size(void) { u16 gmch_ctrl; @@ -741,6 +755,19 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, writel_relaxed(addr | pte_flags, intel_private.gtt + entry); } +static dma_addr_t i830_read_entry(unsigned int entry, + bool *is_present, bool *is_local) +{ + u32 val; + + val = readl(intel_private.gtt + entry); + + *is_present = val & I810_PTE_VALID; + *is_local = false; + + return val & ~0xfff; +} + bool intel_gmch_enable_gtt(void) { u8 __iomem *reg; @@ -878,6 +905,13 @@ void intel_gmch_gtt_insert_sg_entries(struct sg_table *st, } EXPORT_SYMBOL(intel_gmch_gtt_insert_sg_entries); +dma_addr_t intel_gmch_gtt_read_entry(unsigned int pg, + bool *is_present, bool *is_local) +{ + return intel_private.driver->read_entry(pg, is_present, is_local); +} +EXPORT_SYMBOL(intel_gmch_gtt_read_entry); + #if IS_ENABLED(CONFIG_AGP_INTEL) static void intel_gmch_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, @@ -1126,6 +1160,19 @@ static void i965_write_entry(dma_addr_t addr, writel_relaxed(addr | pte_flags, intel_private.gtt + entry); } +static dma_addr_t i965_read_entry(unsigned int entry, + bool *is_present, bool *is_local) +{ + u64 val; + + val = readl(intel_private.gtt + entry); + + *is_present = val & I810_PTE_VALID; + *is_local = false; + + return ((val & 0xf0) << 28) | (val & ~0xfff); +} + static int i9xx_setup(void) { phys_addr_t reg_addr; @@ -1187,6 +1234,7 @@ static const struct intel_gtt_driver i81x_gtt_driver = { .cleanup = i810_cleanup, .check_flags = i830_check_flags, .write_entry = i810_write_entry, + .read_entry = i810_read_entry, }; static const struct intel_gtt_driver i8xx_gtt_driver = { .gen = 2, @@ -1194,6 +1242,7 @@ static const struct intel_gtt_driver i8xx_gtt_driver = { .setup = i830_setup, .cleanup = i830_cleanup, .write_entry = i830_write_entry, + .read_entry = i830_read_entry, .dma_mask_size = 32, .check_flags = i830_check_flags, .chipset_flush = i830_chipset_flush, @@ -1205,6 +1254,7 @@ static const struct intel_gtt_driver i915_gtt_driver = { .cleanup = i9xx_cleanup, /* i945 is the last gpu to need phys mem (for overlay and cursors). */ .write_entry = i830_write_entry, + .read_entry = i830_read_entry, .dma_mask_size = 32, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1215,6 +1265,7 @@ static const struct intel_gtt_driver g33_gtt_driver = { .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, + .read_entry = i965_read_entry, .dma_mask_size = 36, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1225,6 +1276,7 @@ static const struct intel_gtt_driver pineview_gtt_driver = { .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, + .read_entry = i965_read_entry, .dma_mask_size = 36, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1235,6 +1287,7 @@ static const struct intel_gtt_driver i965_gtt_driver = { .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, + .read_entry = i965_read_entry, .dma_mask_size = 36, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1244,6 +1297,7 @@ static const struct intel_gtt_driver g4x_gtt_driver = { .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, + .read_entry = i965_read_entry, .dma_mask_size = 36, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1254,6 +1308,7 @@ static const struct intel_gtt_driver ironlake_gtt_driver = { .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, + .read_entry = i965_read_entry, .dma_mask_size = 36, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, diff --git a/include/drm/intel/intel-gtt.h b/include/drm/intel/intel-gtt.h index cb0d5b7200c7..f53bcff01f22 100644 --- a/include/drm/intel/intel-gtt.h +++ b/include/drm/intel/intel-gtt.h @@ -28,6 +28,8 @@ void intel_gmch_gtt_insert_sg_entries(struct sg_table *st, unsigned int pg_start, unsigned int flags); void intel_gmch_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); +dma_addr_t intel_gmch_gtt_read_entry(unsigned int pg, + bool *is_present, bool *is_local); /* Special gtt memory types */ #define AGP_DCACHE_MEMORY 1 -- 2.51.0 From d1b14231aa0cf78ad21e5e83d32e50608928c108 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:32 +0200 Subject: [PATCH 08/16] drm/i915/ggtt: Add intel_ggtt_read_entry() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The BIOS FB takeover code wants to read out the PTEs (or at least one of them) to figure out where the FB is located in memory. Currently we only do that for systems with LMEMBAR, and we've open coded the PTE decoding in the display code. Introduce a more proper abstract interface (intel_ggtt_read_entry()) for this purpose, and implement it for all platforms. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-5-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/gt/intel_ggtt.c | 56 +++++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c | 8 ++++ drivers/gpu/drm/i915/gt/intel_gtt.h | 6 +++ 3 files changed, 70 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index f6c59f20832f..46a5aa4ab9c8 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -289,6 +289,14 @@ u64 gen8_ggtt_pte_encode(dma_addr_t addr, return pte; } +static dma_addr_t gen8_ggtt_pte_decode(u64 pte, bool *is_present, bool *is_local) +{ + *is_present = pte & GEN8_PAGE_PRESENT; + *is_local = pte & GEN12_GGTT_PTE_LM; + + return pte & GEN12_GGTT_PTE_ADDR_MASK; +} + static bool should_update_ggtt_with_bind(struct i915_ggtt *ggtt) { struct intel_gt *gt = ggtt->vm.gt; @@ -435,6 +443,11 @@ static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) writeq(pte, addr); } +static gen8_pte_t gen8_get_pte(void __iomem *addr) +{ + return readq(addr); +} + static void gen8_ggtt_insert_page(struct i915_address_space *vm, dma_addr_t addr, u64 offset, @@ -450,6 +463,16 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, ggtt->invalidate(ggtt); } +static dma_addr_t gen8_ggtt_read_entry(struct i915_address_space *vm, + u64 offset, bool *is_present, bool *is_local) +{ + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); + gen8_pte_t __iomem *pte = + (gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; + + return ggtt->vm.pte_decode(gen8_get_pte(pte), is_present, is_local); +} + static void gen8_ggtt_insert_page_bind(struct i915_address_space *vm, dma_addr_t addr, u64 offset, unsigned int pat_index, u32 flags) @@ -605,6 +628,17 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, ggtt->invalidate(ggtt); } +static dma_addr_t gen6_ggtt_read_entry(struct i915_address_space *vm, + u64 offset, + bool *is_present, bool *is_local) +{ + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); + gen6_pte_t __iomem *pte = + (gen6_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; + + return vm->pte_decode(ioread32(pte), is_present, is_local); +} + /* * Binds an object into the global gtt with the specified cache level. * The object will be accessible to the GPU via commands whose operands @@ -769,6 +803,14 @@ void intel_ggtt_unbind_vma(struct i915_address_space *vm, vm->clear_range(vm, vma_res->start, vma_res->vma_size); } +dma_addr_t intel_ggtt_read_entry(struct i915_address_space *vm, + u64 offset, bool *is_present, bool *is_local) +{ + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); + + return ggtt->vm.read_entry(vm, offset, is_present, is_local); +} + /* * Reserve the top of the GuC address space for firmware images. Addresses * beyond GUC_GGTT_TOP in the GuC address space are inaccessible by GuC, @@ -1245,6 +1287,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->vm.scratch_range = gen8_ggtt_clear_range; ggtt->vm.insert_entries = gen8_ggtt_insert_entries; + ggtt->vm.read_entry = gen8_ggtt_read_entry; /* * Serialize GTT updates with aperture access on BXT if VT-d is on, @@ -1291,6 +1334,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) else ggtt->vm.pte_encode = gen8_ggtt_pte_encode; + ggtt->vm.pte_decode = gen8_ggtt_pte_decode; + return ggtt_probe_common(ggtt, size); } @@ -1390,6 +1435,14 @@ static u64 iris_pte_encode(dma_addr_t addr, return pte; } +static dma_addr_t gen6_pte_decode(u64 pte, bool *is_present, bool *is_local) +{ + *is_present = pte & GEN6_PTE_VALID; + *is_local = false; + + return ((pte & 0xff0) << 28) | (pte & ~0xfff); +} + static int gen6_gmch_probe(struct i915_ggtt *ggtt) { struct drm_i915_private *i915 = ggtt->vm.i915; @@ -1428,6 +1481,7 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) ggtt->vm.scratch_range = gen6_ggtt_clear_range; ggtt->vm.insert_page = gen6_ggtt_insert_page; ggtt->vm.insert_entries = gen6_ggtt_insert_entries; + ggtt->vm.read_entry = gen6_ggtt_read_entry; ggtt->vm.cleanup = gen6_gmch_remove; ggtt->invalidate = gen6_ggtt_invalidate; @@ -1443,6 +1497,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) else ggtt->vm.pte_encode = snb_pte_encode; + ggtt->vm.pte_decode = gen6_pte_decode; + ggtt->vm.vma_ops.bind_vma = intel_ggtt_bind_vma; ggtt->vm.vma_ops.unbind_vma = intel_ggtt_unbind_vma; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 59eed0a0ce90..c5f5f0bdfb2c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -27,6 +27,13 @@ static void gmch_ggtt_insert_page(struct i915_address_space *vm, intel_gmch_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags); } +static dma_addr_t gmch_ggtt_read_entry(struct i915_address_space *vm, + u64 offset, bool *is_present, bool *is_local) +{ + return intel_gmch_gtt_read_entry(offset >> PAGE_SHIFT, + is_present, is_local); +} + static void gmch_ggtt_insert_entries(struct i915_address_space *vm, struct i915_vma_resource *vma_res, unsigned int pat_index, @@ -103,6 +110,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) ggtt->vm.insert_entries = gmch_ggtt_insert_entries; ggtt->vm.clear_range = gmch_ggtt_clear_range; ggtt->vm.scratch_range = gmch_ggtt_clear_range; + ggtt->vm.read_entry = gmch_ggtt_read_entry; ggtt->vm.cleanup = gmch_ggtt_remove; ggtt->invalidate = gmch_ggtt_invalidate; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 0a36ea751b63..9d3a3ad567a0 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -312,6 +312,7 @@ struct i915_address_space { u64 (*pte_encode)(dma_addr_t addr, unsigned int pat_index, u32 flags); /* Create a valid PTE */ + dma_addr_t (*pte_decode)(u64 pte, bool *is_present, bool *is_local); #define PTE_READ_ONLY BIT(0) #define PTE_LM BIT(1) @@ -340,6 +341,8 @@ struct i915_address_space { struct i915_vma_resource *vma_res, unsigned int pat_index, u32 flags); + dma_addr_t (*read_entry)(struct i915_address_space *vm, + u64 offset, bool *is_present, bool *is_local); void (*cleanup)(struct i915_address_space *vm); void (*foreach)(struct i915_address_space *vm, @@ -590,6 +593,9 @@ void intel_ggtt_bind_vma(struct i915_address_space *vm, void intel_ggtt_unbind_vma(struct i915_address_space *vm, struct i915_vma_resource *vma_res); +dma_addr_t intel_ggtt_read_entry(struct i915_address_space *vm, + u64 offset, bool *is_present, bool *is_local); + int i915_ggtt_probe_hw(struct drm_i915_private *i915); int i915_ggtt_init_hw(struct drm_i915_private *i915); int i915_ggtt_enable_hw(struct drm_i915_private *i915); -- 2.51.0 From 50596bdd4e724c9d84885e4a67edc11c622c590b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:33 +0200 Subject: [PATCH 09/16] drm/i915: Use intel_ggtt_read_entry() in the BIOS FB takeover MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use intel_ggtt_read_entry() instead of open coding the PTE read/decode in the BIOS FB takeover code. So far this codepath only covers platforms with LMEMBAR. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-6-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- .../gpu/drm/i915/display/intel_plane_initial.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index b1675b46e06c..2989a5d76c1c 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -57,24 +57,27 @@ initial_plane_phys_lmem(struct intel_display *display, struct intel_initial_plane_config *plane_config) { struct drm_i915_private *i915 = to_i915(display->drm); - gen8_pte_t __iomem *gte = to_gt(i915)->ggtt->gsm; + struct i915_ggtt *ggtt = to_gt(i915)->ggtt; struct intel_memory_region *mem; + bool is_present, is_local; dma_addr_t dma_addr; - gen8_pte_t pte; u32 base; base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); - gte += base / I915_GTT_PAGE_SIZE; + dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); - pte = ioread64(gte); - if (!(pte & GEN12_GGTT_PTE_LM)) { + if (!is_present) { drm_err(display->drm, - "Initial plane programming missing PTE_LM bit\n"); + "Initial plane FB PTE not present\n"); return false; } - dma_addr = pte & GEN12_GGTT_PTE_ADDR_MASK; + if (!is_local) { + drm_err(display->drm, + "Initial plane FB PTE not LMEM\n"); + return false; + } if (IS_DGFX(i915)) mem = i915->mm.regions[INTEL_REGION_LMEM_0]; -- 2.51.0 From 4bef6b0e1049a952fc4d728b7defc42422cab599 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:34 +0200 Subject: [PATCH 10/16] drm/i915: Verify the BIOS FB first PTE on non-LMEMBAR systems MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Now that we have intel_ggtt_read_entry() we can easily read out the first PTE of the BIOS FB and verify that it looks correct. We'll also use the extracted dma address to figure out where in stolen the FB lives (so far we've just assumed that it sits at offset 0, and in practice that does seem to be true, but better safe than sorry). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-7-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- .../drm/i915/display/intel_plane_initial.c | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 2989a5d76c1c..cf7d1a5ab524 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -115,11 +115,28 @@ initial_plane_phys_smem(struct intel_display *display, struct intel_initial_plane_config *plane_config) { struct drm_i915_private *i915 = to_i915(display->drm); + struct i915_ggtt *ggtt = to_gt(i915)->ggtt; struct intel_memory_region *mem; + bool is_present, is_local; + dma_addr_t dma_addr; u32 base; base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); + dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); + + if (!is_present) { + drm_err(display->drm, + "Initial plane FB PTE not present\n"); + return false; + } + + if (is_local) { + drm_err(display->drm, + "Initial plane FB PTE LMEM\n"); + return false; + } + mem = i915->mm.stolen_region; if (!mem) { drm_dbg_kms(display->drm, @@ -127,8 +144,18 @@ initial_plane_phys_smem(struct intel_display *display, return false; } - /* FIXME get and validate the dma_addr from the PTE */ - plane_config->phys_base = base; + if (dma_addr < mem->region.start || dma_addr > mem->region.end) { + drm_err(display->drm, + "Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n", + &dma_addr, mem->region.name, &mem->region.start, &mem->region.end); + return false; + } + + drm_dbg(display->drm, + "Using dma_addr=%pa, based on initial plane programming\n", + &dma_addr); + + plane_config->phys_base = dma_addr - mem->region.start; plane_config->mem = mem; return true; -- 2.51.0 From 0cd161e9472f2eb4be3436670c6db2dd0e3851e4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:35 +0200 Subject: [PATCH 11/16] drm/i915: Use a nicer way to lookup the memory region in BIOS FB takeover MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use intel_memory_region_by_type() to find the appropriate memory region for the BIOS FB takeover. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-8-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- .../drm/i915/display/intel_plane_initial.c | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index cf7d1a5ab524..5f75ef4ba3b1 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -52,6 +52,17 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this, return false; } +static enum intel_memory_type +initial_plane_memory_type(struct drm_i915_private *i915) +{ + if (IS_DGFX(i915)) + return INTEL_MEMORY_LOCAL; + else if (HAS_LMEMBAR_SMEM_STOLEN(i915)) + return INTEL_MEMORY_STOLEN_LOCAL; + else + return INTEL_MEMORY_STOLEN_SYSTEM; +} + static bool initial_plane_phys_lmem(struct intel_display *display, struct intel_initial_plane_config *plane_config) @@ -59,6 +70,7 @@ initial_plane_phys_lmem(struct intel_display *display, struct drm_i915_private *i915 = to_i915(display->drm); struct i915_ggtt *ggtt = to_gt(i915)->ggtt; struct intel_memory_region *mem; + enum intel_memory_type mem_type; bool is_present, is_local; dma_addr_t dma_addr; u32 base; @@ -79,13 +91,12 @@ initial_plane_phys_lmem(struct intel_display *display, return false; } - if (IS_DGFX(i915)) - mem = i915->mm.regions[INTEL_REGION_LMEM_0]; - else - mem = i915->mm.stolen_region; + mem_type = initial_plane_memory_type(i915); + mem = intel_memory_region_by_type(i915, mem_type); if (!mem) { drm_dbg_kms(display->drm, - "Initial plane memory region not initialized\n"); + "Initial plane memory region (type %s) not initialized\n", + intel_memory_type_str(mem_type)); return false; } @@ -117,6 +128,7 @@ initial_plane_phys_smem(struct intel_display *display, struct drm_i915_private *i915 = to_i915(display->drm); struct i915_ggtt *ggtt = to_gt(i915)->ggtt; struct intel_memory_region *mem; + enum intel_memory_type mem_type; bool is_present, is_local; dma_addr_t dma_addr; u32 base; @@ -137,10 +149,12 @@ initial_plane_phys_smem(struct intel_display *display, return false; } - mem = i915->mm.stolen_region; + mem_type = initial_plane_memory_type(i915); + mem = intel_memory_region_by_type(i915, mem_type); if (!mem) { drm_dbg_kms(display->drm, - "Initial plane memory region not initialized\n"); + "Initial plane memory region (type %s) not initialized\n", + intel_memory_type_str(mem_type)); return false; } -- 2.51.0 From a47720c545065aef972fba78c50bf1bdc6f89d02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:36 +0200 Subject: [PATCH 12/16] drm/i915: Lookup the memory region first in the BIOS FB takeover MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When doing the BIOS FB takeover let's look up the appropriate memory region first. If it doesn't exist there's not much point in doing the PTE read/etc either. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-9-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- .../drm/i915/display/intel_plane_initial.c | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 5f75ef4ba3b1..d522da7000ff 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -75,6 +75,15 @@ initial_plane_phys_lmem(struct intel_display *display, dma_addr_t dma_addr; u32 base; + mem_type = initial_plane_memory_type(i915); + mem = intel_memory_region_by_type(i915, mem_type); + if (!mem) { + drm_dbg_kms(display->drm, + "Initial plane memory region (type %s) not initialized\n", + intel_memory_type_str(mem_type)); + return false; + } + base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); @@ -91,15 +100,6 @@ initial_plane_phys_lmem(struct intel_display *display, return false; } - mem_type = initial_plane_memory_type(i915); - mem = intel_memory_region_by_type(i915, mem_type); - if (!mem) { - drm_dbg_kms(display->drm, - "Initial plane memory region (type %s) not initialized\n", - intel_memory_type_str(mem_type)); - return false; - } - /* * On lmem we don't currently expect this to * ever be placed in the stolen portion. @@ -133,6 +133,15 @@ initial_plane_phys_smem(struct intel_display *display, dma_addr_t dma_addr; u32 base; + mem_type = initial_plane_memory_type(i915); + mem = intel_memory_region_by_type(i915, mem_type); + if (!mem) { + drm_dbg_kms(display->drm, + "Initial plane memory region (type %s) not initialized\n", + intel_memory_type_str(mem_type)); + return false; + } + base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); @@ -149,15 +158,6 @@ initial_plane_phys_smem(struct intel_display *display, return false; } - mem_type = initial_plane_memory_type(i915); - mem = intel_memory_region_by_type(i915, mem_type); - if (!mem) { - drm_dbg_kms(display->drm, - "Initial plane memory region (type %s) not initialized\n", - intel_memory_type_str(mem_type)); - return false; - } - if (dma_addr < mem->region.start || dma_addr > mem->region.end) { drm_err(display->drm, "Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n", -- 2.51.0 From 9d293478474f0a7101b678967bf3b3ae88d35696 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:37 +0200 Subject: [PATCH 13/16] drm/i915: Use intel_memory_region_type_is_local() in the BIOS FB takeover MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Replace the hardcoded PTE vs. memory region is_local checks in the BIOS FB takeover with intel_memory_region_type_is_local(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-10-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/intel_plane_initial.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d522da7000ff..6abe17be0add 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -94,9 +94,10 @@ initial_plane_phys_lmem(struct intel_display *display, return false; } - if (!is_local) { + if (intel_memory_type_is_local(mem->type) != is_local) { drm_err(display->drm, - "Initial plane FB PTE not LMEM\n"); + "Initial plane FB PTE unsuitable for %s\n", + mem->region.name); return false; } @@ -152,9 +153,10 @@ initial_plane_phys_smem(struct intel_display *display, return false; } - if (is_local) { + if (intel_memory_type_is_local(mem->type) != is_local) { drm_err(display->drm, - "Initial plane FB PTE LMEM\n"); + "Initial plane FB PTE unsuitable for %s\n", + mem->region.name); return false; } -- 2.51.0 From 544813fb8cbcd8b53ddb6d7dafec6673be91ee2f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 13 Mar 2025 16:08:38 +0200 Subject: [PATCH 14/16] drm/i915: Eliminate the initial_plane_phys_{smem,lmem}() duplication MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit initial_plane_phys_lmem() and initial_plane_phys_smem() are now identical. Remove one of them. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250313140838.29742-11-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- .../drm/i915/display/intel_plane_initial.c | 75 +------------------ 1 file changed, 2 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 6abe17be0add..b0c4892775ce 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -64,67 +64,8 @@ initial_plane_memory_type(struct drm_i915_private *i915) } static bool -initial_plane_phys_lmem(struct intel_display *display, - struct intel_initial_plane_config *plane_config) -{ - struct drm_i915_private *i915 = to_i915(display->drm); - struct i915_ggtt *ggtt = to_gt(i915)->ggtt; - struct intel_memory_region *mem; - enum intel_memory_type mem_type; - bool is_present, is_local; - dma_addr_t dma_addr; - u32 base; - - mem_type = initial_plane_memory_type(i915); - mem = intel_memory_region_by_type(i915, mem_type); - if (!mem) { - drm_dbg_kms(display->drm, - "Initial plane memory region (type %s) not initialized\n", - intel_memory_type_str(mem_type)); - return false; - } - - base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); - - dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); - - if (!is_present) { - drm_err(display->drm, - "Initial plane FB PTE not present\n"); - return false; - } - - if (intel_memory_type_is_local(mem->type) != is_local) { - drm_err(display->drm, - "Initial plane FB PTE unsuitable for %s\n", - mem->region.name); - return false; - } - - /* - * On lmem we don't currently expect this to - * ever be placed in the stolen portion. - */ - if (dma_addr < mem->region.start || dma_addr > mem->region.end) { - drm_err(display->drm, - "Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n", - &dma_addr, mem->region.name, &mem->region.start, &mem->region.end); - return false; - } - - drm_dbg(display->drm, - "Using dma_addr=%pa, based on initial plane programming\n", - &dma_addr); - - plane_config->phys_base = dma_addr - mem->region.start; - plane_config->mem = mem; - - return true; -} - -static bool -initial_plane_phys_smem(struct intel_display *display, - struct intel_initial_plane_config *plane_config) +initial_plane_phys(struct intel_display *display, + struct intel_initial_plane_config *plane_config) { struct drm_i915_private *i915 = to_i915(display->drm); struct i915_ggtt *ggtt = to_gt(i915)->ggtt; @@ -177,18 +118,6 @@ initial_plane_phys_smem(struct intel_display *display, return true; } -static bool -initial_plane_phys(struct intel_display *display, - struct intel_initial_plane_config *plane_config) -{ - struct drm_i915_private *i915 = to_i915(display->drm); - - if (IS_DGFX(i915) || HAS_LMEMBAR_SMEM_STOLEN(i915)) - return initial_plane_phys_lmem(display, plane_config); - else - return initial_plane_phys_smem(display, plane_config); -} - static struct i915_vma * initial_plane_vma(struct intel_display *display, struct intel_initial_plane_config *plane_config) -- 2.51.0 From d354d52c55c6ccebcc4f4148820139f319a4065f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jouni=20H=C3=B6gander?= Date: Mon, 31 Mar 2025 12:07:47 +0300 Subject: [PATCH 15/16] drm/i915/psr: Prevent DP Panel Replay as well when CRC is enable MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We are seeing timeouts in opening CRC fd when testing on setup where DP Panel Replay can be enabled. Fix these by checking if CRC is enabled for DP Panel Replay as well. Signed-off-by: Jouni Högander Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250331090747.2964028-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 55414fa55b12..eef48c014112 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1595,6 +1595,12 @@ _panel_replay_compute_config(struct intel_dp *intel_dp, return false; } + if (crtc_state->crc_enabled) { + drm_dbg_kms(display->drm, + "Panel Replay not enabled because it would inhibit pipe CRC calculation\n"); + return false; + } + if (!intel_dp_is_edp(intel_dp)) return true; @@ -1625,12 +1631,6 @@ _panel_replay_compute_config(struct intel_dp *intel_dp, if (!alpm_config_valid(intel_dp, crtc_state, true)) return false; - if (crtc_state->crc_enabled) { - drm_dbg_kms(display->drm, - "Panel Replay not enabled because it would inhibit pipe CRC calculation\n"); - return false; - } - return true; } -- 2.51.0 From 38188a7f575dacba1120a59fd5d62c7f3313c0fa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 23:07:40 +0200 Subject: [PATCH 16/16] drm/i915/dp: Reject HBR3 when sink doesn't support TPS4 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit According to the DP spec TPS4 is mandatory for HBR3. We have however seen some broken eDP sinks that violate this and declare support for HBR3 without TPS4 support. At least in the case of the icl Dell XPS 13 7390 this results in an unstable output. Reject HBR3 when TPS4 supports is unavailable on the sink. v2: Leave breadcrumbs in dmesg to avoid head scratching (Jani) Cc: stable@vger.kernel.org Cc: Jani Nikula Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5969 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306210740.11886-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 49 +++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f21f9b441fc2..7b95d62730e6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -172,10 +172,28 @@ int intel_dp_link_symbol_clock(int rate) static int max_dprx_rate(struct intel_dp *intel_dp) { + struct intel_display *display = to_intel_display(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + int max_rate; + if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp)) - return drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel); + max_rate = drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel); + else + max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]); - return drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]); + /* + * Some broken eDP sinks illegally declare support for + * HBR3 without TPS4, and are unable to produce a stable + * output. Reject HBR3 when TPS4 is not available. + */ + if (max_rate >= 810000 && !drm_dp_tps4_supported(intel_dp->dpcd)) { + drm_dbg_kms(display->drm, + "[ENCODER:%d:%s] Rejecting HBR3 due to missing TPS4 support\n", + encoder->base.base.id, encoder->base.name); + max_rate = 540000; + } + + return max_rate; } static int max_dprx_lane_count(struct intel_dp *intel_dp) @@ -4170,6 +4188,9 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp) static void intel_edp_set_sink_rates(struct intel_dp *intel_dp) { + struct intel_display *display = to_intel_display(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + intel_dp->num_sink_rates = 0; if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { @@ -4180,10 +4201,7 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp) sink_rates, sizeof(sink_rates)); for (i = 0; i < ARRAY_SIZE(sink_rates); i++) { - int val = le16_to_cpu(sink_rates[i]); - - if (val == 0) - break; + int rate; /* Value read multiplied by 200kHz gives the per-lane * link rate in kHz. The source rates are, however, @@ -4191,7 +4209,24 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp) * back to symbols is * (val * 200kHz)*(8/10 ch. encoding)*(1/8 bit to Byte) */ - intel_dp->sink_rates[i] = (val * 200) / 10; + rate = le16_to_cpu(sink_rates[i]) * 200 / 10; + + if (rate == 0) + break; + + /* + * Some broken eDP sinks illegally declare support for + * HBR3 without TPS4, and are unable to produce a stable + * output. Reject HBR3 when TPS4 is not available. + */ + if (rate >= 810000 && !drm_dp_tps4_supported(intel_dp->dpcd)) { + drm_dbg_kms(display->drm, + "[ENCODER:%d:%s] Rejecting HBR3 due to missing TPS4 support\n", + encoder->base.base.id, encoder->base.name); + break; + } + + intel_dp->sink_rates[i] = rate; } intel_dp->num_sink_rates = i; } -- 2.51.0