From 0f45696ddb2b901fbf15cb8d2e89767be481d59f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 7 May 2025 18:19:53 +0300 Subject: [PATCH 001/902] drm/i915/dp: Fix determining SST/MST mode during MTP TU state computation Determining the SST/MST mode during state computation must be done based on the output type stored in the CRTC state, which in turn is set once based on the modeset connector's SST vs. MST type and will not change as long as the connector is using the CRTC. OTOH the MST mode indicated by the given connector's intel_dp::is_mst flag can change independently of the above output type, based on what sink is at any moment plugged to the connector. Fix the state computation accordingly. Cc: Jani Nikula Fixes: f6971d7427c2 ("drm/i915/mst: adapt intel_dp_mtp_tu_compute_config() for 128b/132b SST") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4607 Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250507151953.251846-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index aeda59f5fa7a4..30f5636d18b7d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -253,7 +253,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - bool is_mst = intel_dp->is_mst; + bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); int bpp_x16, slots = -EINVAL; int dsc_slice_count = 0; int max_dpt_bpp_x16; -- GitLab From ff868667a4f9c6e349f4a4f0dcc3ff60d6ea8a73 Mon Sep 17 00:00:00 2001 From: Julia Filipchuk Date: Fri, 2 May 2025 15:39:24 -0700 Subject: [PATCH 002/902] drm/i915/guc: Enable DUAL_QUEUE_WA for newer platforms For newer platforms (post DG2) hardware intentionally stalls on submisstion of concurrent submissions on RCS and CCS of different address spaces. With this workaround GuC will never schedule such conlicting contexts; preventing detection of a stall as a hang. GuC specs recommend to enable this for all platforms starting from MTL supporting CCS. v2: Use existing macros for version check. (Jani) v3: Reword explanation for clarity. Remove unneeded parens. Remove accidental comment change. (Daniele) Signed-off-by: Julia Filipchuk Cc: Daniele Ceraolo Spurio Reviewed-by: Daniele Ceraolo Spurio Signed-off-by: Daniele Ceraolo Spurio Link: https://lore.kernel.org/r/20250502223924.94628-1-julia.filipchuk@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 5949ff0b0161f..553daf32c0b54 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -313,8 +313,13 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) * * The same WA bit is used for both and 22011391025 is applicable to * all DG2. + * + * Platforms post DG2 prevent this issue in hardware by stalling + * submissions. With this flag GuC will schedule as to avoid such + * stalls. */ - if (IS_DG2(gt->i915)) + if (IS_DG2(gt->i915) || + (CCS_MASK(gt) && GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70))) flags |= GUC_WA_DUAL_QUEUE; /* Wa_22011802037: graphics version 11/12 */ -- GitLab From 243bf99e2fe75edf8df1711c1377b6fc020b806c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Thu, 8 May 2025 13:29:31 +0200 Subject: [PATCH 003/902] drm/xe: Fix the gem shrinker name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe buffer object shrinker name is visible in the /shrinker directory and most if not all other shinkers follow a naming convention that looks like -_: Follow the same convention for xe, changing the name to drm-xe_gem:. Other shrinkers typically use the device node for but since drm drivers typically don't have a single unique device- node, instead use the unique name in the drm device. Fixes: 00c8efc3180f ("drm/xe: Add a shrinker for xe bos") Cc: Matthew Brost Signed-off-by: Thomas Hellström Reviewed-by: Francois Dugast Link: https://lore.kernel.org/r/20250508112931.3347-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_shrinker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c index 8184390f9c7b9..86d47aaf03589 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -227,7 +227,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) if (!shrinker) return ERR_PTR(-ENOMEM); - shrinker->shrink = shrinker_alloc(0, "xe system shrinker"); + shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique); if (!shrinker->shrink) { kfree(shrinker); return ERR_PTR(-ENOMEM); -- GitLab From 5dd933e33b9a2a379bcdefa140b4ee94ea184444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Thu, 8 May 2025 13:30:15 +0200 Subject: [PATCH 004/902] drm/xe: Make the gem shrinker drm managed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the xe drm shrinker drm managed like many other resources created at device creation time. Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/20250508113015.3374-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_device.c | 9 +++----- drivers/gpu/drm/xe/xe_shrinker.c | 37 ++++++++++++++++---------------- drivers/gpu/drm/xe/xe_shrinker.h | 4 +--- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index c02c4c4e94128..399ae5f40321a 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -402,9 +402,6 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy) if (xe->unordered_wq) destroy_workqueue(xe->unordered_wq); - if (!IS_ERR_OR_NULL(xe->mem.shrinker)) - xe_shrinker_destroy(xe->mem.shrinker); - if (xe->destroy_wq) destroy_workqueue(xe->destroy_wq); @@ -438,9 +435,9 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, if (err) goto err; - xe->mem.shrinker = xe_shrinker_create(xe); - if (IS_ERR(xe->mem.shrinker)) - return ERR_CAST(xe->mem.shrinker); + err = xe_shrinker_create(xe); + if (err) + goto err; xe->info.devid = pdev->device; xe->info.revid = pdev->revision; diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c index 86d47aaf03589..125c836e0ee42 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -5,6 +5,7 @@ #include +#include #include #include #include @@ -213,24 +214,34 @@ static void xe_shrinker_pm(struct work_struct *work) xe_pm_runtime_put(shrinker->xe); } +static void xe_shrinker_fini(struct drm_device *drm, void *arg) +{ + struct xe_shrinker *shrinker = arg; + + xe_assert(shrinker->xe, !shrinker->shrinkable_pages); + xe_assert(shrinker->xe, !shrinker->purgeable_pages); + shrinker_free(shrinker->shrink); + flush_work(&shrinker->pm_worker); + kfree(shrinker); +} + /** * xe_shrinker_create() - Create an xe per-device shrinker * @xe: Pointer to the xe device. * - * Returns: A pointer to the created shrinker on success, - * Negative error code on failure. + * Return: %0 on success. Negative error code on failure. */ -struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) +int xe_shrinker_create(struct xe_device *xe) { struct xe_shrinker *shrinker = kzalloc(sizeof(*shrinker), GFP_KERNEL); if (!shrinker) - return ERR_PTR(-ENOMEM); + return -ENOMEM; shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique); if (!shrinker->shrink) { kfree(shrinker); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } INIT_WORK(&shrinker->pm_worker, xe_shrinker_pm); @@ -240,19 +251,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) shrinker->shrink->scan_objects = xe_shrinker_scan; shrinker->shrink->private_data = shrinker; shrinker_register(shrinker->shrink); + xe->mem.shrinker = shrinker; - return shrinker; -} - -/** - * xe_shrinker_destroy() - Destroy an xe per-device shrinker - * @shrinker: Pointer to the shrinker to destroy. - */ -void xe_shrinker_destroy(struct xe_shrinker *shrinker) -{ - xe_assert(shrinker->xe, !shrinker->shrinkable_pages); - xe_assert(shrinker->xe, !shrinker->purgeable_pages); - shrinker_free(shrinker->shrink); - flush_work(&shrinker->pm_worker); - kfree(shrinker); + return drmm_add_action_or_reset(&xe->drm, xe_shrinker_fini, shrinker); } diff --git a/drivers/gpu/drm/xe/xe_shrinker.h b/drivers/gpu/drm/xe/xe_shrinker.h index 28a038f4fcbff..5132ae5192e1c 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.h +++ b/drivers/gpu/drm/xe/xe_shrinker.h @@ -11,8 +11,6 @@ struct xe_device; void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable); -struct xe_shrinker *xe_shrinker_create(struct xe_device *xe); - -void xe_shrinker_destroy(struct xe_shrinker *shrinker); +int xe_shrinker_create(struct xe_device *xe); #endif -- GitLab From c58af5cd9c6529e92d559b66470ae1bca6360015 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 2 May 2025 15:07:25 +0300 Subject: [PATCH 005/902] drm/i915/irq: stop using HAS_GMCH() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right or wrong, HAS_GMCH() has become a display only thing. The last three users outside of display are in irq code. Reorder the if ladders to stop using HAS_GMCH(). Reviewed-by: Michał Grzelak Link: https://lore.kernel.org/r/20250502120725.439800-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_irq.c | 105 +++++++++++++++----------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 95042879bec4a..cc05f347555ad 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1152,71 +1152,62 @@ void intel_irq_fini(struct drm_i915_private *i915) static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - return cherryview_irq_handler; - else if (IS_VALLEYVIEW(dev_priv)) - return valleyview_irq_handler; - else if (GRAPHICS_VER(dev_priv) == 4) - return i965_irq_handler; - else - return i915_irq_handler; - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - return dg1_irq_handler; - else if (GRAPHICS_VER(dev_priv) >= 11) - return gen11_irq_handler; - else if (GRAPHICS_VER(dev_priv) >= 8) - return gen8_irq_handler; - else - return ilk_irq_handler; - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + return dg1_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 11) + return gen11_irq_handler; + else if (IS_CHERRYVIEW(dev_priv)) + return cherryview_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 8) + return gen8_irq_handler; + else if (IS_VALLEYVIEW(dev_priv)) + return valleyview_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 5) + return ilk_irq_handler; + else if (GRAPHICS_VER(dev_priv) == 4) + return i965_irq_handler; + else + return i915_irq_handler; } static void intel_irq_reset(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - cherryview_irq_reset(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) - valleyview_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) == 4) - i965_irq_reset(dev_priv); - else - i915_irq_reset(dev_priv); - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - dg1_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 11) - gen11_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 8) - gen8_irq_reset(dev_priv); - else - ilk_irq_reset(dev_priv); - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + dg1_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 11) + gen11_irq_reset(dev_priv); + else if (IS_CHERRYVIEW(dev_priv)) + cherryview_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 8) + gen8_irq_reset(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 5) + ilk_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) == 4) + i965_irq_reset(dev_priv); + else + i915_irq_reset(dev_priv); } static void intel_irq_postinstall(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - cherryview_irq_postinstall(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) - valleyview_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) == 4) - i965_irq_postinstall(dev_priv); - else - i915_irq_postinstall(dev_priv); - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - dg1_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 11) - gen11_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 8) - gen8_irq_postinstall(dev_priv); - else - ilk_irq_postinstall(dev_priv); - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + dg1_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 11) + gen11_irq_postinstall(dev_priv); + else if (IS_CHERRYVIEW(dev_priv)) + cherryview_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 8) + gen8_irq_postinstall(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 5) + ilk_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) == 4) + i965_irq_postinstall(dev_priv); + else + i915_irq_postinstall(dev_priv); } /** -- GitLab From 5dff17241483d934d8a72633fb2c2b7eaf2d91a3 Mon Sep 17 00:00:00 2001 From: Mikolaj Wasiak Date: Fri, 9 May 2025 09:57:18 +0200 Subject: [PATCH 006/902] drm/i915/selftest: allow larger memory allocation Due to changes in allocator, the size of the allocation for contiguous region is not rounded up to a power-of-two and instead allocated as is. Thus, change the part of test that expected the allocation to fail. Signed-off-by: Mikolaj Wasiak Reviewed-by: Krzysztof Karas Reviewed-by: Andi Shyti Reviewed-by: Krzysztof Niemiec Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/fptevdfbclvg2lbfuys5ibffbl2baouywkutnr7vdsy5tzcqfk@mpflwlh6jxfd --- .../gpu/drm/i915/selftests/intel_memory_region.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index f08f6674911ee..7b856b5090f9a 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -413,15 +413,8 @@ static int igt_mock_splintered_region(void *arg) close_objects(mem, &objects); - /* - * While we should be able allocate everything without any flag - * restrictions, if we consider I915_BO_ALLOC_CONTIGUOUS then we are - * actually limited to the largest power-of-two for the region size i.e - * max_order, due to the inner workings of the buddy allocator. So make - * sure that does indeed hold true. - */ - - obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS); + obj = igt_object_create(mem, &objects, roundup_pow_of_two(size), + I915_BO_ALLOC_CONTIGUOUS); if (!IS_ERR(obj)) { pr_err("%s too large contiguous allocation was not rejected\n", __func__); @@ -429,8 +422,7 @@ static int igt_mock_splintered_region(void *arg) goto out_close; } - obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size), - I915_BO_ALLOC_CONTIGUOUS); + obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS); if (IS_ERR(obj)) { pr_err("%s largest possible contiguous allocation failed\n", __func__); -- GitLab From 266e2fcfe2ea0d062ea392cd22f6250ae0d11c04 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:28 +0300 Subject: [PATCH 007/902] drm/i915/dp_mst: Use the correct connector while computing the link BPP limit on MST Atm, on an MST link in DSC mode intel_dp_compute_config_link_bpp_limits() calculates the maximum link bpp limit using the MST root connector's DSC capabilities. That's not correct in general: the decompression could be performed by a branch device downstream of the root branch device or the sink itself. Fix the above by passing to intel_dp_compute_config_link_bpp_limits() the actual connector being modeset, containing the correct DSC capabilities. Cc: Ankit Nautiyal Fixes: 1c5b72daff46 ("drm/i915/dp: Set the DSC link limits in intel_dp_compute_config_link_bpp_limits") Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 593b29b56714a..ad1e4fc9c7fe3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2524,6 +2524,7 @@ intel_dp_dsc_compute_pipe_bpp_limits(struct intel_dp *intel_dp, bool intel_dp_compute_config_limits(struct intel_dp *intel_dp, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool respect_downstream_limits, bool dsc, @@ -2577,7 +2578,7 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, intel_dp_test_compute_config(intel_dp, crtc_state, limits); return intel_dp_compute_config_link_bpp_limits(intel_dp, - intel_dp->attached_connector, + connector, crtc_state, dsc, limits); @@ -2638,7 +2639,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || - !intel_dp_compute_config_limits(intel_dp, pipe_config, + !intel_dp_compute_config_limits(intel_dp, connector, pipe_config, respect_downstream_limits, false, &limits); @@ -2672,7 +2673,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); - if (!intel_dp_compute_config_limits(intel_dp, pipe_config, + if (!intel_dp_compute_config_limits(intel_dp, connector, pipe_config, respect_downstream_limits, true, &limits)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index a7cc10800e0b4..742ae26ac4a9a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -194,6 +194,7 @@ void intel_dp_wait_source_oui(struct intel_dp *intel_dp); int intel_dp_output_bpp(enum intel_output_format output_format, int bpp); bool intel_dp_compute_config_limits(struct intel_dp *intel_dp, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool respect_downstream_limits, bool dsc, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 30f5636d18b7d..06f4ad8de591e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -599,12 +599,13 @@ adjust_limits_for_dsc_hblank_expansion_quirk(struct intel_dp *intel_dp, static bool mst_stream_compute_config_limits(struct intel_dp *intel_dp, - const struct intel_connector *connector, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool dsc, struct link_config_limits *limits) { - if (!intel_dp_compute_config_limits(intel_dp, crtc_state, false, dsc, + if (!intel_dp_compute_config_limits(intel_dp, connector, + crtc_state, false, dsc, limits)) return false; -- GitLab From 49a50054b784989ad56f8df911611f823d628044 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:29 +0300 Subject: [PATCH 008/902] drm/i915/dp_mst: Simplify handling the single-bpp case during state computation A follow-up change wants to skip invalid bpps in the bpp select loop of a stream state computation. To allow for that, using the usual 'continue' statement in the loop, change the way the single-bpp range is handled. v2: Fix typo in commit message. (Ankit) Cc: Jani Nikula Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 06f4ad8de591e..fa969b46245cd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -263,6 +263,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, fxp_q4_to_frac(max_bpp_x16) || fxp_q4_to_frac(bpp_step_x16))); + if (!bpp_step_x16) { + /* Allow using zero step only to indicate single try for a given bpp. */ + drm_WARN_ON(display->drm, min_bpp_x16 != max_bpp_x16); + bpp_step_x16 = 1; + } + if (is_mst) { mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst.mgr); if (IS_ERR(mst_state)) @@ -386,10 +392,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, break; } - - /* Allow using zero step to indicate one try */ - if (!bpp_step_x16) - break; } if (slots < 0) { -- GitLab From 97ae79d3ad91122991d1ad0032be02fa3e9d918f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:30 +0300 Subject: [PATCH 009/902] drm/i915/dp_mst: Validate compressed bpp vs. platform restrictions Atm TGL supports only a fixed set of valid DSC compressed bpps (6,8,10,12,15), but this is not taken into account while looking for a bpp in the minimum..maximum compressed bpp range. This happened to work only by chance since atm from the above min..max range it's always the maximum bpp that is selected, which is one of the above valid bpps (see mst_stream_dsc_compute_link_config() -> intel_dp_dsc_nearest_valid_bpp()). Before selecting a bpp however, the bpp's BW requirement should be checked wrt. to the MST total link BW; after doing that - in a follow-up change - the validity of any bpp in the min..max range must be ensured before the bpp is selected, do that here. Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 9 ++++++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ad1e4fc9c7fe3..c67c3b5b2dafa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2111,8 +2111,11 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) return fxp_q4_from_int(1) / incr; } -/* Note: This is not universally usable! */ -static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) +/* + * Note: for bpp_x16 to be valid it must be also within the source/sink's + * min..max bpp capability range. + */ +bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16) { struct intel_display *display = to_intel_display(intel_dp); int i; @@ -2176,7 +2179,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { - if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) + if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) continue; ret = dsc_compute_link_config(intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 742ae26ac4a9a..4d8c3f2b90dff 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -147,6 +147,7 @@ int intel_dp_dsc_sink_min_compressed_bpp(const struct intel_crtc_state *pipe_con int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector, const struct intel_crtc_state *pipe_config, int bpc); +bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16); u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, int num_joined_pipes); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index fa969b46245cd..196182c3fd988 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -310,6 +310,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16)); + if (dsc && !intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) { + /* SST must have validated the single bpp tried here already earlier. */ + drm_WARN_ON(display->drm, !is_mst); + continue; + } + link_bpp_x16 = dsc ? bpp_x16 : fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format, fxp_q4_to_int(bpp_x16))); -- GitLab From dd697c720fea53d415c4d86f6e128b8bfceb35ce Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:31 +0300 Subject: [PATCH 010/902] drm/i915/dp_mst: Update the total link slot count early A follow up change will check a selected bpp's BW requirement in intel_dp_mtp_tu_compute_config(), however that requires the total link slot count to be up-to-date. The latter in turn depends on the channel encoding and hence the link rate used, so it can be set after the link rate used is selected. This also allows simplifying mst_stream_update_slots(), do that as well, moving the function definition before its use. Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 36 +++++++-------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 196182c3fd988..4345107aa3e81 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -241,6 +241,15 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec num_joined_pipes); } +static void mst_stream_update_slots(const struct intel_crtc_state *crtc_state, + struct drm_dp_mst_topology_state *topology_state) +{ + u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ? + DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B; + + drm_dp_mst_update_slots(topology_state, link_coding_cap); +} + int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, @@ -276,6 +285,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, crtc_state->lane_count); + + mst_stream_update_slots(crtc_state, mst_state); } if (dsc) { @@ -491,27 +502,6 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, fxp_q4_from_int(1), true); } -static int mst_stream_update_slots(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct intel_display *display = to_intel_display(intel_dp); - struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst.mgr; - struct drm_dp_mst_topology_state *topology_state; - u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ? - DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B; - - topology_state = drm_atomic_get_mst_topology_state(conn_state->state, mgr); - if (IS_ERR(topology_state)) { - drm_dbg_kms(display->drm, "slot update failed\n"); - return PTR_ERR(topology_state); - } - - drm_dp_mst_update_slots(topology_state, link_coding_cap); - - return 0; -} - static int mode_hblank_period_ns(const struct drm_display_mode *mode) { return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(mode->htotal - mode->hdisplay, @@ -714,10 +704,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder, pipe_config->dp_m_n.tu); } - if (ret) - return ret; - - ret = mst_stream_update_slots(intel_dp, pipe_config, conn_state); if (ret) return ret; -- GitLab From c2a38dc3006a2f8eff7044a3d1f0510fd7b749bd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:32 +0300 Subject: [PATCH 011/902] drm/i915/dp_mst: Check BW limit on the local MST link early Check the BW requirement of a selected compressed bpp against the total MST link BW early. This didn't cause a problem, since all the BW limits within the MST topology are checked during the later MST topology BW check. However it doesn't make sense to defer the total link BW check, since for resolving a BW limit issue due to this later also (a) requires selecting a pipe to reduce its bpp, ending up reducing the bpp for another pipe, which is not ideal (b) requires recomputing the state for all CRTC/stream's in the topology which may slow down the commit considerably (especially when using fractional bpps). Based on the above, check a stream bpp's BW requirement against the MST link's total BW early. Ideally drm_dp_atomic_find_time_slots() should check internally the corresponding PBN/TU slot BW against the total link BW, returning an error if the check fails, however that change would also affect other drivers, so leaving this for a follow-up. v2: Rephrase description of pipe selection/bpp reduction in commit message. (Ankit) Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 4345107aa3e81..ff88888e4b293 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -390,6 +390,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst.mgr, connector->mst.port, dfixed_trunc(pbn)); + + /* TODO: Check this already in drm_dp_atomic_find_time_slots(). */ + if (slots > mst_state->total_avail_slots) + slots = -EINVAL; } else { /* Same as above for remote_tu */ crtc_state->dp_m_n.tu = ALIGN(crtc_state->dp_m_n.tu, -- GitLab From 1f581f38bc0d23c6ac6714c84a72e098f1f645fe Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:33 +0300 Subject: [PATCH 012/902] drm/i915/dp_mst: Simplify computing the min/max compressed bpp limits Adjusting the compressed bpp range min/max limits in intel_dp_dsc_nearest_valid_bpp() is unnecessary: - The source/sink min/max values are enforced already by the link_config_limits::min_bpp_x16/max_bpp_x16 values computed early in intel_dp_compute_config_link_bpp_limits(). - The fixed set of valid bpps are enforced already - for all bpps in the min .. max range by intel_dp_dsc_valid_compressed_bpp() called from intel_dp_mtp_tu_compute_config(). The only thing needed is limiting max compressed bpp below the uncompressed pipe bpp, do that one thing only instead of calling intel_dp_dsc_nearest_valid_bpp(). Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.h | 2 -- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c67c3b5b2dafa..f8de29d8a4da4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -847,7 +847,7 @@ small_joiner_ram_size_bits(struct intel_display *display) return 6144 * 8; } -u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp) +static u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp) { u32 bits_per_pixel = bpp; int i; diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 4d8c3f2b90dff..2fe6720a88fc1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -174,8 +174,6 @@ bool intel_dp_supports_dsc(struct intel_dp *intel_dp, const struct intel_connector *connector, const struct intel_crtc_state *crtc_state); -u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp); - void intel_ddi_update_pipe(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index ff88888e4b293..42351229177d8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -491,11 +491,7 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, drm_dbg_kms(display->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n", min_compressed_bpp, max_compressed_bpp); - /* Align compressed bpps according to our own constraints */ - max_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, max_compressed_bpp, - crtc_state->pipe_bpp); - min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, min_compressed_bpp, - crtc_state->pipe_bpp); + max_compressed_bpp = min(max_compressed_bpp, crtc_state->pipe_bpp - 1); crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; -- GitLab From 7acc7a6fc77413ab061819cee2ab7771c4132cf0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:34 +0300 Subject: [PATCH 013/902] drm/i915/dp: Limit max link bpp properly to a fractional value on SST The maximum link bpp - determined by the link BW for instance - can be fractional, handle this properly during computing the link bpp on SST. This keeps the pipe joiner specific maximum link bpp as a rounded-down integer value still, changing that to a fractional value is left for later. v2: Align the min/max bpp value to the bpp step. Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-8-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f8de29d8a4da4..b91c1e43051a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include #include @@ -939,6 +941,7 @@ static u32 ultrajoiner_ram_max_bpp(u32 mode_hdisplay) return ultrajoiner_ram_bits() / mode_hdisplay; } +/* TODO: return a bpp_x16 value */ static u32 get_max_compressed_bpp_with_joiner(struct intel_display *display, u32 mode_clock, u32 mode_hdisplay, @@ -2153,24 +2156,16 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, const struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int output_bpp; - int dsc_min_bpp; - int dsc_max_bpp; int min_bpp_x16, max_bpp_x16, bpp_step_x16; int dsc_joiner_max_bpp; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); int bpp_x16; int ret; - dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16); - dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(display, adjusted_mode->clock, adjusted_mode->hdisplay, num_joined_pipes); - dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16)); - - /* FIXME: remove the round trip via integers */ - min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); - max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp); + max_bpp_x16 = min(fxp_q4_from_int(dsc_joiner_max_bpp), limits->link.max_bpp_x16); bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); @@ -2178,6 +2173,10 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); + drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16)); + min_bpp_x16 = round_up(limits->link.min_bpp_x16, bpp_step_x16); + max_bpp_x16 = round_down(max_bpp_x16, bpp_step_x16); + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) continue; -- GitLab From 00f00859820e021e0f228ff3244401da6efc9d51 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:35 +0300 Subject: [PATCH 014/902] drm/i915/dp_mst: Add support for fractional compressed link bpps on MST Add support for a fractional compressed link bpp on an MST link. Leave the actual enabling of fractional bpps to a follow-up change. While at it add an assert before the bpp loop, that the min and max bpps are aligned to the bpp step. This should hold regardless of the non-DSC/DSC or MST/UHBR-SST modes. This keeps the mode validation and DSC->DPT BW specific maximum link bpps as rounded-down integer values still, changing those to a fractional value is left for later, add here TODO comments for them. v2: - Align the min/max bpp value to the bpp step. - Assert that the min/max bpp values are aligned to the bpp step. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-9-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 32 +++++++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b91c1e43051a1..cdbdf20a46b7d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -958,6 +958,7 @@ u32 get_max_compressed_bpp_with_joiner(struct intel_display *display, return max_bpp; } +/* TODO: return a bpp_x16 value */ u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display, u32 link_clock, u32 lane_count, u32 mode_clock, u32 mode_hdisplay, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 42351229177d8..13b2bd3ec8607 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -23,6 +23,9 @@ * */ +#include +#include + #include #include #include @@ -135,6 +138,7 @@ static bool intel_dp_mst_inc_active_streams(struct intel_dp *intel_dp) return intel_dp->mst.active_streams++ == 0; } +/* TODO: return a bpp_x16 value */ static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state, bool dsc) { @@ -315,6 +319,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, } } + drm_WARN_ON(display->drm, min_bpp_x16 % bpp_step_x16 || max_bpp_x16 % bpp_step_x16); + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { int local_bw_overhead; int link_bpp_x16; @@ -460,7 +466,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, int num_bpc; u8 dsc_bpc[3] = {}; int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp; - int min_compressed_bpp, max_compressed_bpp; + int min_compressed_bpp_x16, max_compressed_bpp_x16; + int bpp_step_x16; max_bpp = limits->pipe.max_bpp; min_bpp = limits->pipe.min_bpp; @@ -485,21 +492,28 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, crtc_state->pipe_bpp = max_bpp; - max_compressed_bpp = fxp_q4_to_int(limits->link.max_bpp_x16); - min_compressed_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16); + min_compressed_bpp_x16 = limits->link.min_bpp_x16; + max_compressed_bpp_x16 = limits->link.max_bpp_x16; + + drm_dbg_kms(display->drm, + "DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n", + FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16)); + + bpp_step_x16 = fxp_q4_from_int(1); - drm_dbg_kms(display->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n", - min_compressed_bpp, max_compressed_bpp); + max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16); - max_compressed_bpp = min(max_compressed_bpp, crtc_state->pipe_bpp - 1); + drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16)); + min_compressed_bpp_x16 = round_up(min_compressed_bpp_x16, bpp_step_x16); + max_compressed_bpp_x16 = round_down(max_compressed_bpp_x16, bpp_step_x16); crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, - fxp_q4_from_int(min_compressed_bpp), - fxp_q4_from_int(max_compressed_bpp), - fxp_q4_from_int(1), true); + min_compressed_bpp_x16, + max_compressed_bpp_x16, + bpp_step_x16, true); } static int mode_hblank_period_ns(const struct drm_display_mode *mode) -- GitLab From a43a02d8f5f4360f7e2473c54cddc4a9bfcd0b62 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:36 +0300 Subject: [PATCH 015/902] drm/i915/display: Factor out intel_display_{min, max}_pipe_bpp() Factor out helpers that can be used in a follow-up change to query the minimum and maximum pipe bpp supported by the HW. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-10-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 28 +++++++++++++------- drivers/gpu/drm/i915/display/intel_display.h | 3 +++ drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 287110e4e4351..704ca079980c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4318,6 +4318,22 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, return 0; } +int intel_display_min_pipe_bpp(void) +{ + return 6 * 3; +} + +int intel_display_max_pipe_bpp(struct intel_display *display) +{ + if (display->platform.g4x || display->platform.valleyview || + display->platform.cherryview) + return 10*3; + else if (DISPLAY_VER(display) >= 5) + return 12*3; + else + return 8*3; +} + static int compute_baseline_pipe_bpp(struct intel_atomic_state *state, struct intel_crtc *crtc) @@ -4327,17 +4343,9 @@ compute_baseline_pipe_bpp(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct drm_connector *connector; struct drm_connector_state *connector_state; - int bpp, i; - - if (display->platform.g4x || display->platform.valleyview || - display->platform.cherryview) - bpp = 10*3; - else if (DISPLAY_VER(display) >= 5) - bpp = 12*3; - else - bpp = 8*3; + int i; - crtc_state->pipe_bpp = bpp; + crtc_state->pipe_bpp = intel_display_max_pipe_bpp(display); /* Clamp display bpp to connector max bpp */ for_each_new_connector_in_state(&state->base, connector, connector_state, i) { diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 3b54a62c290af..b6610e9175a7a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -524,6 +524,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state); bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, struct intel_crtc *crtc); +int intel_display_min_pipe_bpp(void); +int intel_display_max_pipe_bpp(struct intel_display *display); + /* modesetting */ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, const char *reason, u8 pipe_mask); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cdbdf20a46b7d..eb3898a49d1ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1199,7 +1199,7 @@ intel_dp_output_format(struct intel_connector *connector, int intel_dp_min_bpp(enum intel_output_format output_format) { if (output_format == INTEL_OUTPUT_FORMAT_RGB) - return 6 * 3; + return intel_display_min_pipe_bpp(); else return 8 * 3; } -- GitLab From 67e12c64b49f5a2b5a2db50d84f69b16f6d6d42e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:37 +0300 Subject: [PATCH 016/902] drm/i915/dp: Export intel_dp_dsc_min_src_compressed_bpp() Export the function that can be used by a follow-up change to query the minimum compressed link bpp supported by the HW. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-11-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index eb3898a49d1ca..3021395dead2d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2071,7 +2071,7 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector pipe_config, bpc) >> 4; } -static int dsc_src_min_compressed_bpp(void) +int intel_dp_dsc_min_src_compressed_bpp(void) { /* Min Compressed bpp supported by source is 8 */ return 8; @@ -2482,7 +2482,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp; int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp; - dsc_src_min_bpp = dsc_src_min_compressed_bpp(); + dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp(); dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state); dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp); limits->link.min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 2fe6720a88fc1..0b8a9b939070f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -208,6 +208,7 @@ bool intel_dp_has_connector(struct intel_dp *intel_dp, const struct drm_connector_state *conn_state); int intel_dp_dsc_max_src_input_bpc(struct intel_display *display); int intel_dp_dsc_min_src_input_bpc(void); +int intel_dp_dsc_min_src_compressed_bpp(void); int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); -- GitLab From f7f46a80fa68c19260aa6c88881cee4a18682562 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:38 +0300 Subject: [PATCH 017/902] drm/i915: Add support for forcing the link bpp on a connector Add support for forcing the link bpp on a connector via a connector debugfs entry. During reducing link bpps due to a link BW limit, keep bpps close to their forced value. Add the debugfs entry to all relevant connectors: all DP connectors and on an FDI link CRT/SDVO/LVDS/HDMI connectors. v2: - Move adding the debugfs entries to this patch. - Rename i915_force_link_bpp to intel_force_link_bpp. (Jani) - Select the relevant connectors via platform checks. (Jani) - Use for_each_new_intel_connector_in_state(). (Jani) - Fix 64 bit division vs. 32 bit build when converting str to q4. (lkp) - Avoid division and addition overflow when converting str to q4. v3: - Add TODO: to make the non-DSC min bpp value connector specific. (Ankit) Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-12-imre.deak@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 2 + .../drm/i915/display/intel_display_device.h | 1 + .../drm/i915/display/intel_display_types.h | 4 + drivers/gpu/drm/i915/display/intel_link_bw.c | 239 +++++++++++++++++- drivers/gpu/drm/i915/display/intel_link_bw.h | 2 + 5 files changed, 241 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 8d0a1779dd193..a9b1ec4cf0f75 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -39,6 +39,7 @@ #include "intel_hdcp.h" #include "intel_hdmi.h" #include "intel_hotplug.h" +#include "intel_link_bw.h" #include "intel_panel.h" #include "intel_pps.h" #include "intel_psr.h" @@ -1325,6 +1326,7 @@ void intel_connector_debugfs_add(struct intel_connector *connector) intel_psr_connector_debugfs_add(connector); intel_alpm_lobf_debugfs_add(connector); intel_dp_link_training_debugfs_add(connector); + intel_link_bw_connector_debugfs_add(connector); if (DISPLAY_VER(display) >= 11 && ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst.dp) || diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 87c666792c0da..fe14a92ae8c65 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -172,6 +172,7 @@ struct intel_display_platforms { #define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake) #define HAS_GMBUS_IRQ(__display) (DISPLAY_VER(__display) >= 4) #define HAS_GMCH(__display) (DISPLAY_INFO(__display)->has_gmch) +#define HAS_FDI(__display) (IS_DISPLAY_VER((__display), 5, 8) && !HAS_GMCH(__display)) #define HAS_HOTPLUG(__display) (DISPLAY_INFO(__display)->has_hotplug) #define HAS_HW_SAGV_WM(__display) (DISPLAY_VER(__display) >= 13 && !(__display)->platform.dgfx) #define HAS_IPC(__display) (DISPLAY_INFO(__display)->has_ipc) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index d6d0440dcee9b..056219272c36e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -550,6 +550,10 @@ struct intel_connector { struct intel_dp *dp; } mst; + struct { + int force_bpp_x16; + } link; + /* Work struct to schedule a uevent on link train failure */ struct work_struct modeset_retry_work; diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c index a10cd39926075..3caef7f9c7c47 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.c +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -3,6 +3,11 @@ * Copyright © 2023 Intel Corporation */ +#include +#include +#include +#include + #include #include @@ -10,11 +15,33 @@ #include "intel_crtc.h" #include "intel_display_core.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_mst.h" #include "intel_dp_tunnel.h" #include "intel_fdi.h" #include "intel_link_bw.h" +static int get_forced_link_bpp_x16(struct intel_atomic_state *state, + const struct intel_crtc *crtc) +{ + struct intel_digital_connector_state *conn_state; + struct intel_connector *connector; + int force_bpp_x16 = INT_MAX; + int i; + + for_each_new_intel_connector_in_state(state, connector, conn_state, i) { + if (conn_state->base.crtc != &crtc->base) + continue; + + if (!connector->link.force_bpp_x16) + continue; + + force_bpp_x16 = min(force_bpp_x16, connector->link.force_bpp_x16); + } + + return force_bpp_x16 < INT_MAX ? force_bpp_x16 : 0; +} + /** * intel_link_bw_init_limits - initialize BW limits * @state: Atomic state @@ -31,9 +58,10 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, limits->force_fec_pipes = 0; limits->bpp_limit_reached_pipes = 0; for_each_pipe(display, pipe) { + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); const struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, - intel_crtc_for_pipe(display, pipe)); + intel_atomic_get_new_crtc_state(state, crtc); + int forced_bpp_x16 = get_forced_link_bpp_x16(state, crtc); if (state->base.duplicated && crtc_state) { limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16; @@ -42,15 +70,19 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, } else { limits->max_bpp_x16[pipe] = INT_MAX; } + + if (forced_bpp_x16) + limits->max_bpp_x16[pipe] = min(limits->max_bpp_x16[pipe], forced_bpp_x16); } } /** - * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe + * __intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe * @state: atomic state * @limits: link BW limits * @pipe_mask: mask of pipes to select from * @reason: explanation of why bpp reduction is needed + * @reduce_forced_bpp: allow reducing bpps below their forced link bpp * * Select the pipe from @pipe_mask with the biggest link bpp value and set the * maximum of link bpp in @limits below this value. Modeset the selected pipe, @@ -64,10 +96,11 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, * - %-ENOSPC if no pipe can further reduce its link bpp * - Other negative error, if modesetting the selected pipe failed */ -int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, - struct intel_link_bw_limits *limits, - u8 pipe_mask, - const char *reason) +static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits, + u8 pipe_mask, + const char *reason, + bool reduce_forced_bpp) { struct intel_display *display = to_intel_display(state); enum pipe max_bpp_pipe = INVALID_PIPE; @@ -97,6 +130,10 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, */ link_bpp_x16 = fxp_q4_from_int(crtc_state->pipe_bpp); + if (!reduce_forced_bpp && + link_bpp_x16 <= get_forced_link_bpp_x16(state, crtc)) + continue; + if (link_bpp_x16 > max_bpp_x16) { max_bpp_x16 = link_bpp_x16; max_bpp_pipe = crtc->pipe; @@ -112,6 +149,21 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, BIT(max_bpp_pipe)); } +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits, + u8 pipe_mask, + const char *reason) +{ + int ret; + + /* Try to keep any forced link BPP. */ + ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, false); + if (ret == -ENOSPC) + ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, true); + + return ret; +} + /** * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum * @state: atomic state @@ -245,3 +297,176 @@ int intel_link_bw_atomic_check(struct intel_atomic_state *state, return -EAGAIN; } + +static int force_link_bpp_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + + seq_printf(m, FXP_Q4_FMT "\n", FXP_Q4_ARGS(connector->link.force_bpp_x16)); + + return 0; +} + +static int str_to_fxp_q4_nonneg_int(const char *str, int *val_x16) +{ + unsigned int val; + int err; + + err = kstrtouint(str, 10, &val); + if (err) + return err; + + if (val > INT_MAX >> 4) + return -ERANGE; + + *val_x16 = fxp_q4_from_int(val); + + return 0; +} + +/* modifies str */ +static int str_to_fxp_q4_nonneg(char *str, int *val_x16) +{ + const char *int_str; + char *frac_str; + int frac_digits; + int frac_val; + int err; + + int_str = strim(str); + frac_str = strchr(int_str, '.'); + + if (frac_str) + *frac_str++ = '\0'; + + err = str_to_fxp_q4_nonneg_int(int_str, val_x16); + if (err) + return err; + + if (!frac_str) + return 0; + + /* prevent negative number/leading +- sign mark */ + if (!isdigit(*frac_str)) + return -EINVAL; + + err = str_to_fxp_q4_nonneg_int(frac_str, &frac_val); + if (err) + return err; + + frac_digits = strlen(frac_str); + if (frac_digits > intlog10(INT_MAX) >> 24 || + frac_val > INT_MAX - int_pow(10, frac_digits) / 2) + return -ERANGE; + + frac_val = DIV_ROUND_CLOSEST(frac_val, (int)int_pow(10, frac_digits)); + + if (*val_x16 > INT_MAX - frac_val) + return -ERANGE; + + *val_x16 += frac_val; + + return 0; +} + +static int user_str_to_fxp_q4_nonneg(const char __user *ubuf, size_t len, int *val_x16) +{ + char *kbuf; + int err; + + kbuf = memdup_user_nul(ubuf, len); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + + err = str_to_fxp_q4_nonneg(kbuf, val_x16); + + kfree(kbuf); + + return err; +} + +static bool connector_supports_dsc(struct intel_connector *connector) +{ + struct intel_display *display = to_intel_display(connector); + + switch (connector->base.connector_type) { + case DRM_MODE_CONNECTOR_eDP: + return intel_dp_has_dsc(connector); + case DRM_MODE_CONNECTOR_DisplayPort: + if (connector->mst.dp) + return HAS_DSC_MST(display); + + return HAS_DSC(display); + default: + return false; + } +} + +static ssize_t +force_link_bpp_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct intel_connector *connector = m->private; + struct intel_display *display = to_intel_display(connector); + int min_bpp; + int bpp_x16; + int err; + + err = user_str_to_fxp_q4_nonneg(ubuf, len, &bpp_x16); + if (err) + return err; + + /* TODO: Make the non-DSC min_bpp value connector specific. */ + if (connector_supports_dsc(connector)) + min_bpp = intel_dp_dsc_min_src_compressed_bpp(); + else + min_bpp = intel_display_min_pipe_bpp(); + + if (bpp_x16 && + (bpp_x16 < fxp_q4_from_int(min_bpp) || + bpp_x16 > fxp_q4_from_int(intel_display_max_pipe_bpp(display)))) + return -EINVAL; + + err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex); + if (err) + return err; + + connector->link.force_bpp_x16 = bpp_x16; + + drm_modeset_unlock(&display->drm->mode_config.connection_mutex); + + *offp += len; + + return len; +} +DEFINE_SHOW_STORE_ATTRIBUTE(force_link_bpp); + +void intel_link_bw_connector_debugfs_add(struct intel_connector *connector) +{ + struct intel_display *display = to_intel_display(connector); + struct dentry *root = connector->base.debugfs_entry; + + switch (connector->base.connector_type) { + case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_eDP: + break; + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_DVID: + if (HAS_FDI(display)) + break; + + return; + case DRM_MODE_CONNECTOR_HDMIA: + if (HAS_FDI(display) && !HAS_DDI(display)) + break; + + return; + default: + return; + } + + debugfs_create_file("intel_force_link_bpp", 0644, root, + connector, &force_link_bpp_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h index e69049cf178f6..b499042e62b13 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.h +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h @@ -11,6 +11,7 @@ #include "intel_display_limits.h" struct intel_atomic_state; +struct intel_connector; struct intel_crtc_state; struct intel_link_bw_limits { @@ -32,5 +33,6 @@ bool intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state, enum pipe pipe); int intel_link_bw_atomic_check(struct intel_atomic_state *state, struct intel_link_bw_limits *new_limits); +void intel_link_bw_connector_debugfs_add(struct intel_connector *connector); #endif -- GitLab From f77d8675c1adfb7bad559c1183161db5e39e4a4d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:39 +0300 Subject: [PATCH 018/902] drm/i915/dp_mst: Enable fractional link bpps on MST if the bpp is forced Enable using a fractional (compressed) link bpp on MST links, if this is supported and the link bpp is forced. Fractional link bpps will be enabled by default as a follow-up change after testing this functionality within a set of commonly used MST monitors and docks/hubs which support it. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-13-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++++- drivers/gpu/drm/i915/display/intel_dp.h | 2 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3021395dead2d..91a34d474463a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2103,7 +2103,7 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp) /* * Note: for pre-13 display you still need to check the validity of each step. */ -static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) +int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); @@ -2111,6 +2111,10 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) if (DISPLAY_VER(display) < 14 || !incr) return fxp_q4_from_int(1); + if (connector->mst.dp && + !connector->link.force_bpp_x16 && !connector->mst.dp->force_dsc_fractional_bpp_en) + return fxp_q4_from_int(1); + /* fxp q4 */ return fxp_q4_from_int(1) / incr; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 0b8a9b939070f..eff3414c05dbf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -212,4 +212,6 @@ int intel_dp_dsc_min_src_compressed_bpp(void); int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); +int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 13b2bd3ec8607..57602606acd5a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -499,7 +499,7 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, "DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16)); - bpp_step_x16 = fxp_q4_from_int(1); + bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16); -- GitLab From dd39212b5f43577bcd0c4493c0ae4c7828bb55e1 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:15 +0200 Subject: [PATCH 019/902] drm/xe/vf: Divide GGTT ballooning into allocation and insertion The balloon nodes, which are used to fill areas of GGTT inaccessible for a specific VF, were allocated and inserted into GGTT within one function. To be able to re-use that insertion code during VF migration recovery, we need to split it. This patch separates allocation (init/fini functs) from the insertion of balloons (balloon/deballoon functs). Locks are also moved to ensure calls from post-migration recovery worker will not cause a deadlock. v2: Moved declarations to proper header v3: Rephrased description, introduced "_locked" versions of some functs, more lockdep checks, some functions renamed, altered error handling, added missing kerneldocs. v4: Suffixed more functs with `_locked`, moved lockdep asserts, fixed finalization in error path, added asserts v5: Renamed another few functs, used xe_ggtt_node_allocated(), moved lockdep back again to avoid null dereference, added asserts, improved comments v6: Changed params of cleanup_ggtt() Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-2-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_ggtt.c | 35 ++++----- drivers/gpu/drm/xe/xe_ggtt.h | 6 +- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 114 +++++++++++++++++++++------- drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 2 + 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 7062115909f2d..5a37233f24205 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -429,16 +429,17 @@ static void xe_ggtt_dump_node(struct xe_ggtt *ggtt, } /** - * xe_ggtt_node_insert_balloon - prevent allocation of specified GGTT addresses + * xe_ggtt_node_insert_balloon_locked - prevent allocation of specified GGTT addresses * @node: the &xe_ggtt_node to hold reserved GGTT node * @start: the starting GGTT address of the reserved region * @end: then end GGTT address of the reserved region * - * Use xe_ggtt_node_remove_balloon() to release a reserved GGTT node. + * To be used in cases where ggtt->lock is already taken. + * Use xe_ggtt_node_remove_balloon_locked() to release a reserved GGTT node. * * Return: 0 on success or a negative error code on failure. */ -int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) +int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 end) { struct xe_ggtt *ggtt = node->ggtt; int err; @@ -447,14 +448,13 @@ int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) xe_tile_assert(ggtt->tile, IS_ALIGNED(start, XE_PAGE_SIZE)); xe_tile_assert(ggtt->tile, IS_ALIGNED(end, XE_PAGE_SIZE)); xe_tile_assert(ggtt->tile, !drm_mm_node_allocated(&node->base)); + lockdep_assert_held(&ggtt->lock); node->base.color = 0; node->base.start = start; node->base.size = end - start; - mutex_lock(&ggtt->lock); err = drm_mm_reserve_node(&ggtt->mm, &node->base); - mutex_unlock(&ggtt->lock); if (xe_gt_WARN(ggtt->tile->primary_gt, err, "Failed to balloon GGTT %#llx-%#llx (%pe)\n", @@ -466,27 +466,22 @@ int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) } /** - * xe_ggtt_node_remove_balloon - release a reserved GGTT region + * xe_ggtt_node_remove_balloon_locked - release a reserved GGTT region * @node: the &xe_ggtt_node with reserved GGTT region * - * See xe_ggtt_node_insert_balloon() for details. + * To be used in cases where ggtt->lock is already taken. + * See xe_ggtt_node_insert_balloon_locked() for details. */ -void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node) +void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) { - if (!node || !node->ggtt) + if (!xe_ggtt_node_allocated(node)) return; - if (!drm_mm_node_allocated(&node->base)) - goto free_node; + lockdep_assert_held(&node->ggtt->lock); xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon"); - mutex_lock(&node->ggtt->lock); drm_mm_remove_node(&node->base); - mutex_unlock(&node->ggtt->lock); - -free_node: - xe_ggtt_node_fini(node); } /** @@ -537,12 +532,12 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align) * xe_ggtt_node_init - Initialize %xe_ggtt_node struct * @ggtt: the &xe_ggtt where the new node will later be inserted/reserved. * - * This function will allocated the struct %xe_ggtt_node and return it's pointer. + * This function will allocate the struct %xe_ggtt_node and return its pointer. * This struct will then be freed after the node removal upon xe_ggtt_node_remove() - * or xe_ggtt_node_remove_balloon(). + * or xe_ggtt_node_remove_balloon_locked(). * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated * in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), - * xe_ggtt_node_insert_balloon() will ensure the node is inserted or reserved in GGTT. + * xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT. * * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. **/ @@ -564,7 +559,7 @@ struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt) * @node: the &xe_ggtt_node to be freed * * If anything went wrong with either xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), - * or xe_ggtt_node_insert_balloon(); and this @node is not going to be reused, then, + * or xe_ggtt_node_insert_balloon_locked(); and this @node is not going to be reused, then, * this function needs to be called to free the %xe_ggtt_node struct **/ void xe_ggtt_node_fini(struct xe_ggtt_node *node) diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 27e7d67de0047..d468af96b465e 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -15,9 +15,9 @@ int xe_ggtt_init(struct xe_ggtt *ggtt); struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt); void xe_ggtt_node_fini(struct xe_ggtt_node *node); -int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, - u64 start, u64 size); -void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node); +int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, + u64 start, u64 size); +void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index a439261bf4d72..f82ddff79b3b9 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -560,35 +560,43 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) return gt->sriov.vf.self_config.lmem_size; } -static struct xe_ggtt_node * -vf_balloon_ggtt_node(struct xe_ggtt *ggtt, u64 start, u64 end) +static int vf_init_ggtt_balloons(struct xe_gt *gt) { - struct xe_ggtt_node *node; - int err; + struct xe_tile *tile = gt_to_tile(gt); + struct xe_ggtt *ggtt = tile->mem.ggtt; - node = xe_ggtt_node_init(ggtt); - if (IS_ERR(node)) - return node; + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - err = xe_ggtt_node_insert_balloon(node, start, end); - if (err) { - xe_ggtt_node_fini(node); - return ERR_PTR(err); + tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) + return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); + + tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); + return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); } - return node; + return 0; } -static int vf_balloon_ggtt(struct xe_gt *gt) +/** + * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range. + * @gt: the &xe_gt struct instance + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt) { struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; struct xe_tile *tile = gt_to_tile(gt); - struct xe_ggtt *ggtt = tile->mem.ggtt; struct xe_device *xe = gt_to_xe(gt); u64 start, end; + int err; xe_gt_assert(gt, IS_SRIOV_VF(xe)); xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + lockdep_assert_held(&tile->mem.ggtt->lock); if (!config->ggtt_size) return -ENODATA; @@ -611,31 +619,77 @@ static int vf_balloon_ggtt(struct xe_gt *gt) start = xe_wopcm_size(xe); end = config->ggtt_base; if (end != start) { - tile->sriov.vf.ggtt_balloon[0] = vf_balloon_ggtt_node(ggtt, start, end); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) - return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], + start, end); + if (err) + return err; } start = config->ggtt_base + config->ggtt_size; end = GUC_GGTT_TOP; if (end != start) { - tile->sriov.vf.ggtt_balloon[1] = vf_balloon_ggtt_node(ggtt, start, end); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); - return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1], + start, end); + if (err) { + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); + return err; } } return 0; } -static void deballoon_ggtt(struct drm_device *drm, void *arg) +static int vf_balloon_ggtt(struct xe_gt *gt) +{ + struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt; + int err; + + mutex_lock(&ggtt->lock); + err = xe_gt_sriov_vf_balloon_ggtt_locked(gt); + mutex_unlock(&ggtt->lock); + + return err; +} + +/** + * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. + * @gt: the &xe_gt struct instance + */ +void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt) { - struct xe_tile *tile = arg; + struct xe_tile *tile = gt_to_tile(gt); xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[1]); - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); +} + +static void vf_deballoon_ggtt(struct xe_gt *gt) +{ + struct xe_tile *tile = gt_to_tile(gt); + + mutex_lock(&tile->mem.ggtt->lock); + xe_gt_sriov_vf_deballoon_ggtt_locked(gt); + mutex_unlock(&tile->mem.ggtt->lock); +} + +static void vf_fini_ggtt_balloons(struct xe_gt *gt) +{ + struct xe_tile *tile = gt_to_tile(gt); + + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); +} + +static void cleanup_ggtt(struct drm_device *drm, void *arg) +{ + struct xe_gt *gt = arg; + + vf_deballoon_ggtt(gt); + vf_fini_ggtt_balloons(gt); } /** @@ -655,11 +709,17 @@ int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt) if (xe_gt_is_media_type(gt)) return 0; - err = vf_balloon_ggtt(gt); + err = vf_init_ggtt_balloons(gt); if (err) return err; - return drmm_add_action_or_reset(&xe->drm, deballoon_ggtt, tile); + err = vf_balloon_ggtt(gt); + if (err) { + vf_fini_ggtt_balloons(gt); + return err; + } + + return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, gt); } static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index ba6c5d74e326f..d717deb8af914 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -18,6 +18,8 @@ int xe_gt_sriov_vf_query_config(struct xe_gt *gt); int xe_gt_sriov_vf_connect(struct xe_gt *gt); int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); +int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); +void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); -- GitLab From 3e693945b125da0f8459e84cee385cec77910c2f Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:16 +0200 Subject: [PATCH 020/902] drm/xe/vf: Shifting GGTT area post migration We have only one GGTT for all IOV functions, with each VF having assigned a range of addresses for its use. After migration, a VF can receive a different range of addresses than it had initially. This implements shifting GGTT addresses within drm_mm nodes, so that VMAs stay valid after migration. This will make the driver use new addresses when accessing GGTT from the moment the shifting ends. By taking the ggtt->lock for the period of VMA fixups, this change also adds constraint on that mutex. Any locks used during the recovery cannot ever wait for hardware response - because after migration, the hardware will not do anything until fixups are finished. v2: Moved some functs to xe_ggtt.c; moved shift computation to just after querying; improved documentation; switched some warns to asserts; skipping fixups when GGTT shift eq 0; iterating through tiles (Michal) v3: Updated kerneldocs, removed unused funct, properly allocate balloning nodes if non existent v4: Re-used ballooning functions from VF init, used bool in place of standard error codes v5: Renamed one function v6: Subject tag change, several kerneldocs updated, some functions renamed, some moved, added several asserts, shuffled declarations of variables, revealed more detail in high level functions v7: Fixed typos, added `_locked` suffix to some functs, improved readability of asserts, removed unneeded conditional v8: Moved one function, removed implementation detail from kerneldoc, added asserts v9: Code shuffling without much change, and one param rename v10: Minor error path change, added printing the shift via debugfs Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-3-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_ggtt.c | 50 +++++++++++ drivers/gpu/drm/xe/xe_ggtt.h | 1 + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 104 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 2 + drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h | 2 + drivers/gpu/drm/xe/xe_sriov_vf.c | 21 +++++ 6 files changed, 180 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 5a37233f24205..af8e53014b874 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -484,6 +484,56 @@ void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) drm_mm_remove_node(&node->base); } +static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size) +{ + struct xe_tile *tile = ggtt->tile; + struct xe_device *xe = tile_to_xe(tile); + u64 __maybe_unused wopcm = xe_wopcm_size(xe); + + xe_tile_assert(tile, start >= wopcm); + xe_tile_assert(tile, start + size < ggtt->size - wopcm); +} + +/** + * xe_ggtt_shift_nodes_locked - Shift GGTT nodes to adjust for a change in usable address range. + * @ggtt: the &xe_ggtt struct instance + * @shift: change to the location of area provisioned for current VF + * + * This function moves all nodes from the GGTT VM, to a temp list. These nodes are expected + * to represent allocations in range formerly assigned to current VF, before the range changed. + * When the GGTT VM is completely clear of any nodes, they are re-added with shifted offsets. + * + * The function has no ability of failing - because it shifts existing nodes, without + * any additional processing. If the nodes were successfully existing at the old address, + * they will do the same at the new one. A fail inside this function would indicate that + * the list of nodes was either already damaged, or that the shift brings the address range + * outside of valid bounds. Both cases justify an assert rather than error code. + */ +void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift) +{ + struct xe_tile *tile __maybe_unused = ggtt->tile; + struct drm_mm_node *node, *tmpn; + LIST_HEAD(temp_list_head); + + lockdep_assert_held(&ggtt->lock); + + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) + drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) + xe_ggtt_assert_fit(ggtt, node->start + shift, node->size); + + drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) { + drm_mm_remove_node(node); + list_add(&node->node_list, &temp_list_head); + } + + list_for_each_entry_safe(node, tmpn, &temp_list_head, node_list) { + list_del(&node->node_list); + node->start += shift; + drm_mm_reserve_node(&ggtt->mm, node); + xe_tile_assert(tile, drm_mm_node_allocated(node)); + } +} + /** * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT * @node: the &xe_ggtt_node to be inserted diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index d468af96b465e..4337a279ff3b0 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -18,6 +18,7 @@ void xe_ggtt_node_fini(struct xe_ggtt_node *node); int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 size); void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); +void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift); int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index f82ddff79b3b9..4ff7ae1a5f16c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -415,6 +415,7 @@ static int vf_get_ggtt_info(struct xe_gt *gt) xe_gt_sriov_dbg_verbose(gt, "GGTT %#llx-%#llx = %lluK\n", start, start + size - 1, size / SZ_1K); + config->ggtt_shift = start - (s64)config->ggtt_base; config->ggtt_base = start; config->ggtt_size = size; @@ -560,6 +561,24 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) return gt->sriov.vf.self_config.lmem_size; } +/** + * xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration + * @gt: the &xe_gt struct instance + * + * This function is for VF use only. + * + * Return: The shift value; could be negative + */ +s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) +{ + struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; + + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + return config->ggtt_shift; +} + static int vf_init_ggtt_balloons(struct xe_gt *gt) { struct xe_tile *tile = gt_to_tile(gt); @@ -817,6 +836,89 @@ failed: return err; } +/** + * DOC: GGTT nodes shifting during VF post-migration recovery + * + * The first fixup applied to the VF KMD structures as part of post-migration + * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved + * from range previously assigned to this VF, into newly provisioned area. + * The changes include balloons, which are resized accordingly. + * + * The balloon nodes are there to eliminate unavailable ranges from use: one + * reserves the GGTT area below the range for current VF, and another one + * reserves area above. + * + * Below is a GGTT layout of example VF, with a certain address range assigned to + * said VF, and inaccessible areas above and below: + * + * 0 4GiB + * |<--------------------------- Total GGTT size ----------------------------->| + * WOPCM GUC_TOP + * |<-------------- Area mappable by xe_ggtt instance ---------------->| + * + * +---+---------------------------------+----------+----------------------+---+ + * |\\\|/////////////////////////////////| VF mem |//////////////////////|\\\| + * +---+---------------------------------+----------+----------------------+---+ + * + * Hardware enforced access rules before migration: + * + * |<------- inaccessible for VF ------->||<-- inaccessible for VF ->| + * + * GGTT nodes used for tracking allocations: + * + * |<---------- balloon ------------>|<- nodes->|<----- balloon ------>| + * + * After the migration, GGTT area assigned to the VF might have shifted, either + * to lower or to higher address. But we expect the total size and extra areas to + * be identical, as migration can only happen between matching platforms. + * Below is an example of GGTT layout of the VF after migration. Content of the + * GGTT for VF has been moved to a new area, and we receive its address from GuC: + * + * +---+----------------------+----------+---------------------------------+---+ + * |\\\|//////////////////////| VF mem |/////////////////////////////////|\\\| + * +---+----------------------+----------+---------------------------------+---+ + * + * Hardware enforced access rules after migration: + * + * |<- inaccessible for VF -->||<------- inaccessible for VF ------->| + * + * So the VF has a new slice of GGTT assigned, and during migration process, the + * memory content was copied to that new area. But the &xe_ggtt nodes are still + * tracking allocations using the old addresses. The nodes within VF owned area + * have to be shifted, and balloon nodes need to be resized to properly mask out + * areas not owned by the VF. + * + * Fixed &xe_ggtt nodes used for tracking allocations: + * + * |<------ balloon ------>|<- nodes->|<----------- balloon ----------->| + * + * Due to use of GPU profiles, we do not expect the old and new GGTT ares to + * overlap; but our node shifting will fix addresses properly regardless. + */ + +/** + * xe_gt_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range. + * @gt: the &xe_gt struct instance + * @shift: the shift value + * + * Since Global GTT is not virtualized, each VF has an assigned range + * within the global space. This range might have changed during migration, + * which requires all memory addresses pointing to GGTT to be shifted. + */ +void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift) +{ + struct xe_tile *tile = gt_to_tile(gt); + struct xe_ggtt *ggtt = tile->mem.ggtt; + + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + mutex_lock(&ggtt->lock); + xe_gt_sriov_vf_deballoon_ggtt_locked(gt); + xe_ggtt_shift_nodes_locked(ggtt, shift); + xe_gt_sriov_vf_balloon_ggtt_locked(gt); + mutex_unlock(&ggtt->lock); +} + /** * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery, * or just mark that a GuC is ready for it. @@ -1103,6 +1205,8 @@ void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) string_get_size(config->ggtt_size, 1, STRING_UNITS_2, buf, sizeof(buf)); drm_printf(p, "GGTT size:\t%llu (%s)\n", config->ggtt_size, buf); + drm_printf(p, "GGTT shift on last restore:\t%lld\n", config->ggtt_shift); + if (IS_DGFX(xe) && !xe_gt_is_media_type(gt)) { string_get_size(config->lmem_size, 1, STRING_UNITS_2, buf, sizeof(buf)); drm_printf(p, "LMEM size:\t%llu (%s)\n", config->lmem_size, buf); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index d717deb8af914..9db41afddd5a8 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -20,6 +20,8 @@ int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); +s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt); +void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h index a57f13b5afcd0..5ccbdf8d08b64 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h @@ -40,6 +40,8 @@ struct xe_gt_sriov_vf_selfconfig { u64 ggtt_base; /** @ggtt_size: assigned size of the GGTT region. */ u64 ggtt_size; + /** @ggtt_shift: difference in ggtt_base on last migration */ + s64 ggtt_shift; /** @lmem_size: assigned size of the LMEM. */ u64 lmem_size; /** @num_ctxs: assigned number of GuC submission context IDs. */ diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index c1275e64aa9c6..d48ea70d0f624 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -7,6 +7,7 @@ #include "xe_assert.h" #include "xe_device.h" +#include "xe_gt.h" #include "xe_gt_sriov_printk.h" #include "xe_gt_sriov_vf.h" #include "xe_pm.h" @@ -170,6 +171,25 @@ static bool vf_post_migration_imminent(struct xe_device *xe) work_pending(&xe->sriov.vf.migration.worker); } +static bool vf_post_migration_fixup_ggtt_nodes(struct xe_device *xe) +{ + bool need_fixups = false; + struct xe_tile *tile; + unsigned int id; + + for_each_tile(tile, xe, id) { + struct xe_gt *gt = tile->primary_gt; + s64 shift; + + shift = xe_gt_sriov_vf_ggtt_shift(gt); + if (shift) { + need_fixups = true; + xe_gt_sriov_vf_fixup_ggtt_nodes(gt, shift); + } + } + return need_fixups; +} + /* * Notify all GuCs about resource fixups apply finished. */ @@ -201,6 +221,7 @@ static void vf_post_migration_recovery(struct xe_device *xe) if (unlikely(err)) goto fail; + vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ vf_post_migration_notify_resfix_done(xe); xe_pm_runtime_put(xe); -- GitLab From e327592cc901a3e415e28e1b6aa26381a2a93582 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:17 +0200 Subject: [PATCH 021/902] drm/xe/guc: Introduce enum with offsets for context register H2Gs Some GuC messages are constructed with incrementing dword counter rather than referencing specific DWORDs, as described in GuC interface specification. This change introduces the definitions of DWORD numbers for parameters which will need to be referenced in a CTB parser to be added in a following patch. To ensure correctness of these DWORDs, verification in form of asserts was added to the message construction code. v2: Renamed enum members, added ones for single context registration, modified asserts to check values rather than indexes. v3: Reordered assert args to take less lines v4: Added lengths v5: Renamed MULTI_LRC_MSG_LEN to MULTI_LRC_MSG_MIN_LEN Suggested-by: Michal Wajdeczko Signed-off-by: Tomasz Lis Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-4-tomasz.lis@intel.com --- drivers/gpu/drm/xe/abi/guc_actions_abi.h | 31 ++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_submit.c | 17 +++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h index 448afb86e05c7..ff4f412c28d8c 100644 --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h @@ -161,6 +161,37 @@ enum xe_guc_preempt_options { XE_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8, }; +enum xe_guc_register_context_param_offsets { + XE_GUC_REGISTER_CONTEXT_DATA_0_MBZ = 0, + XE_GUC_REGISTER_CONTEXT_DATA_1_FLAGS, + XE_GUC_REGISTER_CONTEXT_DATA_2_CONTEXT_INDEX, + XE_GUC_REGISTER_CONTEXT_DATA_3_ENGINE_CLASS, + XE_GUC_REGISTER_CONTEXT_DATA_4_ENGINE_SUBMIT_MASK, + XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER, + XE_GUC_REGISTER_CONTEXT_DATA_6_WQ_DESC_ADDR_UPPER, + XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER, + XE_GUC_REGISTER_CONTEXT_DATA_8_WQ_BUF_BASE_UPPER, + XE_GUC_REGISTER_CONTEXT_DATA_9_WQ_BUF_SIZE, + XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR, + XE_GUC_REGISTER_CONTEXT_MSG_LEN, +}; + +enum xe_guc_register_context_multi_lrc_param_offsets { + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_0_MBZ = 0, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_1_FLAGS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_2_PARENT_CONTEXT, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_3_ENGINE_CLASS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_4_ENGINE_SUBMIT_MASK, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_6_WQ_DESC_ADDR_UPPER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_8_WQ_BUF_BASE_UPPER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_9_WQ_BUF_SIZE, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN = 11, +}; + enum xe_guc_report_status { XE_GUC_REPORT_STATUS_UNKNOWN = 0x0, XE_GUC_REPORT_STATUS_ACKED = 0x1, diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 369be36f7dc5a..06e2998b0e214 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -487,6 +487,15 @@ static void __register_mlrc_exec_queue(struct xe_guc *guc, action[len++] = upper_32_bits(xe_lrc_descriptor(lrc)); } + /* explicitly checks some fields that we might fixup later */ + xe_gt_assert(guc_to_gt(guc), info->wq_desc_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->wq_base_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER]); + xe_gt_assert(guc_to_gt(guc), q->width == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS]); + xe_gt_assert(guc_to_gt(guc), info->hwlrca_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR]); xe_gt_assert(guc_to_gt(guc), len <= MAX_MLRC_REG_SIZE); #undef MAX_MLRC_REG_SIZE @@ -511,6 +520,14 @@ static void __register_exec_queue(struct xe_guc *guc, info->hwlrca_hi, }; + /* explicitly checks some fields that we might fixup later */ + xe_gt_assert(guc_to_gt(guc), info->wq_desc_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->wq_base_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->hwlrca_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR]); + xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); } -- GitLab From cef88d1265cac7d415606af73ba58926fd3cd8b7 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:18 +0200 Subject: [PATCH 022/902] drm/xe/vf: Fixup CTB send buffer messages after migration During post-migration recovery of a VF, it is necessary to update GGTT references included in messages which are going to be sent to GuC. GuC will start consuming messages after VF KMD will inform it about fixups being done; before that, the VF KMD is expected to update any H2G messages which are already in send buffer but were not consumed by GuC. Only a small subset of messages allowed for VFs have GGTT references in them. This patch adds the functionality to parse the CTB send ring buffer and shift addresses contained within. While fixing the CTB content, ct->lock is not taken. This means the only barrier taken remains GGTT address lock - which is ok, because only requests with GGTT addresses matter, but it also means tail changes can happen during the CTB fixups execution (which may be ignored as any new messages will not have anything to fix). The GGTT address locking will be introduced in a future series. v2: removed storing shift as that's now done in VMA nodes patch; macros to inlines; warns to asserts; log messages fixes (Michal) v3: removed inline keywords, enums for offsets in CTB messages, less error messages, if return unused then made functs void (Michal) v4: update the cached head before starting fixups v5: removed/updated comments, wrapped lines, converted assert into error, enums for offsets to separate patch, reused xe_map_rd v6: define xe_map_*_array() macros, support CTB wrap which divides a message, updated comments, moved one function to an earlier patch v7: renamed few functions, wider use on previously introduced helper, separate cases in parsing messges, documented a static funct v8: Introduced more helpers, fixed coding style mistakes v9: Move xe_map*() functs to macros, add asserts, add debug print v10: Errors in place of some asserts, style fixes v11: Fixed invalid conditionals, added debug-only local pointer v12: Removed redundant __maybe_unused Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-5-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_guc_ct.c | 183 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_ct.h | 2 + drivers/gpu/drm/xe/xe_map.h | 18 +++ drivers/gpu/drm/xe/xe_sriov_vf.c | 21 +++- 4 files changed, 223 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 2447de0ebedf4..ff6edf1b14f49 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -25,6 +25,7 @@ #include "xe_gt_printk.h" #include "xe_gt_sriov_pf_control.h" #include "xe_gt_sriov_pf_monitor.h" +#include "xe_gt_sriov_printk.h" #include "xe_gt_tlb_invalidation.h" #include "xe_guc.h" #include "xe_guc_log.h" @@ -84,6 +85,8 @@ struct g2h_fence { bool done; }; +#define make_u64(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo))) + static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer) { g2h_fence->response_buffer = response_buffer; @@ -1624,6 +1627,186 @@ static void g2h_worker_func(struct work_struct *w) receive_g2h(ct); } +static void xe_fixup_u64_in_cmds(struct xe_device *xe, struct iosys_map *cmds, + u32 size, u32 idx, s64 shift) +{ + u32 hi, lo; + u64 offset; + + lo = xe_map_rd_ring_u32(xe, cmds, idx, size); + hi = xe_map_rd_ring_u32(xe, cmds, idx + 1, size); + offset = make_u64(hi, lo); + offset += shift; + lo = lower_32_bits(offset); + hi = upper_32_bits(offset); + xe_map_wr_ring_u32(xe, cmds, idx, size, lo); + xe_map_wr_ring_u32(xe, cmds, idx + 1, size, hi); +} + +/* + * Shift any GGTT addresses within a single message left within CTB from + * before post-migration recovery. + * @ct: pointer to CT struct of the target GuC + * @cmds: iomap buffer containing CT messages + * @head: start of the target message within the buffer + * @len: length of the target message + * @size: size of the commands buffer + * @shift: the address shift to be added to each GGTT reference + * Return: true if the message was fixed or needed no fixups, false on failure + */ +static bool ct_fixup_ggtt_in_message(struct xe_guc_ct *ct, + struct iosys_map *cmds, u32 head, + u32 len, u32 size, s64 shift) +{ + struct xe_gt *gt = ct_to_gt(ct); + struct xe_device *xe = ct_to_xe(ct); + u32 msg[GUC_HXG_MSG_MIN_LEN]; + u32 action, i, n; + + xe_gt_assert(gt, len >= GUC_HXG_MSG_MIN_LEN); + + msg[0] = xe_map_rd_ring_u32(xe, cmds, head, size); + action = FIELD_GET(GUC_HXG_REQUEST_MSG_0_ACTION, msg[0]); + + xe_gt_sriov_dbg_verbose(gt, "fixing H2G %#x\n", action); + + switch (action) { + case XE_GUC_ACTION_REGISTER_CONTEXT: + if (len != XE_GUC_REGISTER_CONTEXT_MSG_LEN) + goto err_len; + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR, shift); + break; + case XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC: + if (len < XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN) + goto err_len; + n = xe_map_rd_ring_u32(xe, cmds, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS, size); + if (len != XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN + 2 * n) + goto err_len; + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER, + shift); + for (i = 0; i < n; i++) + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR + + 2 * i, shift); + break; + default: + break; + } + return true; + +err_len: + xe_gt_err(gt, "Skipped G2G %#x message fixups, unexpected length (%u)\n", action, len); + return false; +} + +/* + * Apply fixups to the next outgoing CT message within given CTB + * @ct: the &xe_guc_ct struct instance representing the target GuC + * @h2g: the &guc_ctb struct instance of the target buffer + * @shift: shift to be added to all GGTT addresses within the CTB + * @mhead: pointer to an integer storing message start position; the + * position is changed to next message before this function return + * @avail: size of the area available for parsing, that is length + * of all remaining messages stored within the CTB + * Return: size of the area available for parsing after one message + * has been parsed, that is length remaining from the updated mhead + */ +static int ct_fixup_ggtt_in_buffer(struct xe_guc_ct *ct, struct guc_ctb *h2g, + s64 shift, u32 *mhead, s32 avail) +{ + struct xe_gt *gt = ct_to_gt(ct); + struct xe_device *xe = ct_to_xe(ct); + u32 msg[GUC_HXG_MSG_MIN_LEN]; + u32 size = h2g->info.size; + u32 head = *mhead; + u32 len; + + xe_gt_assert(gt, avail >= (s32)GUC_CTB_MSG_MIN_LEN); + + /* Read header */ + msg[0] = xe_map_rd_ring_u32(xe, &h2g->cmds, head, size); + len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, msg[0]) + GUC_CTB_MSG_MIN_LEN; + + if (unlikely(len > (u32)avail)) { + xe_gt_err(gt, "H2G channel broken on read, avail=%d, len=%d, fixups skipped\n", + avail, len); + return 0; + } + + head = (head + GUC_CTB_MSG_MIN_LEN) % size; + if (!ct_fixup_ggtt_in_message(ct, &h2g->cmds, head, msg_len_to_hxg_len(len), size, shift)) + return 0; + *mhead = (head + msg_len_to_hxg_len(len)) % size; + + return avail - len; +} + +/** + * xe_guc_ct_fixup_messages_with_ggtt - Fixup any pending H2G CTB messages + * @ct: pointer to CT struct of the target GuC + * @ggtt_shift: shift to be added to all GGTT addresses within the CTB + * + * Messages in GuC to Host CTB are owned by GuC and any fixups in them + * are made by GuC. But content of the Host to GuC CTB is owned by the + * KMD, so fixups to GGTT references in any pending messages need to be + * applied here. + * This function updates GGTT offsets in payloads of pending H2G CTB + * messages (messages which were not consumed by GuC before the VF got + * paused). + */ +void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift) +{ + struct guc_ctb *h2g = &ct->ctbs.h2g; + struct xe_guc *guc = ct_to_guc(ct); + struct xe_gt *gt = guc_to_gt(guc); + u32 head, tail, size; + s32 avail; + + if (unlikely(h2g->info.broken)) + return; + + h2g->info.head = desc_read(ct_to_xe(ct), h2g, head); + head = h2g->info.head; + tail = READ_ONCE(h2g->info.tail); + size = h2g->info.size; + + if (unlikely(head > size)) + goto corrupted; + + if (unlikely(tail >= size)) + goto corrupted; + + avail = tail - head; + + /* beware of buffer wrap case */ + if (unlikely(avail < 0)) + avail += size; + xe_gt_dbg(gt, "available %d (%u:%u:%u)\n", avail, head, tail, size); + xe_gt_assert(gt, avail >= 0); + + while (avail > 0) + avail = ct_fixup_ggtt_in_buffer(ct, h2g, ggtt_shift, &head, avail); + + return; + +corrupted: + xe_gt_err(gt, "Corrupted H2G descriptor head=%u tail=%u size=%u, fixups not applied\n", + head, tail, size); + h2g->info.broken = true; +} + static struct xe_guc_ct_snapshot *guc_ct_snapshot_alloc(struct xe_guc_ct *ct, bool atomic, bool want_ctb) { diff --git a/drivers/gpu/drm/xe/xe_guc_ct.h b/drivers/gpu/drm/xe/xe_guc_ct.h index 82c4ae458dda3..5649bda828239 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.h +++ b/drivers/gpu/drm/xe/xe_guc_ct.h @@ -22,6 +22,8 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, struct drm_pr void xe_guc_ct_snapshot_free(struct xe_guc_ct_snapshot *snapshot); void xe_guc_ct_print(struct xe_guc_ct *ct, struct drm_printer *p, bool want_ctb); +void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift); + static inline bool xe_guc_ct_enabled(struct xe_guc_ct *ct) { return ct->state == XE_GUC_CT_STATE_ENABLED; diff --git a/drivers/gpu/drm/xe/xe_map.h b/drivers/gpu/drm/xe/xe_map.h index f62e0c8b67aba..8d67f6ba2d95b 100644 --- a/drivers/gpu/drm/xe/xe_map.h +++ b/drivers/gpu/drm/xe/xe_map.h @@ -78,6 +78,24 @@ static inline void xe_map_write32(struct xe_device *xe, struct iosys_map *map, iosys_map_wr(map__, offset__, type__, val__); \ }) +#define xe_map_rd_array(xe__, map__, index__, type__) \ + xe_map_rd(xe__, map__, (index__) * sizeof(type__), type__) + +#define xe_map_wr_array(xe__, map__, index__, type__, val__) \ + xe_map_wr(xe__, map__, (index__) * sizeof(type__), type__, val__) + +#define xe_map_rd_array_u32(xe__, map__, index__) \ + xe_map_rd_array(xe__, map__, index__, u32) + +#define xe_map_wr_array_u32(xe__, map__, index__, val__) \ + xe_map_wr_array(xe__, map__, index__, u32, val__) + +#define xe_map_rd_ring_u32(xe__, map__, index__, size__) \ + xe_map_rd_array_u32(xe__, map__, (index__) % (size__)) + +#define xe_map_wr_ring_u32(xe__, map__, index__, size__, val__) \ + xe_map_wr_array_u32(xe__, map__, (index__) % (size__), val__) + #define xe_map_rd_field(xe__, map__, struct_offset__, struct_type__, field__) ({ \ struct xe_device *__xe = xe__; \ xe_device_assert_mem_access(__xe); \ diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index d48ea70d0f624..2674fa948fda3 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -10,6 +10,7 @@ #include "xe_gt.h" #include "xe_gt_sriov_printk.h" #include "xe_gt_sriov_vf.h" +#include "xe_guc_ct.h" #include "xe_pm.h" #include "xe_sriov.h" #include "xe_sriov_printk.h" @@ -158,6 +159,20 @@ static int vf_post_migration_requery_guc(struct xe_device *xe) return ret; } +static void vf_post_migration_fixup_ctb(struct xe_device *xe) +{ + struct xe_gt *gt; + unsigned int id; + + xe_assert(xe, IS_SRIOV_VF(xe)); + + for_each_gt(gt, xe, id) { + s32 shift = xe_gt_sriov_vf_ggtt_shift(gt); + + xe_guc_ct_fixup_messages_with_ggtt(>->uc.guc.ct, shift); + } +} + /* * vf_post_migration_imminent - Check if post-restore recovery is coming. * @xe: the &xe_device struct instance @@ -211,6 +226,7 @@ skip: static void vf_post_migration_recovery(struct xe_device *xe) { + bool need_fixups; int err; drm_dbg(&xe->drm, "migration recovery in progress\n"); @@ -221,8 +237,11 @@ static void vf_post_migration_recovery(struct xe_device *xe) if (unlikely(err)) goto fail; - vf_post_migration_fixup_ggtt_nodes(xe); + need_fixups = vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ + if (need_fixups) + vf_post_migration_fixup_ctb(xe); + vf_post_migration_notify_resfix_done(xe); xe_pm_runtime_put(xe); drm_notice(&xe->drm, "migration recovery ended\n"); -- GitLab From e5c13e2c505b73a8667ef9a0fd5cbd4227e483e6 Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Mon, 12 May 2025 06:50:04 +0000 Subject: [PATCH 023/902] drm/xe/xe2hpg: Add Wa_22021007897 Add Wa_22021007897 for the Xe2_HPG (graphics version: 20.01) IP. It is a permanent workaround, and applicable on all the steppings. Reviewed-by: Gustavo Sousa Reviewed-by: Tejas Upadhyay Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250512065004.2576-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_wa.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index cbb9f7cbcfc0e..5cd5ab8529c5c 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -156,6 +156,7 @@ #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) +#define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12) #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) #define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 6f6563cc74306..67196baa42492 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -827,6 +827,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = { XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX)) }, + { XE_RTP_NAME("22021007897"), + XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), + XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) + }, /* Xe3_LPG */ { XE_RTP_NAME("14021490052"), -- GitLab From 8a9b978ebd47df9e0694c34748c2d6fa0c31eb4d Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Mon, 12 May 2025 06:54:55 -0700 Subject: [PATCH 024/902] drm/gpusvm: Introduce devmem_only flag for allocation This commit adds a new flag, devmem_only, to the drm_gpusvm structure. The purpose of this flag is to ensure that the get_pages function allocates memory exclusively from the device's memory. If the allocation from device memory fails, the function will return an -EFAULT error. Required for shared CPU and GPU atomics on certain devices. v3: - s/vram_only/devmem_only/ Fixes: 99624bdff867 ("drm/gpusvm: Add support for GPU Shared Virtual Memory") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Signed-off-by: Himal Prasad Ghimiray Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250512135500.1405019-2-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 5 +++++ include/drm/drm_gpusvm.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index de424e670995c..a58d03e6cac27 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1454,6 +1454,11 @@ map_pages: goto err_unmap; } + if (ctx->devmem_only) { + err = -EFAULT; + goto err_unmap; + } + addr = dma_map_page(gpusvm->drm->dev, page, 0, PAGE_SIZE << order, diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index df120b4d1f836..9fd25fc880a49 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -286,6 +286,7 @@ struct drm_gpusvm { * @in_notifier: entering from a MMU notifier * @read_only: operating on read-only memory * @devmem_possible: possible to use device memory + * @devmem_only: use only device memory * * Context that is DRM GPUSVM is operating in (i.e. user arguments). */ @@ -294,6 +295,7 @@ struct drm_gpusvm_ctx { unsigned int in_notifier :1; unsigned int read_only :1; unsigned int devmem_possible :1; + unsigned int devmem_only :1; }; int drm_gpusvm_init(struct drm_gpusvm *gpusvm, -- GitLab From a9ac0fa455b050d03e3032501368048fb284d318 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:56 -0700 Subject: [PATCH 025/902] drm/xe: Strict migration policy for atomic SVM faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mixing GPU and CPU atomics does not work unless a strict migration policy of GPU atomics must be device memory. Enforce a policy of must be in VRAM with a retry loop of 3 attempts, if retry loop fails abort fault. Removing always_migrate_to_vram modparam as we now have real migration policy. v2: - Only retry migration on atomics - Drop alway migrate modparam v3: - Only set vram_only on DGFX (Himal) - Bail on get_pages failure if vram_only and retry count exceeded (Himal) - s/vram_only/devmem_only - Update xe_svm_range_is_valid to accept devmem_only argument v4: - Fix logic bug get_pages failure v5: - Fix commit message (Himal) - Mention removing always_migrate_to_vram in commit message (Lucas) - Fix xe_svm_range_is_valid to check for devmem pages - Bail on devmem_only && !migrate_devmem (Thomas) v6: - Add READ_ONCE barriers for opportunistic checks (Thomas) - Pair READ_ONCE with WRITE_ONCE (Thomas) v7: - Adjust comments (Thomas) Fixes: 2f118c949160 ("drm/xe: Add SVM VRAM migration") Cc: stable@vger.kernel.org Signed-off-by: Himal Prasad Ghimiray Signed-off-by: Matthew Brost Acked-by: Himal Prasad Ghimiray Reviewed-by: Thomas Hellström Link: https://lore.kernel.org/r/20250512135500.1405019-3-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 23 +++++-- drivers/gpu/drm/xe/xe_module.c | 3 - drivers/gpu/drm/xe/xe_module.h | 1 - drivers/gpu/drm/xe/xe_pt.c | 14 ++++- drivers/gpu/drm/xe/xe_svm.c | 111 +++++++++++++++++++++++++-------- drivers/gpu/drm/xe/xe_svm.h | 5 -- include/drm/drm_gpusvm.h | 40 +++++++----- 7 files changed, 140 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index a58d03e6cac27..41f6616bcf76f 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1118,6 +1118,10 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, lockdep_assert_held(&gpusvm->notifier_lock); if (range->flags.has_dma_mapping) { + struct drm_gpusvm_range_flags flags = { + .__flags = range->flags.__flags, + }; + for (i = 0, j = 0; i < npages; j++) { struct drm_pagemap_device_addr *addr = &range->dma_addr[j]; @@ -1131,8 +1135,12 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, dev, *addr); i += 1 << addr->order; } - range->flags.has_devmem_pages = false; - range->flags.has_dma_mapping = false; + + /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ + flags.has_devmem_pages = false; + flags.has_dma_mapping = false; + WRITE_ONCE(range->flags.__flags, flags.__flags); + range->dpagemap = NULL; } } @@ -1334,6 +1342,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, int err = 0; struct dev_pagemap *pagemap; struct drm_pagemap *dpagemap; + struct drm_gpusvm_range_flags flags; retry: hmm_range.notifier_seq = mmu_interval_read_begin(notifier); @@ -1378,7 +1387,8 @@ map_pages: */ drm_gpusvm_notifier_lock(gpusvm); - if (range->flags.unmapped) { + flags.__flags = range->flags.__flags; + if (flags.unmapped) { drm_gpusvm_notifier_unlock(gpusvm); err = -EFAULT; goto err_free; @@ -1474,14 +1484,17 @@ map_pages: } i += 1 << order; num_dma_mapped = i; - range->flags.has_dma_mapping = true; + flags.has_dma_mapping = true; } if (zdd) { - range->flags.has_devmem_pages = true; + flags.has_devmem_pages = true; range->dpagemap = dpagemap; } + /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ + WRITE_ONCE(range->flags.__flags, flags.__flags); + drm_gpusvm_notifier_unlock(gpusvm); kvfree(pfns); set_seqno: diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c index 64bf466465449..e4742e27e2cd3 100644 --- a/drivers/gpu/drm/xe/xe_module.c +++ b/drivers/gpu/drm/xe/xe_module.c @@ -30,9 +30,6 @@ struct xe_modparam xe_modparam = { module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600); MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size(in MiB), must be power of 2"); -module_param_named(always_migrate_to_vram, xe_modparam.always_migrate_to_vram, bool, 0444); -MODULE_PARM_DESC(always_migrate_to_vram, "Always migrate to VRAM on GPU fault"); - module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444); MODULE_PARM_DESC(force_execlist, "Force Execlist submission"); diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h index 84339e509c80d..5a3bfea8b7b4c 100644 --- a/drivers/gpu/drm/xe/xe_module.h +++ b/drivers/gpu/drm/xe/xe_module.h @@ -12,7 +12,6 @@ struct xe_modparam { bool force_execlist; bool probe_display; - bool always_migrate_to_vram; u32 force_vram_bar_size; int guc_log_level; char *guc_firmware_path; diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index b42cf5d1b20c3..b04756a97cdcf 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -2270,11 +2270,19 @@ static void op_commit(struct xe_vm *vm, } case DRM_GPUVA_OP_DRIVER: { + /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ + if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { - op->map_range.range->tile_present |= BIT(tile->id); - op->map_range.range->tile_invalidated &= ~BIT(tile->id); + WRITE_ONCE(op->map_range.range->tile_present, + op->map_range.range->tile_present | + BIT(tile->id)); + WRITE_ONCE(op->map_range.range->tile_invalidated, + op->map_range.range->tile_invalidated & + ~BIT(tile->id)); } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { - op->unmap_range.range->tile_present &= ~BIT(tile->id); + WRITE_ONCE(op->unmap_range.range->tile_present, + op->unmap_range.range->tile_present & + ~BIT(tile->id)); } break; } diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d25f02c8d7fc7..d8e15259a8dfc 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -16,8 +16,17 @@ static bool xe_svm_range_in_vram(struct xe_svm_range *range) { - /* Not reliable without notifier lock */ - return range->base.flags.has_devmem_pages; + /* + * Advisory only check whether the range is currently backed by VRAM + * memory. + */ + + struct drm_gpusvm_range_flags flags = { + /* Pairs with WRITE_ONCE in drm_gpusvm.c */ + .__flags = READ_ONCE(range->base.flags.__flags), + }; + + return flags.has_devmem_pages; } static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range) @@ -650,9 +659,16 @@ void xe_svm_fini(struct xe_vm *vm) } static bool xe_svm_range_is_valid(struct xe_svm_range *range, - struct xe_tile *tile) + struct xe_tile *tile, + bool devmem_only) { - return (range->tile_present & ~range->tile_invalidated) & BIT(tile->id); + /* + * Advisory only check whether the range currently has a valid mapping, + * READ_ONCE pairs with WRITE_ONCE in xe_pt.c + */ + return ((READ_ONCE(range->tile_present) & + ~READ_ONCE(range->tile_invalidated)) & BIT(tile->id)) && + (!devmem_only || xe_svm_range_in_vram(range)); } #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) @@ -726,6 +742,36 @@ static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, } #endif +static bool supports_4K_migration(struct xe_device *xe) +{ + if (xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) + return false; + + return true; +} + +static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, + struct xe_vma *vma) +{ + struct xe_vm *vm = range_to_vm(&range->base); + u64 range_size = xe_svm_range_size(range); + + if (!range->base.flags.migrate_devmem) + return false; + + if (xe_svm_range_in_vram(range)) { + drm_dbg(&vm->xe->drm, "Range is already in VRAM\n"); + return false; + } + + if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); + return false; + } + + return true; +} + /** * xe_svm_handle_pagefault() - SVM handle page fault * @vm: The VM. @@ -749,12 +795,15 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), .check_pages_threshold = IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, + .devmem_only = atomic && IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), }; struct xe_svm_range *range; struct drm_gpusvm_range *r; struct drm_exec exec; struct dma_fence *fence; struct xe_tile *tile = gt_to_tile(gt); + int migrate_try_count = ctx.devmem_only ? 3 : 1; ktime_t end = 0; int err; @@ -775,24 +824,30 @@ retry: if (IS_ERR(r)) return PTR_ERR(r); + if (ctx.devmem_only && !r->flags.migrate_devmem) + return -EACCES; + range = to_xe_range(r); - if (xe_svm_range_is_valid(range, tile)) + if (xe_svm_range_is_valid(range, tile, ctx.devmem_only)) return 0; range_debug(range, "PAGE FAULT"); - /* XXX: Add migration policy, for now migrate range once */ - if (!range->skip_migrate && range->base.flags.migrate_devmem && - xe_svm_range_size(range) >= SZ_64K) { - range->skip_migrate = true; - + if (--migrate_try_count >= 0 && + xe_svm_range_needs_migrate_to_vram(range, vma)) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); if (err) { - drm_dbg(&vm->xe->drm, - "VRAM allocation failed, falling back to " - "retrying fault, asid=%u, errno=%pe\n", - vm->usm.asid, ERR_PTR(err)); - goto retry; + if (migrate_try_count || !ctx.devmem_only) { + drm_dbg(&vm->xe->drm, + "VRAM allocation failed, falling back to retrying fault, asid=%u, errno=%pe\n", + vm->usm.asid, ERR_PTR(err)); + goto retry; + } else { + drm_err(&vm->xe->drm, + "VRAM allocation failed, retry count exceeded, asid=%u, errno=%pe\n", + vm->usm.asid, ERR_PTR(err)); + return err; + } } } @@ -800,15 +855,22 @@ retry: err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { - if (err == -EOPNOTSUPP) { - range_debug(range, "PAGE FAULT - EVICT PAGES"); - drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); + if (migrate_try_count > 0 || !ctx.devmem_only) { + if (err == -EOPNOTSUPP) { + range_debug(range, "PAGE FAULT - EVICT PAGES"); + drm_gpusvm_range_evict(&vm->svm.gpusvm, + &range->base); + } + drm_dbg(&vm->xe->drm, + "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + range_debug(range, "PAGE FAULT - RETRY PAGES"); + goto retry; + } else { + drm_err(&vm->xe->drm, + "Get pages failed, retry count exceeded, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); } - drm_dbg(&vm->xe->drm, - "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", - vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); - range_debug(range, "PAGE FAULT - RETRY PAGES"); - goto retry; } if (err) { range_debug(range, "PAGE FAULT - FAIL PAGE COLLECT"); @@ -842,9 +904,6 @@ retry_bind: } drm_exec_fini(&exec); - if (xe_modparam.always_migrate_to_vram) - range->skip_migrate = false; - dma_fence_wait(fence, false); dma_fence_put(fence); diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 2881af1e60b23..30fc78b85b30f 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -39,11 +39,6 @@ struct xe_svm_range { * range. Protected by GPU SVM notifier lock. */ u8 tile_invalidated; - /** - * @skip_migrate: Skip migration to VRAM, protected by GPU fault handler - * locking. - */ - u8 skip_migrate :1; }; /** diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index 9fd25fc880a49..653d48dbe1c11 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -185,6 +185,31 @@ struct drm_gpusvm_notifier { } flags; }; +/** + * struct drm_gpusvm_range_flags - Structure representing a GPU SVM range flags + * + * @migrate_devmem: Flag indicating whether the range can be migrated to device memory + * @unmapped: Flag indicating if the range has been unmapped + * @partial_unmap: Flag indicating if the range has been partially unmapped + * @has_devmem_pages: Flag indicating if the range has devmem pages + * @has_dma_mapping: Flag indicating if the range has a DMA mapping + * @__flags: Flags for range in u16 form (used for READ_ONCE) + */ +struct drm_gpusvm_range_flags { + union { + struct { + /* All flags below must be set upon creation */ + u16 migrate_devmem : 1; + /* All flags below must be set / cleared under notifier lock */ + u16 unmapped : 1; + u16 partial_unmap : 1; + u16 has_devmem_pages : 1; + u16 has_dma_mapping : 1; + }; + u16 __flags; + }; +}; + /** * struct drm_gpusvm_range - Structure representing a GPU SVM range * @@ -198,11 +223,6 @@ struct drm_gpusvm_notifier { * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping. * Note this is assuming only one drm_pagemap per range is allowed. * @flags: Flags for range - * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory - * @flags.unmapped: Flag indicating if the range has been unmapped - * @flags.partial_unmap: Flag indicating if the range has been partially unmapped - * @flags.has_devmem_pages: Flag indicating if the range has devmem pages - * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping * * This structure represents a GPU SVM range used for tracking memory ranges * mapped in a DRM device. @@ -216,15 +236,7 @@ struct drm_gpusvm_range { unsigned long notifier_seq; struct drm_pagemap_device_addr *dma_addr; struct drm_pagemap *dpagemap; - struct { - /* All flags below must be set upon creation */ - u16 migrate_devmem : 1; - /* All flags below must be set / cleared under notifier lock */ - u16 unmapped : 1; - u16 partial_unmap : 1; - u16 has_devmem_pages : 1; - u16 has_dma_mapping : 1; - } flags; + struct drm_gpusvm_range_flags flags; }; /** -- GitLab From 8dc1812b5b3a42311d28eb385eed88e2053ad3cb Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:57 -0700 Subject: [PATCH 026/902] drm/gpusvm: Add timeslicing support to GPU SVM Add timeslicing support to GPU SVM which will guarantee the GPU a minimum execution time on piece of physical memory before migration back to CPU. Intended to implement strict migration policies which require memory to be in a certain placement for correct execution. Required for shared CPU and GPU atomics on certain devices. Fixes: 99624bdff867 ("drm/gpusvm: Add support for GPU Shared Virtual Memory") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-4-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 9 +++++++++ include/drm/drm_gpusvm.h | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 41f6616bcf76f..4b2f32889f00f 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1783,6 +1783,8 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm, goto err_finalize; /* Upon success bind devmem allocation to range and zdd */ + devmem_allocation->timeslice_expiration = get_jiffies_64() + + msecs_to_jiffies(ctx->timeslice_ms); zdd->devmem_allocation = devmem_allocation; /* Owns ref */ err_finalize: @@ -2003,6 +2005,13 @@ static int __drm_gpusvm_migrate_to_ram(struct vm_area_struct *vas, void *buf; int i, err = 0; + if (page) { + zdd = page->zone_device_data; + if (time_before64(get_jiffies_64(), + zdd->devmem_allocation->timeslice_expiration)) + return 0; + } + start = ALIGN_DOWN(fault_addr, size); end = ALIGN(fault_addr + 1, size); diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index 653d48dbe1c11..eaf704d3d05e8 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -89,6 +89,7 @@ struct drm_gpusvm_devmem_ops { * @ops: Pointer to the operations structure for GPU SVM device memory * @dpagemap: The struct drm_pagemap of the pages this allocation belongs to. * @size: Size of device memory allocation + * @timeslice_expiration: Timeslice expiration in jiffies */ struct drm_gpusvm_devmem { struct device *dev; @@ -97,6 +98,7 @@ struct drm_gpusvm_devmem { const struct drm_gpusvm_devmem_ops *ops; struct drm_pagemap *dpagemap; size_t size; + u64 timeslice_expiration; }; /** @@ -295,6 +297,8 @@ struct drm_gpusvm { * @check_pages_threshold: Check CPU pages for present if chunk is less than or * equal to threshold. If not present, reduce chunk * size. + * @timeslice_ms: The timeslice MS which in minimum time a piece of memory + * remains with either exclusive GPU or CPU access. * @in_notifier: entering from a MMU notifier * @read_only: operating on read-only memory * @devmem_possible: possible to use device memory @@ -304,6 +308,7 @@ struct drm_gpusvm { */ struct drm_gpusvm_ctx { unsigned long check_pages_threshold; + unsigned long timeslice_ms; unsigned int in_notifier :1; unsigned int read_only :1; unsigned int devmem_possible :1; -- GitLab From a5d8d3be1dea8154edbbea481081469627665659 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:58 -0700 Subject: [PATCH 027/902] drm/xe: Timeslice GPU on atomic SVM fault Ensure GPU can make forward progress on an atomic SVM GPU fault by giving the GPU a timeslice of 5ms v2: - Reduce timeslice to 5ms - Double timeslice on retry - Split out GPU SVM changes into independent patch v5: - Double timeslice in a few more places Fixes: 2f118c949160 ("drm/xe: Add SVM VRAM migration") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-5-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_svm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d8e15259a8dfc..d934df622276a 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -797,6 +797,8 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, .devmem_only = atomic && IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), + .timeslice_ms = atomic && IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? 5 : 0, }; struct xe_svm_range *range; struct drm_gpusvm_range *r; @@ -836,6 +838,7 @@ retry: if (--migrate_try_count >= 0 && xe_svm_range_needs_migrate_to_vram(range, vma)) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (err) { if (migrate_try_count || !ctx.devmem_only) { drm_dbg(&vm->xe->drm, @@ -855,6 +858,7 @@ retry: err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (migrate_try_count > 0 || !ctx.devmem_only) { if (err == -EOPNOTSUPP) { range_debug(range, "PAGE FAULT - EVICT PAGES"); @@ -894,6 +898,7 @@ retry_bind: drm_exec_fini(&exec); err = PTR_ERR(fence); if (err == -EAGAIN) { + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ range_debug(range, "PAGE FAULT - RETRY BIND"); goto retry; } -- GitLab From 1b894c22462f286537b934d4dfcb20e6a9f7f4ee Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:59 -0700 Subject: [PATCH 028/902] drm/xe: Add atomic_svm_timeslice_ms debugfs entry Add some informal control for atomic SVM fault GPU timeslice to be able to play around with values and tweak performance. v2: - Reduce timeslice default value to 5ms Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-6-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_debugfs.c | 38 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_device.c | 1 + drivers/gpu/drm/xe/xe_device_types.h | 3 +++ drivers/gpu/drm/xe/xe_svm.c | 3 ++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index d0503959a8ed0..d83cd6ed3fa8a 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -191,6 +191,41 @@ static const struct file_operations wedged_mode_fops = { .write = wedged_mode_set, }; +static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf, + size_t size, loff_t *pos) +{ + struct xe_device *xe = file_inode(f)->i_private; + char buf[32]; + int len = 0; + + len = scnprintf(buf, sizeof(buf), "%d\n", xe->atomic_svm_timeslice_ms); + + return simple_read_from_buffer(ubuf, size, pos, buf, len); +} + +static ssize_t atomic_svm_timeslice_ms_set(struct file *f, + const char __user *ubuf, + size_t size, loff_t *pos) +{ + struct xe_device *xe = file_inode(f)->i_private; + u32 atomic_svm_timeslice_ms; + ssize_t ret; + + ret = kstrtouint_from_user(ubuf, size, 0, &atomic_svm_timeslice_ms); + if (ret) + return ret; + + xe->atomic_svm_timeslice_ms = atomic_svm_timeslice_ms; + + return size; +} + +static const struct file_operations atomic_svm_timeslice_ms_fops = { + .owner = THIS_MODULE, + .read = atomic_svm_timeslice_ms_show, + .write = atomic_svm_timeslice_ms_set, +}; + void xe_debugfs_register(struct xe_device *xe) { struct ttm_device *bdev = &xe->ttm; @@ -211,6 +246,9 @@ void xe_debugfs_register(struct xe_device *xe) debugfs_create_file("wedged_mode", 0600, root, xe, &wedged_mode_fops); + debugfs_create_file("atomic_svm_timeslice_ms", 0600, root, xe, + &atomic_svm_timeslice_ms_fops); + for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) { man = ttm_manager_type(bdev, mem_type); diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 399ae5f40321a..d4b6e623aa48b 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -442,6 +442,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, xe->info.devid = pdev->device; xe->info.revid = pdev->revision; xe->info.force_execlist = xe_modparam.force_execlist; + xe->atomic_svm_timeslice_ms = 5; err = xe_irq_init(xe); if (err) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 495bc00ebed4c..59babadeb9d17 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -571,6 +571,9 @@ struct xe_device { /** @pmu: performance monitoring unit */ struct xe_pmu pmu; + /** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */ + u32 atomic_svm_timeslice_ms; + #ifdef TEST_VM_OPS_ERROR /** * @vm_inject_error_position: inject errors at different places in VM diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d934df622276a..ab88b4194e574 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -798,7 +798,8 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, .devmem_only = atomic && IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), .timeslice_ms = atomic && IS_DGFX(vm->xe) && - IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? 5 : 0, + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? + vm->xe->atomic_svm_timeslice_ms : 0, }; struct xe_svm_range *range; struct drm_gpusvm_range *r; -- GitLab From 38b14233e5deff51db8faec287b4acd227152246 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:01 -0700 Subject: [PATCH 029/902] drm/xe: Save CTX_TIMESTAMP mmio value instead of LRC value For determining actual job execution time, save the current value of the CTX_TIMESTAMP register rather than the value saved in LRC since the current register value is the closest to the start time of the job. v2: Define MI_STORE_REGISTER_MEM to fix compile error v3: Place MI_STORE_REGISTER_MEM sorted by MI_INSTR (Lucas) Fixes: 65921374c48f ("drm/xe: Emit ctx timestamp copy in ring ops") Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-6-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/instructions/xe_mi_commands.h | 4 ++++ drivers/gpu/drm/xe/xe_lrc.c | 2 +- drivers/gpu/drm/xe/xe_ring_ops.c | 7 ++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h index eba582058d550..e3f5e8bb3ebcd 100644 --- a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h +++ b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h @@ -48,6 +48,10 @@ #define MI_LRI_FORCE_POSTED REG_BIT(12) #define MI_LRI_LEN(x) (((x) & 0xff) + 1) +#define MI_STORE_REGISTER_MEM (__MI_INSTR(0x24) | XE_INSTR_NUM_DW(4)) +#define MI_SRM_USE_GGTT REG_BIT(22) +#define MI_SRM_ADD_CS_OFFSET REG_BIT(19) + #define MI_FLUSH_DW __MI_INSTR(0x26) #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 855c8acaf3f1e..015b00a73c0b7 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -687,7 +687,7 @@ static inline u32 __xe_lrc_start_seqno_offset(struct xe_lrc *lrc) static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc) { - /* The start seqno is stored in the driver-defined portion of PPHWSP */ + /* This is stored in the driver-defined portion of PPHWSP */ return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET; } diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c index a7582b097ae67..bc1689db4cd71 100644 --- a/drivers/gpu/drm/xe/xe_ring_ops.c +++ b/drivers/gpu/drm/xe/xe_ring_ops.c @@ -234,13 +234,10 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) { - dw[i++] = MI_COPY_MEM_MEM | MI_COPY_MEM_MEM_SRC_GGTT | - MI_COPY_MEM_MEM_DST_GGTT; + dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; + dw[i++] = RING_CTX_TIMESTAMP(0).addr; dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); dw[i++] = 0; - dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc); - dw[i++] = 0; - dw[i++] = MI_NOOP; return i; } -- GitLab From 741d3ef8b8b88fab2729ca89de1180e49bc9cef0 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:02 -0700 Subject: [PATCH 030/902] drm/xe: Save the gt pointer in lrc and drop the tile Save the gt pointer in the lrc so that it can used for gt based helpers. Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-7-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/xe_lrc.c | 4 ++-- drivers/gpu/drm/xe/xe_lrc_types.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 015b00a73c0b7..9d9be93832074 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -867,7 +867,7 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe) static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) { - u64 desc = xe_vm_pdp4_descriptor(vm, lrc->tile); + u64 desc = xe_vm_pdp4_descriptor(vm, gt_to_tile(lrc->gt)); xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc)); xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc)); @@ -900,6 +900,7 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, int err; kref_init(&lrc->refcount); + lrc->gt = gt; lrc->flags = 0; lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); if (xe_gt_has_indirect_ring_state(gt)) @@ -921,7 +922,6 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, return PTR_ERR(lrc->bo); lrc->size = lrc_size; - lrc->tile = gt_to_tile(hwe->gt); lrc->ring.size = ring_size; lrc->ring.tail = 0; lrc->ctx_timestamp = 0; diff --git a/drivers/gpu/drm/xe/xe_lrc_types.h b/drivers/gpu/drm/xe/xe_lrc_types.h index 71ecb453f811a..cd38586ae9893 100644 --- a/drivers/gpu/drm/xe/xe_lrc_types.h +++ b/drivers/gpu/drm/xe/xe_lrc_types.h @@ -25,8 +25,8 @@ struct xe_lrc { /** @size: size of lrc including any indirect ring state page */ u32 size; - /** @tile: tile which this LRC belongs to */ - struct xe_tile *tile; + /** @gt: gt which this LRC belongs to */ + struct xe_gt *gt; /** @flags: LRC flags */ #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 -- GitLab From 82b98cadb01f63cdb159e596ec06866d00f8e8c7 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:03 -0700 Subject: [PATCH 031/902] drm/xe: Add WA BB to capture active context utilization Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the context, but only gets updated when the context switches out. In order to check how long a context has been active before it switches out, two things are required: (1) Determine if the context is running: To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in the LRC. The value chosen is 1 since 0 is the initial value when the LRC is initialized. During a query, we just check for this value to determine if the context is active. If the context switched out, it would overwrite this location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as the last part of the context restore, so reusing this LRC location will not clobber anything. (2) Calculate the time that the context has been active for: The CTX_TIMESTAMP ticks only when the context is active. If a context is active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization. While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific engine instance. Since we do not know which instance the context is running on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and store it in the PPHSWP. Using the above 2 instructions in a WA BB, capture active context utilization. v2: (Matt Brost) - This breaks TDR, fix it by saving the CTX_TIMESTAMP register "drm/xe: Save CTX_TIMESTAMP mmio value instead of LRC value" - Drop tile from LRC if using gt "drm/xe: Save the gt pointer in LRC and drop the tile" v3: - Remove helpers for bb_per_ctx_ptr (Matt) - Add define for context active value (Matt) - Use 64 bit CTX TIMESTAMP for platforms that support it. For platforms that don't, live with the rare race. (Matt, Lucas) - Convert engine id to hwe and get the MMIO value (Lucas) - Correct commit message on when WA BB runs (Lucas) v4: - s/GRAPHICS_VER(...)/xe->info.has_64bit_timestamp/ (Matt) - Drop support for active utilization on a VF (CI failure) - In xe_lrc_init ensure the lrc value is 0 to begin with (CI regression) v5: - Minor checkpatch fix - Squash into previous commit and make TDR use 32-bit time - Update code comment to match commit msg Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4532 Suggested-by: Lucas De Marchi Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-8-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 5 + drivers/gpu/drm/xe/regs/xe_lrc_layout.h | 2 + drivers/gpu/drm/xe/xe_device_types.h | 2 + drivers/gpu/drm/xe/xe_exec_queue.c | 2 +- drivers/gpu/drm/xe/xe_guc_submit.c | 2 +- drivers/gpu/drm/xe/xe_lrc.c | 185 ++++++++++++++++++++++- drivers/gpu/drm/xe/xe_lrc.h | 5 +- drivers/gpu/drm/xe/xe_lrc_types.h | 5 +- drivers/gpu/drm/xe/xe_pci.c | 2 + drivers/gpu/drm/xe/xe_pci_types.h | 1 + drivers/gpu/drm/xe/xe_trace_lrc.h | 8 +- 11 files changed, 203 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index da713634d6a0c..7ade41e2b7b3b 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -43,6 +43,10 @@ #define XEHPC_BCS8_RING_BASE 0x3ee000 #define GSCCS_RING_BASE 0x11a000 +#define ENGINE_ID(base) XE_REG((base) + 0x8c) +#define ENGINE_INSTANCE_ID REG_GENMASK(9, 4) +#define ENGINE_CLASS_ID REG_GENMASK(2, 0) + #define RING_TAIL(base) XE_REG((base) + 0x30) #define TAIL_ADDR REG_GENMASK(20, 3) @@ -154,6 +158,7 @@ #define STOP_RING REG_BIT(8) #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) +#define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) #define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc) #define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4) diff --git a/drivers/gpu/drm/xe/regs/xe_lrc_layout.h b/drivers/gpu/drm/xe/regs/xe_lrc_layout.h index 57944f90bbf6e..994af591a2e85 100644 --- a/drivers/gpu/drm/xe/regs/xe_lrc_layout.h +++ b/drivers/gpu/drm/xe/regs/xe_lrc_layout.h @@ -11,7 +11,9 @@ #define CTX_RING_TAIL (0x06 + 1) #define CTX_RING_START (0x08 + 1) #define CTX_RING_CTL (0x0a + 1) +#define CTX_BB_PER_CTX_PTR (0x12 + 1) #define CTX_TIMESTAMP (0x22 + 1) +#define CTX_TIMESTAMP_UDW (0x24 + 1) #define CTX_INDIRECT_RING_STATE (0x26 + 1) #define CTX_PDP0_UDW (0x30 + 1) #define CTX_PDP0_LDW (0x32 + 1) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 59babadeb9d17..f81be293b260e 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -334,6 +334,8 @@ struct xe_device { u8 has_sriov:1; /** @info.has_usm: Device has unified shared memory support */ u8 has_usm:1; + /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ + u8 has_64bit_timestamp:1; /** @info.is_dgfx: is discrete device */ u8 is_dgfx:1; /** @info.needs_scratch: needs scratch page for oob prefetch to work */ diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 21d4ced31dd9b..ce78cee5dec68 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -829,7 +829,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) { struct xe_device *xe = gt_to_xe(q->gt); struct xe_lrc *lrc; - u32 old_ts, new_ts; + u64 old_ts, new_ts; int idx; /* diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 06e2998b0e214..fb125f940de8f 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -967,7 +967,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) return xe_sched_invalidate_job(job, 2); } - ctx_timestamp = xe_lrc_ctx_timestamp(q->lrc[0]); + ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); /* diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 9d9be93832074..61a2e87990a9d 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -24,6 +24,7 @@ #include "xe_hw_fence.h" #include "xe_map.h" #include "xe_memirq.h" +#include "xe_mmio.h" #include "xe_sriov.h" #include "xe_trace_lrc.h" #include "xe_vm.h" @@ -654,6 +655,7 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc) #define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8) #define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8) #define LRC_PARALLEL_PPHWSP_OFFSET 2048 +#define LRC_ENGINE_ID_PPHWSP_OFFSET 2096 u32 xe_lrc_regs_offset(struct xe_lrc *lrc) { @@ -697,11 +699,21 @@ static inline u32 __xe_lrc_parallel_offset(struct xe_lrc *lrc) return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET; } +static inline u32 __xe_lrc_engine_id_offset(struct xe_lrc *lrc) +{ + return xe_lrc_pphwsp_offset(lrc) + LRC_ENGINE_ID_PPHWSP_OFFSET; +} + static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc) { return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32); } +static u32 __xe_lrc_ctx_timestamp_udw_offset(struct xe_lrc *lrc) +{ + return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP_UDW * sizeof(u32); +} + static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc) { /* Indirect ring state page is at the very end of LRC */ @@ -729,8 +741,10 @@ DECL_MAP_ADDR_HELPERS(regs) DECL_MAP_ADDR_HELPERS(start_seqno) DECL_MAP_ADDR_HELPERS(ctx_job_timestamp) DECL_MAP_ADDR_HELPERS(ctx_timestamp) +DECL_MAP_ADDR_HELPERS(ctx_timestamp_udw) DECL_MAP_ADDR_HELPERS(parallel) DECL_MAP_ADDR_HELPERS(indirect_ring) +DECL_MAP_ADDR_HELPERS(engine_id) #undef DECL_MAP_ADDR_HELPERS @@ -745,19 +759,38 @@ u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc) return __xe_lrc_ctx_timestamp_ggtt_addr(lrc); } +/** + * xe_lrc_ctx_timestamp_udw_ggtt_addr() - Get ctx timestamp udw GGTT address + * @lrc: Pointer to the lrc. + * + * Returns: ctx timestamp udw GGTT address + */ +u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc) +{ + return __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); +} + /** * xe_lrc_ctx_timestamp() - Read ctx timestamp value * @lrc: Pointer to the lrc. * * Returns: ctx timestamp value */ -u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) +u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) { struct xe_device *xe = lrc_to_xe(lrc); struct iosys_map map; + u32 ldw, udw = 0; map = __xe_lrc_ctx_timestamp_map(lrc); - return xe_map_read32(xe, &map); + ldw = xe_map_read32(xe, &map); + + if (xe->info.has_64bit_timestamp) { + map = __xe_lrc_ctx_timestamp_udw_map(lrc); + udw = xe_map_read32(xe, &map); + } + + return (u64)udw << 32 | ldw; } /** @@ -880,6 +913,65 @@ static void xe_lrc_finish(struct xe_lrc *lrc) xe_bo_unpin(lrc->bo); xe_bo_unlock(lrc->bo); xe_bo_put(lrc->bo); + xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo); +} + +/* + * xe_lrc_setup_utilization() - Setup wa bb to assist in calculating active + * context run ticks. + * @lrc: Pointer to the lrc. + * + * Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the + * context, but only gets updated when the context switches out. In order to + * check how long a context has been active before it switches out, two things + * are required: + * + * (1) Determine if the context is running: + * To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in + * the LRC. The value chosen is 1 since 0 is the initial value when the LRC is + * initialized. During a query, we just check for this value to determine if the + * context is active. If the context switched out, it would overwrite this + * location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as + * the last part of context restore, so reusing this LRC location will not + * clobber anything. + * + * (2) Calculate the time that the context has been active for: + * The CTX_TIMESTAMP ticks only when the context is active. If a context is + * active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization. + * While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific + * engine instance. Since we do not know which instance the context is running + * on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and + * store it in the PPHSWP. + */ +#define CONTEXT_ACTIVE 1ULL +static void xe_lrc_setup_utilization(struct xe_lrc *lrc) +{ + u32 *cmd; + + cmd = lrc->bb_per_ctx_bo->vmap.vaddr; + + *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; + *cmd++ = ENGINE_ID(0).addr; + *cmd++ = __xe_lrc_engine_id_ggtt_addr(lrc); + *cmd++ = 0; + + *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); + *cmd++ = __xe_lrc_ctx_timestamp_ggtt_addr(lrc); + *cmd++ = 0; + *cmd++ = lower_32_bits(CONTEXT_ACTIVE); + + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) { + *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); + *cmd++ = __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); + *cmd++ = 0; + *cmd++ = upper_32_bits(CONTEXT_ACTIVE); + } + + *cmd++ = MI_BATCH_BUFFER_END; + + xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, + xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); + } #define PVC_CTX_ASID (0x2e + 1) @@ -921,10 +1013,17 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, if (IS_ERR(lrc->bo)) return PTR_ERR(lrc->bo); + lrc->bb_per_ctx_bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, + ttm_bo_type_kernel, + bo_flags); + if (IS_ERR(lrc->bb_per_ctx_bo)) { + err = PTR_ERR(lrc->bb_per_ctx_bo); + goto err_lrc_finish; + } + lrc->size = lrc_size; lrc->ring.size = ring_size; lrc->ring.tail = 0; - lrc->ctx_timestamp = 0; xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt, hwe->fence_irq, hwe->name); @@ -997,7 +1096,10 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); + lrc->ctx_timestamp = 0; xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) + xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP_UDW, 0); if (xe->info.has_asid && vm) xe_lrc_write_ctx_reg(lrc, PVC_CTX_ASID, vm->usm.asid); @@ -1026,6 +1128,8 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, map = __xe_lrc_start_seqno_map(lrc); xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); + xe_lrc_setup_utilization(lrc); + return 0; err_lrc_finish: @@ -1245,6 +1349,21 @@ struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc) return __xe_lrc_parallel_map(lrc); } +/** + * xe_lrc_engine_id() - Read engine id value + * @lrc: Pointer to the lrc. + * + * Returns: context id value + */ +static u32 xe_lrc_engine_id(struct xe_lrc *lrc) +{ + struct xe_device *xe = lrc_to_xe(lrc); + struct iosys_map map; + + map = __xe_lrc_engine_id_map(lrc); + return xe_map_read32(xe, &map); +} + static int instr_dw(u32 cmd_header) { /* GFXPIPE "SINGLE_DW" opcodes are a single dword */ @@ -1692,7 +1811,7 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; snapshot->lrc_snapshot = NULL; - snapshot->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); + snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc)); snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); return snapshot; } @@ -1792,22 +1911,74 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) kfree(snapshot); } +static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) +{ + u16 class = REG_FIELD_GET(ENGINE_CLASS_ID, engine_id); + u16 instance = REG_FIELD_GET(ENGINE_INSTANCE_ID, engine_id); + struct xe_hw_engine *hwe; + u64 val; + + hwe = xe_gt_hw_engine(lrc->gt, class, instance, false); + if (xe_gt_WARN_ONCE(lrc->gt, !hwe || xe_hw_engine_is_reserved(hwe), + "Unexpected engine class:instance %d:%d for context utilization\n", + class, instance)) + return -1; + + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) + val = xe_mmio_read64_2x32(&hwe->gt->mmio, + RING_CTX_TIMESTAMP(hwe->mmio_base)); + else + val = xe_mmio_read32(&hwe->gt->mmio, + RING_CTX_TIMESTAMP(hwe->mmio_base)); + + *reg_ctx_ts = val; + + return 0; +} + /** * xe_lrc_update_timestamp() - Update ctx timestamp * @lrc: Pointer to the lrc. * @old_ts: Old timestamp value * * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and - * update saved value. + * update saved value. With support for active contexts, the calculation may be + * slightly racy, so follow a read-again logic to ensure that the context is + * still active before returning the right timestamp. * * Returns: New ctx timestamp value */ -u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts) +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) { + u64 lrc_ts, reg_ts; + u32 engine_id; + *old_ts = lrc->ctx_timestamp; - lrc->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); + lrc_ts = xe_lrc_ctx_timestamp(lrc); + /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */ + if (IS_SRIOV_VF(lrc_to_xe(lrc))) { + lrc->ctx_timestamp = lrc_ts; + goto done; + } + + if (lrc_ts == CONTEXT_ACTIVE) { + engine_id = xe_lrc_engine_id(lrc); + if (!get_ctx_timestamp(lrc, engine_id, ®_ts)) + lrc->ctx_timestamp = reg_ts; + + /* read lrc again to ensure context is still active */ + lrc_ts = xe_lrc_ctx_timestamp(lrc); + } + + /* + * If context switched out, just use the lrc_ts. Note that this needs to + * be a separate if condition. + */ + if (lrc_ts != CONTEXT_ACTIVE) + lrc->ctx_timestamp = lrc_ts; +done: trace_xe_lrc_update_timestamp(lrc, *old_ts); return lrc->ctx_timestamp; diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h index 0b40f349ab95d..eb6e8de8c939e 100644 --- a/drivers/gpu/drm/xe/xe_lrc.h +++ b/drivers/gpu/drm/xe/xe_lrc.h @@ -120,7 +120,8 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); -u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); +u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc); +u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); @@ -136,6 +137,6 @@ u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); * * Returns the current LRC timestamp */ -u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts); +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts); #endif diff --git a/drivers/gpu/drm/xe/xe_lrc_types.h b/drivers/gpu/drm/xe/xe_lrc_types.h index cd38586ae9893..ae24cf6f8dd99 100644 --- a/drivers/gpu/drm/xe/xe_lrc_types.h +++ b/drivers/gpu/drm/xe/xe_lrc_types.h @@ -52,7 +52,10 @@ struct xe_lrc { struct xe_hw_fence_ctx fence_ctx; /** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */ - u32 ctx_timestamp; + u64 ctx_timestamp; + + /** @bb_per_ctx_bo: buffer object for per context batch wa buffer */ + struct xe_bo *bb_per_ctx_bo; }; struct xe_lrc_snapshot; diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 882398e09b7e3..024175cfe61e6 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -142,6 +142,7 @@ static const struct xe_graphics_desc graphics_xelpg = { .has_indirect_ring_state = 1, \ .has_range_tlb_invalidation = 1, \ .has_usm = 1, \ + .has_64bit_timestamp = 1, \ .va_bits = 48, \ .vm_max_level = 4, \ .hw_engine_mask = \ @@ -677,6 +678,7 @@ static int xe_info_init(struct xe_device *xe, xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; xe->info.has_usm = graphics_desc->has_usm; + xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; for_each_remote_tile(tile, xe, id) { int err; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index e9b9bbc138d37..ca6b10d355734 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -21,6 +21,7 @@ struct xe_graphics_desc { u8 has_indirect_ring_state:1; u8 has_range_tlb_invalidation:1; u8 has_usm:1; + u8 has_64bit_timestamp:1; }; struct xe_media_desc { diff --git a/drivers/gpu/drm/xe/xe_trace_lrc.h b/drivers/gpu/drm/xe/xe_trace_lrc.h index 5c669a0b21808..d525cbee1e341 100644 --- a/drivers/gpu/drm/xe/xe_trace_lrc.h +++ b/drivers/gpu/drm/xe/xe_trace_lrc.h @@ -19,12 +19,12 @@ #define __dev_name_lrc(lrc) dev_name(gt_to_xe((lrc)->fence_ctx.gt)->drm.dev) TRACE_EVENT(xe_lrc_update_timestamp, - TP_PROTO(struct xe_lrc *lrc, uint32_t old), + TP_PROTO(struct xe_lrc *lrc, uint64_t old), TP_ARGS(lrc, old), TP_STRUCT__entry( __field(struct xe_lrc *, lrc) - __field(u32, old) - __field(u32, new) + __field(u64, old) + __field(u64, new) __string(name, lrc->fence_ctx.name) __string(device_id, __dev_name_lrc(lrc)) ), @@ -36,7 +36,7 @@ TRACE_EVENT(xe_lrc_update_timestamp, __assign_str(name); __assign_str(device_id); ), - TP_printk("lrc=:%p lrc->name=%s old=%u new=%u device_id:%s", + TP_printk("lrc=:%p lrc->name=%s old=%llu new=%llu device_id:%s", __entry->lrc, __get_str(name), __entry->old, __entry->new, __get_str(device_id)) -- GitLab From 6819b5a67e7014352906f82ddedafb602ac8d45d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:52 +0300 Subject: [PATCH 032/902] drm/i915: rename vlv_sideband*.[ch] to vlv_iosf_sb*.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be more specific in the naming, and follow the existing function naming pattern of vlv_iosf_sb_*() in the file. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/d3d97d34a197ba801c558c3fd72b29f9e5c783af.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power_map.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power_well.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 2 +- drivers/gpu/drm/i915/gt/intel_rps.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/i915/intel_clock_gating.c | 2 +- drivers/gpu/drm/i915/soc/intel_dram.c | 2 +- drivers/gpu/drm/i915/{vlv_sideband.c => vlv_iosf_sb.c} | 2 +- drivers/gpu/drm/i915/{vlv_sideband.h => vlv_iosf_sb.h} | 8 ++++---- .../drm/i915/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} | 6 +++--- .../compat-i915-headers/{vlv_sideband.h => vlv_iosf_sb.h} | 8 ++++---- .../{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} | 2 +- 22 files changed, 31 insertions(+), 31 deletions(-) rename drivers/gpu/drm/i915/{vlv_sideband.c => vlv_iosf_sb.c} (99%) rename drivers/gpu/drm/i915/{vlv_sideband.h => vlv_iosf_sb.h} (96%) rename drivers/gpu/drm/i915/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} (98%) rename drivers/gpu/drm/xe/compat-i915-headers/{vlv_sideband.h => vlv_iosf_sb.h} (96%) rename drivers/gpu/drm/xe/compat-i915-headers/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} (66%) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 13d4a16f7d33a..3e3e4f4bfa4e2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -45,7 +45,7 @@ i915-y += \ intel_uncore.o \ intel_uncore_trace.o \ intel_wakeref.o \ - vlv_sideband.o \ + vlv_iosf_sb.o \ vlv_suspend.o # core peripheral code diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 77876ef735b74..02f33cbe6765c 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -16,7 +16,7 @@ #include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct intel_watermark_params { u16 fifo_size; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b1718b491ffda..501b794984149 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -47,7 +47,7 @@ #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_dsi.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /** * DOC: CDCLK / RAWCLK diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 704ca079980c2..c7a6b710b7c0a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -131,7 +131,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 16356523816fb..b3b05d7610e8a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -27,7 +27,7 @@ #include "intel_snps_phy.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #define for_each_power_domain_well(__display, __power_well, __domain) \ for_each_power_well((__display), __power_well) \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index ab1163744bc59..b4c302544909d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -10,7 +10,7 @@ #include "intel_display_power_map.h" #include "intel_display_power_well.h" #include "intel_display_types.h" -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" #define __LIST_INLINE_ELEMS(__elem_type, ...) \ ((__elem_type[]) { __VA_ARGS__ }) diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index b104bce0e14df..6772ac0c3f84c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -30,8 +30,8 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb.h" +#include "vlv_iosf_sb_reg.h" struct i915_power_well_regs { i915_reg_t bios; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 69f2421394205..5b9c0852da2cf 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -32,7 +32,7 @@ #include "intel_dp.h" #include "intel_dpio_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /** * DOC: DPIO diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a9e9b98d0bf9c..055dd2b4a9043 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -22,7 +22,7 @@ #include "intel_pps.h" #include "intel_snps_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct intel_dpll_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 29c9209834138..dce4fdf091f67 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -49,7 +49,7 @@ #include "intel_pps_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #define MIPI_TRANSFER_MODE_SHIFT 0 #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 346737f15fa93..110914bbc1348 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -49,7 +49,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /* return pixels in terms of txbyteclkhs */ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 7ce924a5ef90b..79438cdfc3f9d 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -34,7 +34,7 @@ #include "intel_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_pll_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" static const u16 lfsr_converts[] = { 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index b635aa2820d9f..0704fe763afed 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -22,7 +22,7 @@ #include "intel_rps.h" #include "intel_runtime_pm.h" #include "intel_uncore.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) { diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 461708f1ac543..7fa341d2bfe4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -23,7 +23,7 @@ #include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_rps.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "../../../platform/x86/intel_ips.h" #define BUSY_MAX_EI 20u /* ms */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 273bc43468a0f..2b0bcb9aa3c72 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -108,7 +108,7 @@ #include "intel_pcode.h" #include "intel_region_ttm.h" #include "intel_sbi.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "vlv_suspend.h" static const struct drm_driver i915_drm_driver; diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 387b264001690..8aec8c638fd81 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -37,7 +37,7 @@ #include "i915_reg.h" #include "intel_clock_gating.h" #include "intel_mchbar_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct drm_i915_clock_gating_funcs { void (*init_clock_gating)(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index eee5c4f45a43c..0b92ab4e9fb9b 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -10,7 +10,7 @@ #include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct dram_dimm_info { u16 size; diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c similarity index 99% rename from drivers/gpu/drm/i915/vlv_sideband.c rename to drivers/gpu/drm/i915/vlv_iosf_sb.c index 114ae8eb9cd51..91703c6c478c5 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -6,7 +6,7 @@ #include "i915_drv.h" #include "i915_iosf_mbi.h" #include "i915_reg.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "display/intel_dpio_phy.h" diff --git a/drivers/gpu/drm/i915/vlv_sideband.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h similarity index 96% rename from drivers/gpu/drm/i915/vlv_sideband.h rename to drivers/gpu/drm/i915/vlv_iosf_sb.h index 31813e07c56fb..380b96089cda8 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -3,13 +3,13 @@ * Copyright © 2013-2021 Intel Corporation */ -#ifndef _VLV_SIDEBAND_H_ -#define _VLV_SIDEBAND_H_ +#ifndef _VLV_IOSF_SB_H_ +#define _VLV_IOSF_SB_H_ #include #include -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" enum dpio_phy; struct drm_i915_private; @@ -122,4 +122,4 @@ static inline void vlv_punit_put(struct drm_i915_private *i915) vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); } -#endif /* _VLV_SIDEBAND_H_ */ +#endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/i915/vlv_sideband_reg.h b/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h similarity index 98% rename from drivers/gpu/drm/i915/vlv_sideband_reg.h rename to drivers/gpu/drm/i915/vlv_iosf_sb_reg.h index b7fbff3d04099..f977fb3b6e173 100644 --- a/drivers/gpu/drm/i915/vlv_sideband_reg.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _VLV_SIDEBAND_REG_H_ -#define _VLV_SIDEBAND_REG_H_ +#ifndef _VLV_IOSF_SB_REG_H_ +#define _VLV_IOSF_SB_REG_H_ /* See configdb bunit SB addr map */ #define BUNIT_REG_BISOC 0x11 @@ -177,4 +177,4 @@ #define CCK_FREQUENCY_STATUS_SHIFT 8 #define CCK_FREQUENCY_VALUES (0x1f << 0) -#endif /* _VLV_SIDEBAND_REG_H_ */ +#endif /* _VLV_IOSF_SB_REG_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h similarity index 96% rename from drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h rename to drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index ec6f12de57274..b42a518a79e0a 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -3,12 +3,12 @@ * Copyright © 2013-2021 Intel Corporation */ -#ifndef _VLV_SIDEBAND_H_ -#define _VLV_SIDEBAND_H_ +#ifndef _VLV_IOSF_SB_H_ +#define _VLV_IOSF_SB_H_ #include -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" enum pipe; struct drm_i915_private; @@ -129,4 +129,4 @@ static inline void vlv_punit_put(struct drm_i915_private *i915) { } -#endif /* _VLV_SIDEBAND_H_ */ +#endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h similarity index 66% rename from drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h rename to drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h index 949f134ce3cf3..cb7fa8e794a60 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h @@ -3,4 +3,4 @@ * Copyright © 2023 Intel Corporation */ -#include "../../i915/vlv_sideband_reg.h" +#include "../../i915/vlv_iosf_sb_reg.h" -- GitLab From 7e9f0cc24bb6a2121a6abaef401d429f94ea2e8b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:53 +0300 Subject: [PATCH 033/902] drm/i915: add generic read/write functions for VLV IOSF SB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The read/write functions will be helpful for rewriting the unit specific functions. v2: Fix checkpatch complaint on indent Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/babe42609c7a2056aff301320efbda534d20ad82.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 73 +++++++++++++++++++ drivers/gpu/drm/i915/vlv_iosf_sb.h | 6 +- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 9 ++- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 91703c6c478c5..aaed876a1f2e7 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -123,6 +123,79 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, return err; } +static u32 unit_to_devfn(enum vlv_iosf_sb_unit unit) +{ + if (unit == VLV_IOSF_SB_DPIO || unit == VLV_IOSF_SB_DPIO_2 || + unit == VLV_IOSF_SB_FLISDSI) + return DPIO_DEVFN; + else + return PCI_DEVFN(0, 0); +} + +static u32 unit_to_port(enum vlv_iosf_sb_unit unit) +{ + switch (unit) { + case VLV_IOSF_SB_BUNIT: + return IOSF_PORT_BUNIT; + case VLV_IOSF_SB_CCK: + return IOSF_PORT_CCK; + case VLV_IOSF_SB_CCU: + return IOSF_PORT_CCU; + case VLV_IOSF_SB_DPIO: + return IOSF_PORT_DPIO; + case VLV_IOSF_SB_DPIO_2: + return IOSF_PORT_DPIO_2; + case VLV_IOSF_SB_FLISDSI: + return IOSF_PORT_FLISDSI; + case VLV_IOSF_SB_GPIO: + return 0; /* FIXME: unused */ + case VLV_IOSF_SB_NC: + return IOSF_PORT_NC; + case VLV_IOSF_SB_PUNIT: + return IOSF_PORT_PUNIT; + default: + return 0; + } +} + +static u32 unit_to_opcode(enum vlv_iosf_sb_unit unit, bool write) +{ + if (unit == VLV_IOSF_SB_DPIO || unit == VLV_IOSF_SB_DPIO_2) + return write ? SB_MWR_NP : SB_MRD_NP; + else + return write ? SB_CRWRDA_NP : SB_CRRDDA_NP; +} + +u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +{ + u32 devfn, port, opcode, val = 0; + + devfn = unit_to_devfn(unit); + port = unit_to_port(unit); + opcode = unit_to_opcode(unit, false); + + if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) + return 0; + + vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); + + return val; +} + +int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +{ + u32 devfn, port, opcode; + + devfn = unit_to_devfn(unit); + port = unit_to_port(unit); + opcode = unit_to_opcode(unit, true); + + if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) + return -EINVAL; + + return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); +} + u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) { u32 val = 0; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 380b96089cda8..26af3aa973f8b 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -14,11 +14,12 @@ enum dpio_phy; struct drm_i915_private; -enum { +enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, VLV_IOSF_SB_CCK, VLV_IOSF_SB_CCU, VLV_IOSF_SB_DPIO, + VLV_IOSF_SB_DPIO_2, VLV_IOSF_SB_FLISDSI, VLV_IOSF_SB_GPIO, VLV_IOSF_SB_NC, @@ -31,6 +32,9 @@ void vlv_iosf_sb_fini(struct drm_i915_private *i915); void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports); void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); +u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); +int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); + static inline void vlv_bunit_get(struct drm_i915_private *i915) { vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index b42a518a79e0a..57f7dde90ced8 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -13,11 +13,12 @@ enum pipe; struct drm_i915_private; -enum { +enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, VLV_IOSF_SB_CCK, VLV_IOSF_SB_CCU, VLV_IOSF_SB_DPIO, + VLV_IOSF_SB_DPIO_2, VLV_IOSF_SB_FLISDSI, VLV_IOSF_SB_GPIO, VLV_IOSF_SB_NC, @@ -27,13 +28,13 @@ enum { static inline void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) { } -static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg) +static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) { return 0; } -static inline void vlv_iosf_sb_write(struct drm_i915_private *i915, - u8 port, u32 reg, u32 val) +static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { + return 0; } static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) { -- GitLab From 5c76b7178b511019c0c5f5544d9bfc4b9589f0d4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:54 +0300 Subject: [PATCH 034/902] drm/i915: rewrite VLV IOSF SB unit specific read/write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite the VLV IOSF SB unit specific helpers in terms of the new generic read/write functions. They become even simpler than they were. The DPIO get/put helpers need to get/put both DPIO units. v2: get/put both DPIO units Reviewed-by: Ville Syrjälä # v1 Link: https://lore.kernel.org/r/df97dafa0f7b665e2078c392f0dc3edc59655b0a.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 73 ++++++++---------------------- drivers/gpu/drm/i915/vlv_iosf_sb.h | 4 +- 2 files changed, 22 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index aaed876a1f2e7..efb5ee39dbbb2 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -198,96 +198,68 @@ int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, - SB_CRRDDA_NP, addr, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); } int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) { - return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, - SB_CRWRDA_NP, addr, &val); + return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); } u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); } void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); } u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC, - SB_CRRDDA_NP, addr, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); } u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); } void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); } u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); } void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); } -static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy) +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, + enum dpio_phy phy) { /* * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) */ if (IS_CHERRYVIEW(i915)) - return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO; + return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; else - return IOSF_PORT_DPIO; + return VLV_IOSF_SB_DPIO; } u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) { - u32 port = vlv_dpio_phy_iosf_port(i915, phy); - u32 val = 0; + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + u32 val; - vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val); + val = vlv_iosf_sb_read(i915, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, @@ -303,24 +275,19 @@ u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) void vlv_dpio_write(struct drm_i915_private *i915, enum dpio_phy phy, int reg, u32 val) { - u32 port = vlv_dpio_phy_iosf_port(i915, phy); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val); + vlv_iosf_sb_write(i915, unit, reg, val); } u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP, - reg, &val); - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); } void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP, - reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); } void vlv_iosf_sb_init(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 26af3aa973f8b..66f8918d49743 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -76,7 +76,7 @@ static inline void vlv_ccu_put(struct drm_i915_private *i915) static inline void vlv_dpio_get(struct drm_i915_private *i915) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO)); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); @@ -85,7 +85,7 @@ void vlv_dpio_write(struct drm_i915_private *i915, static inline void vlv_dpio_put(struct drm_i915_private *i915) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO)); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -- GitLab From ead7a1a59e37cc7134e98e3121d0962940a1c1d9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:55 +0300 Subject: [PATCH 035/902] drm/i915: switch i915 core to generic VLV IOSF SB functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll want to relocate the unit specific functions to display, making them inaccessible to i915 core. As there aren't that many users in i915 core, we can just convert them to the generic VLV IOSF SB read/write functions. v2: Use BIT(unit) for get/put Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/3162c8768eeeba928bbc3d4aa2ddfc6a1030a451.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 6 +-- drivers/gpu/drm/i915/gt/intel_rps.c | 46 +++++++++---------- drivers/gpu/drm/i915/soc/intel_dram.c | 4 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 0704fe763afed..a059c6488b3db 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -366,9 +366,9 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) drm_printf(p, "SW control enabled: %s\n", str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); - vlv_punit_get(i915); - freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + freq_sts = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); drm_printf(p, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 7fa341d2bfe4f..37487d2f121dc 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -820,9 +820,9 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) struct drm_i915_private *i915 = rps_to_i915(rps); int err; - vlv_punit_get(i915); - err = vlv_punit_write(i915, PUNIT_REG_GPU_FREQ_REQ, val); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + err = vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d\n", val, intel_gpu_freq(rps, val)); @@ -1268,7 +1268,7 @@ static int chv_rps_max_freq(struct intel_rps *rps) struct intel_gt *gt = rps_to_gt(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); switch (gt->info.sseu.eu_total) { case 8: @@ -1295,7 +1295,7 @@ static int chv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, PUNIT_GPU_DUTYCYCLE_REG); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); val >>= PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT; return val & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK; @@ -1306,7 +1306,7 @@ static int chv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); return val & FB_GFX_FREQ_FUSE_MASK; } @@ -1316,7 +1316,7 @@ static u32 chv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMIN_AT_VMIN_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); val >>= FB_GFX_FMIN_AT_VMIN_FUSE_SHIFT; return val & FB_GFX_FREQ_FUSE_MASK; @@ -1350,14 +1350,14 @@ static bool chv_rps_enable(struct intel_rps *rps) GEN6_PM_RP_DOWN_TIMEOUT); /* Setting Fixed Bias */ - vlv_punit_get(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | CHV_BIAS_CPU_50_SOC_50; - vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1375,7 +1375,7 @@ static int vlv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp1; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp1 = val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK; rp1 >>= FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT; @@ -1388,7 +1388,7 @@ static int vlv_rps_max_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp0; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; /* Clamp to max */ @@ -1402,9 +1402,9 @@ static int vlv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rpe; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_LO); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_HI); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; return rpe; @@ -1415,7 +1415,7 @@ static int vlv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, PUNIT_REG_GPU_LFM) & 0xff; + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; /* * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on @@ -1451,15 +1451,15 @@ static bool vlv_rps_enable(struct intel_rps *rps) /* WaGsvRC0ResidencyMethod:vlv */ rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED; - vlv_punit_get(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); /* Setting Fixed Bias */ val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | VLV_BIAS_CPU_125_SOC_875; - vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -2107,9 +2107,9 @@ static u32 __read_cagf(struct intel_rps *rps, bool take_fw) } else if (GRAPHICS_VER(i915) >= 12) { r = GEN12_RPSTAT1; } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { - vlv_punit_get(i915); - freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + freq = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); } else if (GRAPHICS_VER(i915) >= 6) { r = GEN6_RPSTAT1; } else { diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 0b92ab4e9fb9b..e8d6bd116b446 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -98,7 +98,7 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) u32 val; vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); - val = vlv_cck_read(i915, CCK_FUSE_REG); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, CCK_FUSE_REG); vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); switch ((val >> 2) & 0x7) { @@ -114,7 +114,7 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) u32 val; vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); switch ((val >> 6) & 3) { -- GitLab From 8393253b850b6a5c62d4bb875b582e1582103db8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:56 +0300 Subject: [PATCH 036/902] drm/i915: move VLV IOSF SB unit specific helpers under display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all the VLV IOSF SB unit specific helper users are under display, relocate the helpers themselves under display as well. Resurrect the vlv_sideband.[ch] name for this. Make everything except DPIO helpers static inlines, as their implementations are trivial. All of this considerably simplifies the xe compat header. v2: Rebase Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/e86c2498c9f1c1d30f8e83fa5f1c23526b87b9ab.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../drm/i915/display/intel_display_power.c | 2 +- .../i915/display/intel_display_power_well.c | 2 +- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- drivers/gpu/drm/i915/display/vlv_sideband.c | 45 +++++ drivers/gpu/drm/i915/display/vlv_sideband.h | 156 ++++++++++++++++++ drivers/gpu/drm/i915/vlv_iosf_sb.c | 94 ----------- drivers/gpu/drm/i915/vlv_iosf_sb.h | 93 ----------- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 91 ---------- 16 files changed, 213 insertions(+), 289 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/vlv_sideband.c create mode 100644 drivers/gpu/drm/i915/display/vlv_sideband.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3e3e4f4bfa4e2..1a90eb1f180aa 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -296,7 +296,8 @@ i915-y += \ display/intel_wm.o \ display/skl_scaler.o \ display/skl_universal_plane.o \ - display/skl_watermark.o + display/skl_watermark.o \ + display/vlv_sideband.o i915-$(CONFIG_ACPI) += \ display/intel_acpi.o \ display/intel_opregion.o diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 02f33cbe6765c..77876ef735b74 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -16,7 +16,7 @@ #include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" struct intel_watermark_params { u16 fifo_size; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 501b794984149..b1718b491ffda 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -47,7 +47,7 @@ #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_dsi.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /** * DOC: CDCLK / RAWCLK diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c7a6b710b7c0a..704ca079980c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -131,7 +131,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index b3b05d7610e8a..16356523816fb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -27,7 +27,7 @@ #include "intel_snps_phy.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #define for_each_power_domain_well(__display, __power_well, __domain) \ for_each_power_well((__display), __power_well) \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 6772ac0c3f84c..0a3d302f9d1b1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -30,7 +30,7 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #include "vlv_iosf_sb_reg.h" struct i915_power_well_regs { diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 5b9c0852da2cf..69f2421394205 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -32,7 +32,7 @@ #include "intel_dp.h" #include "intel_dpio_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /** * DOC: DPIO diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 055dd2b4a9043..a9e9b98d0bf9c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -22,7 +22,7 @@ #include "intel_pps.h" #include "intel_snps_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" struct intel_dpll_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index dce4fdf091f67..29c9209834138 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -49,7 +49,7 @@ #include "intel_pps_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #define MIPI_TRANSFER_MODE_SHIFT 0 #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 110914bbc1348..346737f15fa93 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -49,7 +49,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /* return pixels in terms of txbyteclkhs */ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 79438cdfc3f9d..7ce924a5ef90b 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -34,7 +34,7 @@ #include "intel_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_pll_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" static const u16 lfsr_converts[] = { 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c new file mode 100644 index 0000000000000..f1caee32f6232 --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include "i915_drv.h" +#include "intel_dpio_phy.h" +#include "vlv_sideband.h" + +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, + enum dpio_phy phy) +{ + /* + * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) + * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) + */ + if (IS_CHERRYVIEW(i915)) + return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; + else + return VLV_IOSF_SB_DPIO; +} + +u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) +{ + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + u32 val; + + val = vlv_iosf_sb_read(i915, unit, reg); + + /* + * FIXME: There might be some registers where all 1's is a valid value, + * so ideally we should check the register offset instead... + */ + drm_WARN(&i915->drm, val == 0xffffffff, + "DPIO PHY%d read reg 0x%x == 0x%x\n", + phy, reg, val); + + return val; +} + +void vlv_dpio_write(struct drm_i915_private *i915, + enum dpio_phy phy, int reg, u32 val) +{ + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + + vlv_iosf_sb_write(i915, unit, reg, val); +} diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h new file mode 100644 index 0000000000000..beac69157d24b --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef _VLV_SIDEBAND_H_ +#define _VLV_SIDEBAND_H_ + +#include +#include + +#include "vlv_iosf_sb.h" +#include "vlv_iosf_sb_reg.h" + +enum dpio_phy; +struct drm_i915_private; + +static inline void vlv_bunit_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); +} + +static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); +} + +static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); +} + +static inline void vlv_bunit_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); +} + +static inline void vlv_cck_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); +} + +static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); +} + +static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); +} + +static inline void vlv_cck_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); +} + +static inline void vlv_ccu_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); +} + +static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); +} + +static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); +} + +static inline void vlv_ccu_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); +} + +static inline void vlv_dpio_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + +#ifdef I915 +u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); +void vlv_dpio_write(struct drm_i915_private *i915, + enum dpio_phy phy, int reg, u32 val); +#else +static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int phy, int reg) +{ + return 0; +} +static inline void vlv_dpio_write(struct drm_i915_private *i915, + int phy, int reg, u32 val) +{ +} +#endif + +static inline void vlv_dpio_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + +static inline void vlv_flisdsi_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); +} + +static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); +} + +static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); +} + +static inline void vlv_flisdsi_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); +} + +static inline void vlv_nc_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); +} + +static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); +} + +static inline void vlv_nc_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); +} + +static inline void vlv_punit_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); +} + +static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); +} + +static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) +{ + return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); +} + +static inline void vlv_punit_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); +} + +#endif /* _VLV_SIDEBAND_H_ */ diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index efb5ee39dbbb2..c6418d54dae9f 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -196,100 +196,6 @@ int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); } -u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); -} - -int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) -{ - return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); -} - -u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); -} - -void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); -} - -u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); -} - -u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); -} - -void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); -} - -u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); -} - -void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); -} - -static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, - enum dpio_phy phy) -{ - /* - * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) - * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) - */ - if (IS_CHERRYVIEW(i915)) - return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; - else - return VLV_IOSF_SB_DPIO; -} - -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) -{ - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - u32 val; - - val = vlv_iosf_sb_read(i915, unit, reg); - - /* - * FIXME: There might be some registers where all 1's is a valid value, - * so ideally we should check the register offset instead... - */ - drm_WARN(&i915->drm, val == 0xffffffff, - "DPIO PHY%d read reg 0x%x == 0x%x\n", - phy, reg, val); - - return val; -} - -void vlv_dpio_write(struct drm_i915_private *i915, - enum dpio_phy phy, int reg, u32 val) -{ - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - - vlv_iosf_sb_write(i915, unit, reg, val); -} - -u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); -} - -void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); -} - void vlv_iosf_sb_init(struct drm_i915_private *i915) { if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 66f8918d49743..f4fb7213fe377 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -6,12 +6,10 @@ #ifndef _VLV_IOSF_SB_H_ #define _VLV_IOSF_SB_H_ -#include #include #include "vlv_iosf_sb_reg.h" -enum dpio_phy; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -35,95 +33,4 @@ void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); -static inline void vlv_bunit_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); -} - -u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg); -void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_bunit_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); -} - -static inline void vlv_cck_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); -} - -u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg); -void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_cck_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); -} - -static inline void vlv_ccu_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); -} - -u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg); -void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_ccu_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); -} - -static inline void vlv_dpio_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} - -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_i915_private *i915, - enum dpio_phy phy, int reg, u32 val); - -static inline void vlv_dpio_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} - -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); -} - -u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg); -void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); -} - -static inline void vlv_nc_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); -} - -u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr); - -static inline void vlv_nc_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); -} - -static inline void vlv_punit_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); -} - -u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr); -int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val); - -static inline void vlv_punit_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); -} - #endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index 57f7dde90ced8..e34d9c72a587f 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -10,7 +10,6 @@ #include "vlv_iosf_sb_reg.h" -enum pipe; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -39,95 +38,5 @@ static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) { } -static inline void vlv_bunit_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_bunit_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_cck_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_cck_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_ccu_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_ccu_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_dpio_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int pipe, int reg) -{ - return 0; -} -static inline void vlv_dpio_write(struct drm_i915_private *i915, - int pipe, int reg, u32 val) -{ -} -static inline void vlv_dpio_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_nc_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) -{ - return 0; -} -static inline void vlv_nc_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_punit_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) -{ - return 0; -} -static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) -{ - return 0; -} -static inline void vlv_punit_put(struct drm_i915_private *i915) -{ -} #endif /* _VLV_IOSF_SB_H_ */ -- GitLab From bd4d1856f5fe427ad20d54c57bd0f2724f7be47e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:57 +0300 Subject: [PATCH 037/902] drm/i915: convert VLV IOSF SB interface to struct drm_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With users both in i915 core and display, struct drm_device is the common denominator for the VLV IOSF SB users. Also use drm_device for the helpers on the display side to keep the static inlines as simple as possible. We can drop a number of dependencies on i915_drv.h with this. v2,v3: Rebase Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/c1d013ed88ce2e3e5bdc15ce3bf01a3960b1e817.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 35 ++- drivers/gpu/drm/i915/display/intel_cdclk.c | 47 ++--- drivers/gpu/drm/i915/display/intel_display.c | 23 +- drivers/gpu/drm/i915/display/intel_display.h | 7 +- .../drm/i915/display/intel_display_power.c | 7 +- .../i915/display/intel_display_power_well.c | 69 +++--- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 199 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll.c | 135 ++++++------ drivers/gpu/drm/i915/display/vlv_dsi.c | 26 ++- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 46 ++-- drivers/gpu/drm/i915/display/vlv_sideband.c | 25 ++- drivers/gpu/drm/i915/display/vlv_sideband.h | 110 +++++----- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 6 +- drivers/gpu/drm/i915/gt/intel_rps.c | 56 ++--- drivers/gpu/drm/i915/soc/intel_dram.c | 12 +- drivers/gpu/drm/i915/vlv_iosf_sb.c | 14 +- drivers/gpu/drm/i915/vlv_iosf_sb.h | 9 +- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 10 +- 18 files changed, 410 insertions(+), 426 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 77876ef735b74..8e4e938f1ee5e 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -107,43 +107,41 @@ static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *dis static void chv_set_memory_dvfs(struct intel_display *display, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); if (enable) val &= ~FORCE_DDR_HIGH_FREQ; else val |= FORCE_DDR_HIGH_FREQ; val &= ~FORCE_DDR_LOW_FREQ; val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) & + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) & FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) drm_err(display->drm, "timed out waiting for Punit DDR DVFS request\n"); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void chv_set_memory_pm5(struct intel_display *display, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); if (enable) val |= DSP_MAXFIFO_PM5_ENABLE; else val &= ~DSP_MAXFIFO_PM5_ENABLE; - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } #define FW_WM(value, plane) \ @@ -3900,7 +3898,6 @@ static void g4x_wm_sanitize(struct intel_display *display) static void vlv_wm_get_hw_state(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct vlv_wm_values *wm = &display->wm.vlv; struct intel_crtc *crtc; u32 val; @@ -3911,9 +3908,9 @@ static void vlv_wm_get_hw_state(struct intel_display *display) wm->level = VLV_WM_LEVEL_PM2; if (display->platform.cherryview) { - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); if (val & DSP_MAXFIFO_PM5_ENABLE) wm->level = VLV_WM_LEVEL_PM5; @@ -3926,23 +3923,23 @@ static void vlv_wm_get_hw_state(struct intel_display *display) * HIGH/LOW bits so that we don't actually change * the current state. */ - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) & + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) & FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) { drm_dbg_kms(display->drm, "Punit not acking DDR DVFS request, " "assuming DDR DVFS is disabled\n"); display->wm.num_levels = VLV_WM_LEVEL_PM5 + 1; } else { - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); if ((val & FORCE_DDR_HIGH_FREQ) == 0) wm->level = VLV_WM_LEVEL_DDR_DVFS; } - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } for_each_intel_crtc(display->drm, crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b1718b491ffda..f0c673e40ce55 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -567,20 +567,18 @@ static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk) static void vlv_get_cdclk(struct intel_display *display, struct intel_cdclk_config *cdclk_config) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_iosf_sb_get(dev_priv, - BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); - cdclk_config->vco = vlv_get_hpll_vco(dev_priv); - cdclk_config->cdclk = vlv_get_cck_clock(dev_priv, "cdclk", + cdclk_config->vco = vlv_get_hpll_vco(display->drm); + cdclk_config->cdclk = vlv_get_cck_clock(display->drm, "cdclk", CCK_DISPLAY_CLOCK_CONTROL, cdclk_config->vco); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); - vlv_iosf_sb_put(dev_priv, + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); if (display->platform.valleyview) @@ -658,16 +656,16 @@ static void vlv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_iosf_sb_get(dev_priv, + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_BUNIT) | BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK; val |= (cmd << DSPFREQGUAR_SHIFT); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), 50)) { drm_err(display->drm, @@ -681,12 +679,12 @@ static void vlv_set_cdclk(struct intel_display *display, cdclk) - 1; /* adjust cdclk divider */ - val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL); val &= ~CCK_FREQUENCY_VALUES; val |= divider; - vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val); + vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val); - if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) & + if (wait_for((vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL) & CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT), 50)) drm_err(display->drm, @@ -694,7 +692,7 @@ static void vlv_set_cdclk(struct intel_display *display, } /* adjust self-refresh exit latency value */ - val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC); + val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC); val &= ~0x7f; /* @@ -705,9 +703,9 @@ static void vlv_set_cdclk(struct intel_display *display, val |= 4500 / 250; /* 4.5 usec */ else val |= 3000 / 250; /* 3.0 usec */ - vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); + vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val); - vlv_iosf_sb_put(dev_priv, + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_BUNIT) | BIT(VLV_IOSF_SB_PUNIT)); @@ -723,7 +721,6 @@ static void chv_set_cdclk(struct intel_display *display, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int cdclk = cdclk_config->cdclk; u32 val, cmd = cdclk_config->voltage_level; intel_wakeref_t wakeref; @@ -747,19 +744,19 @@ static void chv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_punit_get(dev_priv); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + vlv_punit_get(display->drm); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK_CHV; val |= (cmd << DSPFREQGUAR_SHIFT_CHV); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV), 50)) { drm_err(display->drm, "timed out waiting for CDclk change\n"); } - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); intel_update_cdclk(display); @@ -3528,10 +3525,8 @@ static int pch_rawclk(struct intel_display *display) static int vlv_hrawclk(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - /* RAWCLK_FREQ_VLV register updated from power well code */ - return vlv_get_cck_clock_hpll(dev_priv, "hrawclk", + return vlv_get_cck_clock_hpll(display->drm, "hrawclk", CCK_DISPLAY_REF_CLOCK_CONTROL); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 704ca079980c2..e0928f28d7116 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -140,46 +140,47 @@ static void bdw_set_pipe_misc(struct intel_dsb *dsb, const struct intel_crtc_state *crtc_state); /* returns HPLL frequency in kHz */ -int vlv_get_hpll_vco(struct drm_i915_private *dev_priv) +int vlv_get_hpll_vco(struct drm_device *drm) { int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; /* Obtain SKU information */ - hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) & + hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; return vco_freq[hpll_freq] * 1000; } -int vlv_get_cck_clock(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock(struct drm_device *drm, const char *name, u32 reg, int ref_freq) { u32 val; int divider; - val = vlv_cck_read(dev_priv, reg); + val = vlv_cck_read(drm, reg); divider = val & CCK_FREQUENCY_VALUES; - drm_WARN(&dev_priv->drm, (val & CCK_FREQUENCY_STATUS) != + drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) != (divider << CCK_FREQUENCY_STATUS_SHIFT), "%s change in progress\n", name); return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1); } -int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock_hpll(struct drm_device *drm, const char *name, u32 reg) { + struct drm_i915_private *dev_priv = to_i915(drm); int hpll; - vlv_cck_get(dev_priv); + vlv_cck_get(drm); if (dev_priv->hpll_freq == 0) - dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv); + dev_priv->hpll_freq = vlv_get_hpll_vco(drm); - hpll = vlv_get_cck_clock(dev_priv, name, reg, dev_priv->hpll_freq); + hpll = vlv_get_cck_clock(drm, name, reg, dev_priv->hpll_freq); - vlv_cck_put(dev_priv); + vlv_cck_put(drm); return hpll; } @@ -191,7 +192,7 @@ void intel_update_czclk(struct intel_display *display) if (!display->platform.valleyview && !display->platform.cherryview) return; - dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk", + dev_priv->czclk_freq = vlv_get_cck_clock_hpll(display->drm, "czclk", CCK_CZ_CLOCK_CONTROL); drm_dbg_kms(display->drm, "CZ clock rate: %d kHz\n", dev_priv->czclk_freq); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index b6610e9175a7a..fa857c0e03c70 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -40,7 +40,6 @@ struct drm_encoder; struct drm_file; struct drm_format_info; struct drm_framebuffer; -struct drm_i915_private; struct drm_mode_fb_cmd2; struct drm_modeset_acquire_ctx; struct drm_plane; @@ -452,10 +451,10 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state); void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct intel_display *display, enum pipe pipe); void i830_disable_pipe(struct intel_display *display, enum pipe pipe); -int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); -int vlv_get_cck_clock(struct drm_i915_private *dev_priv, +int vlv_get_hpll_vco(struct drm_device *drm); +int vlv_get_cck_clock(struct drm_device *drm, const char *name, u32 reg, int ref_freq); -int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock_hpll(struct drm_device *drm, const char *name, u32 reg); bool intel_has_pending_fb_unpin(struct intel_display *display); void intel_encoder_destroy(struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 16356523816fb..d7f5d3dbb8a10 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1883,12 +1883,11 @@ static void vlv_cmnlane_wa(struct intel_display *display) static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0) { - struct drm_i915_private *dev_priv = to_i915(display->drm); bool ret; - vlv_punit_get(dev_priv); - ret = (vlv_punit_read(dev_priv, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; - vlv_punit_put(dev_priv); + vlv_punit_get(display->drm); + ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; + vlv_punit_put(display->drm); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 0a3d302f9d1b1..02e3c22be21e0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -809,7 +809,6 @@ static void tgl_disable_dc3co(struct intel_display *display) static void assert_can_enable_dc5(struct intel_display *display) { - struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm); enum i915_power_well_id high_pg; /* Power wells at this level and above must be disabled for DC5 entry */ @@ -1102,7 +1101,6 @@ static void i830_pipes_power_well_sync_hw(struct intel_display *display, static void vlv_set_power_well(struct intel_display *display, struct i915_power_well *power_well, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int pw_idx = i915_power_well_instance(power_well)->vlv.idx; u32 mask; u32 state; @@ -1112,29 +1110,29 @@ static void vlv_set_power_well(struct intel_display *display, state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) : PUNIT_PWRGT_PWR_GATE(pw_idx); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); #define COND \ - ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state) + ((vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask) == state) if (COND) goto out; - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL); ctrl &= ~mask; ctrl |= state; - vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl); + vlv_punit_write(display->drm, PUNIT_REG_PWRGT_CTRL, ctrl); if (wait_for(COND, 100)) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL)); + vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL)); #undef COND out: - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void vlv_power_well_enable(struct intel_display *display, @@ -1152,7 +1150,6 @@ static void vlv_power_well_disable(struct intel_display *display, static bool vlv_power_well_enabled(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int pw_idx = i915_power_well_instance(power_well)->vlv.idx; bool enabled = false; u32 mask; @@ -1162,9 +1159,9 @@ static bool vlv_power_well_enabled(struct intel_display *display, mask = PUNIT_PWRGT_MASK(pw_idx); ctrl = PUNIT_PWRGT_PWR_ON(pw_idx); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask; + state = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask; /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1178,10 +1175,10 @@ static bool vlv_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask; + ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL) & mask; drm_WARN_ON(display->drm, ctrl != state); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); return enabled; } @@ -1437,7 +1434,6 @@ static void assert_chv_phy_status(struct intel_display *display) static void chv_dpio_cmn_power_well_enable(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum i915_power_well_id id = i915_power_well_instance(power_well)->id; enum dpio_phy phy; u32 tmp; @@ -1461,30 +1457,30 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display, drm_err(display->drm, "Display PHY %d is not power up\n", phy); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable dynamic power down */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW28); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW28); tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN | DPIO_SUS_CLK_CONFIG_GATE_CLKREQ; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW28, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW28, tmp); if (id == VLV_DISP_PW_DPIO_CMN_BC) { - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW6_CH1); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW6_CH1); tmp |= DPIO_DYNPWRDOWNEN_CH1; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW6_CH1, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW6_CH1, tmp); } else { /* * Force the non-existing CL2 off. BXT does this * too, so maybe it saves some power even though * CL2 doesn't exist? */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW30); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW30); tmp |= DPIO_CL2_LDOFUSE_PWRENB; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW30, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW30, tmp); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy); intel_de_write(display, DISPLAY_PHY_CONTROL, @@ -1535,7 +1531,6 @@ static void chv_dpio_cmn_power_well_disable(struct intel_display *display, static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_phy phy, enum dpio_channel ch, bool override, unsigned int mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 reg, val, expected, actual; /* @@ -1553,9 +1548,9 @@ static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_ph else reg = CHV_CMN_DW6_CH1; - vlv_dpio_get(dev_priv); - val = vlv_dpio_read(dev_priv, phy, reg); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + val = vlv_dpio_read(display->drm, phy, reg); + vlv_dpio_put(display->drm); /* * This assumes !override is only used when the port is disabled. @@ -1665,14 +1660,13 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, static bool chv_pipe_power_well_enabled(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe = PIPE_A; bool enabled; u32 state, ctrl; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - state = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); + state = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1685,10 +1679,10 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); drm_WARN_ON(display->drm, ctrl << 16 != state); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); return enabled; } @@ -1697,36 +1691,35 @@ static void chv_set_pipe_power_well(struct intel_display *display, struct i915_power_well *power_well, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe = PIPE_A; u32 state; u32 ctrl; state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); #define COND \ - ((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state) + ((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state) if (COND) goto out; - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); ctrl &= ~DP_SSC_MASK(pipe); ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, ctrl); + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, ctrl); if (wait_for(COND, 100)) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM)); + vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM)); #undef COND out: - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void chv_pipe_power_well_sync_hw(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 69f2421394205..552dd984ade95 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -21,9 +21,11 @@ * DEALINGS IN THE SOFTWARE. */ +#include + #include "bxt_dpio_phy_regs.h" -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_utils.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" @@ -715,53 +717,53 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, u32 deemph_reg_value, u32 margin_reg_value, bool uniq_trans_scale) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; int i; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Clear calc init */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); } - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW9(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW9(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW9(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW9(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW9(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW9(ch), val); } /* Program swing deemph */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW4(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW4(ch, i)); val &= ~DPIO_SWING_DEEMPH9P5_MASK; val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value); - vlv_dpio_write(dev_priv, phy, CHV_TX_DW4(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW4(ch, i), val); } /* Program swing margin */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW2(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW2(ch, i)); val &= ~DPIO_SWING_MARGIN000_MASK; val |= DPIO_SWING_MARGIN000(margin_reg_value); @@ -774,7 +776,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, val &= ~DPIO_UNIQ_TRANS_SCALE_MASK; val |= DPIO_UNIQ_TRANS_SCALE(0x9a); - vlv_dpio_write(dev_priv, phy, CHV_TX_DW2(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW2(ch, i), val); } /* @@ -784,70 +786,70 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, * 27 for ch0 and ch1. */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW3(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW3(ch, i)); if (uniq_trans_scale) val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; else val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; - vlv_dpio_write(dev_priv, phy, CHV_TX_DW3(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW3(ch, i), val); } /* Start swing calculation */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void __chv_data_lane_soft_reset(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, bool reset) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW0(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW0(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW0(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW0(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW0(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW0(ch), val); } - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW1(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW1(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW1(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW1(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW1(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW1(ch), val); } } @@ -855,11 +857,11 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, bool reset) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); - vlv_dpio_get(i915); + vlv_dpio_get(display->drm); __chv_data_lane_soft_reset(encoder, crtc_state, reset); - vlv_dpio_put(i915); + vlv_dpio_put(display->drm); } void chv_phy_pre_pll_enable(struct intel_encoder *encoder, @@ -867,7 +869,6 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); @@ -886,47 +887,47 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, chv_phy_powergate_lanes(encoder, true, lane_mask); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Assert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, true); /* program left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA1_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA1_FORCE; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA2_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA2_FORCE; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); } /* program clock channel usage */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW8(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW8(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW8(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW8(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW8(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW8(ch), val); } /* @@ -934,38 +935,38 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, * matches the pipe, but here we need to * pick the CL based on the port. */ - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW19(ch)); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW19(ch)); if (pipe == PIPE_B) val |= CHV_CMN_USEDCLKCHANNEL; else val &= ~CHV_CMN_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW19(ch), val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW19(ch), val); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); int data, i, stagger; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* allow hardware to manage TX FIFO reset source */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); } /* Program Tx lane latency optimal setting*/ @@ -975,7 +976,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, data = 0; else data = (i == 1) ? 0 : DPIO_UPAR; - vlv_dpio_write(dev_priv, phy, CHV_TX_DW14(ch, i), data); + vlv_dpio_write(display->drm, phy, CHV_TX_DW14(ch, i), data); } /* Data lane stagger programming */ @@ -990,17 +991,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, else stagger = 0x2; - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); } - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW12(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1008,7 +1009,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, DPIO_TX2_STAGGER_MULT(0)); if (crtc_state->lane_count > 2) { - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW12(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1019,7 +1020,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, /* Deassert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, false); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void chv_phy_release_cl2_override(struct intel_encoder *encoder) @@ -1036,25 +1037,25 @@ void chv_phy_release_cl2_override(struct intel_encoder *encoder) void chv_phy_post_pll_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder)); enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* disable left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); /* * Leave the power down bit cleared for at least one @@ -1073,97 +1074,97 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, u32 demph_reg_value, u32 preemph_reg_value, u32 uniqtranscale_reg_value, u32 tx3_demph) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW2_GRP(ch), - uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); + vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), 0x00000000); + vlv_dpio_write(display->drm, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW2_GRP(ch), + uniqtranscale_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); if (tx3_demph) - vlv_dpio_write(dev_priv, phy, VLV_TX_DW4(ch, 3), tx3_demph); + vlv_dpio_write(display->drm, phy, VLV_TX_DW4(ch, 3), tx3_demph); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); /* Program Tx lane resets to default */ - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | DPIO_PCS_CLK_DATAWIDTH_8_10 | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW11_GRP(ch), 0x00001500); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW14_GRP(ch), 0x40400000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); + vlv_dpio_write(display->drm, phy, VLV_TX_DW11_GRP(ch), 0x00001500); + vlv_dpio_write(display->drm, phy, VLV_TX_DW14_GRP(ch), 0x40400000); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); enum pipe pipe = crtc->pipe; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable clock channels for this port */ val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; val |= 0xc4; - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW8_GRP(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW8_GRP(ch), val); /* Program lane clock */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_reset_lanes(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(dev_priv); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); + vlv_dpio_put(display->drm); } void vlv_wait_port_ready(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a9e9b98d0bf9c..dd7a29c10b5d8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -6,7 +6,8 @@ #include #include -#include "i915_drv.h" +#include + #include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" @@ -513,8 +514,8 @@ void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state) void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; @@ -526,9 +527,9 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(dev_priv); - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW3(ch)); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW3(ch)); + vlv_dpio_put(display->drm); clock.m1 = REG_FIELD_GET(DPIO_M1_DIV_MASK, tmp); clock.m2 = REG_FIELD_GET(DPIO_M2_DIV_MASK, tmp); @@ -541,8 +542,8 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; @@ -554,13 +555,13 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(dev_priv); - cmn_dw13 = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW13(ch)); - pll_dw0 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW0(ch)); - pll_dw1 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW1(ch)); - pll_dw2 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW2(ch)); - pll_dw3 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch)); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + cmn_dw13 = vlv_dpio_read(display->drm, phy, CHV_CMN_DW13(ch)); + pll_dw0 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW0(ch)); + pll_dw1 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW1(ch)); + pll_dw2 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW2(ch)); + pll_dw3 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); + vlv_dpio_put(display->drm); clock.m1 = REG_FIELD_GET(DPIO_CHV_M1_DIV_MASK, pll_dw1) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; clock.m2 = REG_FIELD_GET(DPIO_CHV_M2_DIV_MASK, pll_dw0) << 22; @@ -1871,45 +1872,43 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state) static void vlv_pllb_recal_opamp(struct intel_display *display, enum dpio_phy phy, enum dpio_channel ch) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; /* * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; tmp |= 0x00000030; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0x8c000000; - vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0xb0000000; - vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); } static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct dpll *clock = &crtc_state->dpll; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); enum pipe pipe = crtc->pipe; u32 tmp, coreclk; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* See eDP HDMI DPIO driver vbios notes doc */ @@ -1918,15 +1917,15 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) vlv_pllb_recal_opamp(display, phy, ch); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW17_BCAST, 0x0100000f); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW17_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW16(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW16(ch)); tmp &= 0x00ffffff; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW16(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW16(ch), tmp); /* Disable fast lock */ - vlv_dpio_write(dev_priv, phy, VLV_CMN_DW0, 0x610); + vlv_dpio_write(display->drm, phy, VLV_CMN_DW0, 0x610); /* Set idtafcrecal before PLL is enabled */ tmp = DPIO_M1_DIV(clock->m1) | @@ -1942,48 +1941,42 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) * Note: don't use the DAC post divider as it seems unstable. */ tmp |= DPIO_S1_DIV(DPIO_S1_DIV_HDMIDP); - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); tmp |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); /* Set HBR and RBR LPF coefficients */ if (crtc_state->port_clock == 162000 || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG) || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch), - 0x009f0003); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x009f0003); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch), - 0x00d0000f); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x00d0000f); if (intel_crtc_has_dp_encoder(crtc_state)) { /* Use SSC source */ if (pipe == PIPE_A) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df40000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df70000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (pipe == PIPE_A) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df70000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df40000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); } - coreclk = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW7(ch)); + coreclk = vlv_dpio_read(display->drm, phy, VLV_PLL_DW7(ch)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_crtc_has_dp_encoder(crtc_state)) coreclk |= 0x01000000; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW7(ch), coreclk); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW7(ch), coreclk); - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW19(ch), 0x87871000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW19(ch), 0x87871000); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state) @@ -2028,8 +2021,8 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct dpll *clock = &crtc_state->dpll; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); @@ -2038,44 +2031,44 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) m2_frac = clock->m2 & 0x3fffff; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* p1 and p2 divider */ - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW13(ch), + vlv_dpio_write(display->drm, phy, CHV_CMN_DW13(ch), DPIO_CHV_S1_DIV(5) | DPIO_CHV_P1_DIV(clock->p1) | DPIO_CHV_P2_DIV(clock->p2) | DPIO_CHV_K_DIV(1)); /* Feedback post-divider - m2 */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW0(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW0(ch), DPIO_CHV_M2_DIV(clock->m2 >> 22)); /* Feedback refclk divider - n and m1 */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW1(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW1(ch), DPIO_CHV_M1_DIV(DPIO_CHV_M1_DIV_BY_2) | DPIO_CHV_N_DIV(1)); /* M2 fraction division */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW2(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW2(ch), DPIO_CHV_M2_FRAC_DIV(m2_frac)); /* M2 fraction division enable */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); tmp &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN); tmp |= DPIO_CHV_FEEDFWD_GAIN(2); if (m2_frac) tmp |= DPIO_CHV_FRAC_DIV_EN; - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW3(ch), tmp); /* Program digital lock detect threshold */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW9(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW9(ch)); tmp &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK | DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE); tmp |= DPIO_CHV_INT_LOCK_THRESHOLD(0x5); if (!m2_frac) tmp |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE; - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW9(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW9(ch), tmp); /* Loop filter */ if (clock->vco == 5400000) { @@ -2100,40 +2093,39 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) DPIO_CHV_GAIN_CTRL(0x3); tribuf_calcntr = 0; } - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW6(ch), loopfilter); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW6(ch), loopfilter); - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW8(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW8(ch)); tmp &= ~DPIO_CHV_TDC_TARGET_CNT_MASK; tmp |= DPIO_CHV_TDC_TARGET_CNT(tribuf_calcntr); - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW8(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW8(ch), tmp); /* AFC Recal */ - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), - vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)) | + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), + vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)) | DPIO_AFC_RECAL); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); enum pipe pipe = crtc->pipe; u32 tmp; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable back the 10bit clock to display controller */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); tmp |= DPIO_DCLKP_EN; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), tmp); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); /* * Need to wait > 100ns between dclkp clock enable bit and PLL enable. @@ -2252,7 +2244,6 @@ void vlv_disable_pll(struct intel_display *display, enum pipe pipe) void chv_disable_pll(struct intel_display *display, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum dpio_channel ch = vlv_pipe_to_channel(pipe); enum dpio_phy phy = vlv_pipe_to_phy(pipe); u32 val; @@ -2268,14 +2259,14 @@ void chv_disable_pll(struct intel_display *display, enum pipe pipe) intel_de_write(display, DPLL(display, pipe), val); intel_de_posting_read(display, DPLL(display, pipe)); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Disable 10bit clock to display controller */ - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); val &= ~DPIO_DCLKP_EN; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), val); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 346737f15fa93..5eb81f1d2f977 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -30,10 +30,11 @@ #include #include #include +#include #include -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_utils.h" #include "intel_atomic.h" #include "intel_backlight.h" #include "intel_connector.h" @@ -253,18 +254,16 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, static void band_gap_reset(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); + vlv_flisdsi_get(display->drm); - vlv_flisdsi_get(dev_priv); - - vlv_flisdsi_write(dev_priv, 0x08, 0x0001); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0005); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0025); + vlv_flisdsi_write(display->drm, 0x08, 0x0001); + vlv_flisdsi_write(display->drm, 0x0F, 0x0005); + vlv_flisdsi_write(display->drm, 0x0F, 0x0025); udelay(150); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0000); - vlv_flisdsi_write(dev_priv, 0x08, 0x0000); + vlv_flisdsi_write(display->drm, 0x0F, 0x0000); + vlv_flisdsi_write(display->drm, 0x08, 0x0000); - vlv_flisdsi_put(dev_priv); + vlv_flisdsi_put(display->drm); } static int intel_dsi_compute_config(struct intel_encoder *encoder, @@ -457,17 +456,16 @@ static void bxt_dsi_device_ready(struct intel_encoder *encoder) static void vlv_dsi_device_ready(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; drm_dbg_kms(display->drm, "\n"); - vlv_flisdsi_get(dev_priv); + vlv_flisdsi_get(display->drm); /* program rcomp for compliance, reduce from 50 ohms to 45 ohms * needed everytime after power gate */ - vlv_flisdsi_write(dev_priv, 0x04, 0x0004); - vlv_flisdsi_put(dev_priv); + vlv_flisdsi_write(display->drm, 0x04, 0x0004); + vlv_flisdsi_put(display->drm); /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(display); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 7ce924a5ef90b..d42b61e6f0764 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -28,7 +28,9 @@ #include #include -#include "i915_drv.h" +#include + +#include "i915_utils.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsi.h" @@ -214,15 +216,14 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *config) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); + vlv_cck_get(display->drm); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, 0); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN); /* wait at least 0.5 us after ungating before enabling VCO, @@ -230,16 +231,16 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, */ usleep_range(10, 50); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); - if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) & + if (wait_for(vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_LOCK, 20)) { - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); drm_err(display->drm, "DSI PLL lock failed\n"); return; } - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); drm_dbg_kms(display->drm, "DSI PLL locked\n"); } @@ -247,19 +248,18 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, void vlv_dsi_pll_disable(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 tmp; drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); + vlv_cck_get(display->drm); - tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); + tmp = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); tmp &= ~DSI_PLL_VCO_EN; tmp |= DSI_PLL_LDO_GATE; - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, tmp); - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); } bool bxt_dsi_pll_is_enabled(struct intel_display *display) @@ -323,15 +323,14 @@ u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, struct intel_crtc_state *config) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 pll_ctl, pll_div; drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); - pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); - vlv_cck_put(dev_priv); + vlv_cck_get(display->drm); + pll_ctl = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); + pll_div = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_DIVIDER); + vlv_cck_put(display->drm); config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK; config->dsi_pll.div = pll_div; @@ -592,12 +591,11 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) static void assert_dsi_pll(struct intel_display *display, bool state) { - struct drm_i915_private *i915 = to_i915(display->drm); bool cur_state; - vlv_cck_get(i915); - cur_state = vlv_cck_read(i915, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; - vlv_cck_put(i915); + vlv_cck_get(display->drm); + cur_state = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; + vlv_cck_put(display->drm); INTEL_DISPLAY_STATE_WARN(display, cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c index f1caee32f6232..e18045f2b89d2 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.c +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -1,45 +1,50 @@ // SPDX-License-Identifier: MIT /* Copyright © 2025 Intel Corporation */ -#include "i915_drv.h" +#include + +#include "intel_display_core.h" +#include "intel_display_types.h" #include "intel_dpio_phy.h" #include "vlv_sideband.h" -static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, enum dpio_phy phy) { /* * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) */ - if (IS_CHERRYVIEW(i915)) + if (display->platform.cherryview) return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; else return VLV_IOSF_SB_DPIO; } -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) +u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg) { - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + struct intel_display *display = to_intel_display(drm); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); u32 val; - val = vlv_iosf_sb_read(i915, unit, reg); + val = vlv_iosf_sb_read(drm, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, * so ideally we should check the register offset instead... */ - drm_WARN(&i915->drm, val == 0xffffffff, + drm_WARN(display->drm, val == 0xffffffff, "DPIO PHY%d read reg 0x%x == 0x%x\n", phy, reg, val); return val; } -void vlv_dpio_write(struct drm_i915_private *i915, +void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val) { - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + struct intel_display *display = to_intel_display(drm); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); - vlv_iosf_sb_write(i915, unit, reg, val); + vlv_iosf_sb_write(drm, unit, reg, val); } diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h index beac69157d24b..2c240d81fead6 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.h +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -11,146 +11,146 @@ #include "vlv_iosf_sb_reg.h" enum dpio_phy; -struct drm_i915_private; +struct drm_device; -static inline void vlv_bunit_get(struct drm_i915_private *i915) +static inline void vlv_bunit_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT)); } -static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_bunit_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg); } -static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val); } -static inline void vlv_bunit_put(struct drm_i915_private *i915) +static inline void vlv_bunit_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT)); } -static inline void vlv_cck_get(struct drm_i915_private *i915) +static inline void vlv_cck_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK)); } -static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_cck_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg); } -static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val); } -static inline void vlv_cck_put(struct drm_i915_private *i915) +static inline void vlv_cck_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK)); } -static inline void vlv_ccu_get(struct drm_i915_private *i915) +static inline void vlv_ccu_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU)); } -static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_ccu_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg); } -static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val); } -static inline void vlv_ccu_put(struct drm_i915_private *i915) +static inline void vlv_ccu_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU)); } -static inline void vlv_dpio_get(struct drm_i915_private *i915) +static inline void vlv_dpio_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } #ifdef I915 -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_i915_private *i915, +u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg); +void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val); #else -static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int phy, int reg) +static inline u32 vlv_dpio_read(struct drm_device *drm, int phy, int reg) { return 0; } -static inline void vlv_dpio_write(struct drm_i915_private *i915, +static inline void vlv_dpio_write(struct drm_device *drm, int phy, int reg, u32 val) { } #endif -static inline void vlv_dpio_put(struct drm_i915_private *i915) +static inline void vlv_dpio_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) +static inline void vlv_flisdsi_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI)); } -static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg); } -static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val); } -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) +static inline void vlv_flisdsi_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI)); } -static inline void vlv_nc_get(struct drm_i915_private *i915) +static inline void vlv_nc_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC)); } -static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) +static inline u32 vlv_nc_read(struct drm_device *drm, u8 addr) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr); } -static inline void vlv_nc_put(struct drm_i915_private *i915) +static inline void vlv_nc_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC)); } -static inline void vlv_punit_get(struct drm_i915_private *i915) +static inline void vlv_punit_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT)); } -static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) +static inline u32 vlv_punit_read(struct drm_device *drm, u32 addr) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr); } -static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) +static inline int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val) { - return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); + return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val); } -static inline void vlv_punit_put(struct drm_i915_private *i915) +static inline void vlv_punit_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT)); } #endif /* _VLV_SIDEBAND_H_ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index a059c6488b3db..87ef85483baec 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -366,9 +366,9 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) drm_printf(p, "SW control enabled: %s\n", str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - freq_sts = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + freq_sts = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); drm_printf(p, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 37487d2f121dc..5db3a0e24b226 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -820,9 +820,9 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) struct drm_i915_private *i915 = rps_to_i915(rps); int err; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - err = vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + err = vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d\n", val, intel_gpu_freq(rps, val)); @@ -1268,7 +1268,7 @@ static int chv_rps_max_freq(struct intel_rps *rps) struct intel_gt *gt = rps_to_gt(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); switch (gt->info.sseu.eu_total) { case 8: @@ -1295,7 +1295,7 @@ static int chv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); val >>= PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT; return val & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK; @@ -1306,7 +1306,7 @@ static int chv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); return val & FB_GFX_FREQ_FUSE_MASK; } @@ -1316,7 +1316,7 @@ static u32 chv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); val >>= FB_GFX_FMIN_AT_VMIN_FUSE_SHIFT; return val & FB_GFX_FREQ_FUSE_MASK; @@ -1350,14 +1350,14 @@ static bool chv_rps_enable(struct intel_rps *rps) GEN6_PM_RP_DOWN_TIMEOUT); /* Setting Fixed Bias */ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | CHV_BIAS_CPU_50_SOC_50; - vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1375,7 +1375,7 @@ static int vlv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp1; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp1 = val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK; rp1 >>= FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT; @@ -1388,7 +1388,7 @@ static int vlv_rps_max_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp0; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; /* Clamp to max */ @@ -1402,9 +1402,9 @@ static int vlv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rpe; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; return rpe; @@ -1415,7 +1415,7 @@ static int vlv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; /* * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on @@ -1451,15 +1451,15 @@ static bool vlv_rps_enable(struct intel_rps *rps) /* WaGsvRC0ResidencyMethod:vlv */ rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* Setting Fixed Bias */ val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | VLV_BIAS_CPU_125_SOC_875; - vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1672,7 +1672,7 @@ static void vlv_init_gpll_ref_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); rps->gpll_ref_freq = - vlv_get_cck_clock(i915, "GPLL ref", + vlv_get_cck_clock(&i915->drm, "GPLL ref", CCK_GPLL_CLOCK_CONTROL, i915->czclk_freq); @@ -1684,7 +1684,7 @@ static void vlv_rps_init(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - vlv_iosf_sb_get(i915, + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1708,7 +1708,7 @@ static void vlv_rps_init(struct intel_rps *rps) drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n", intel_gpu_freq(rps, rps->min_freq), rps->min_freq); - vlv_iosf_sb_put(i915, + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1718,7 +1718,7 @@ static void chv_rps_init(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - vlv_iosf_sb_get(i915, + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1742,7 +1742,7 @@ static void chv_rps_init(struct intel_rps *rps) drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n", intel_gpu_freq(rps, rps->min_freq), rps->min_freq); - vlv_iosf_sb_put(i915, + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -2107,9 +2107,9 @@ static u32 __read_cagf(struct intel_rps *rps, bool take_fw) } else if (GRAPHICS_VER(i915) >= 12) { r = GEN12_RPSTAT1; } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - freq = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + freq = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); } else if (GRAPHICS_VER(i915) >= 6) { r = GEN6_RPSTAT1; } else { diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index e8d6bd116b446..efee955ae8a3d 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -97,9 +97,9 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) { u32 val; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); switch ((val >> 2) & 0x7) { case 3: @@ -113,9 +113,9 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) { u32 val; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); switch ((val >> 6) & 3) { case 0: diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index c6418d54dae9f..9101b5c97bf17 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -57,16 +57,20 @@ static void __vlv_punit_put(struct drm_i915_private *i915) iosf_mbi_punit_release(); } -void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) { + struct drm_i915_private *i915 = to_i915(drm); + if (ports & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); } -void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) { + struct drm_i915_private *i915 = to_i915(drm); + mutex_unlock(&i915->vlv_iosf_sb.lock); if (ports & BIT(VLV_IOSF_SB_PUNIT)) @@ -166,8 +170,9 @@ static u32 unit_to_opcode(enum vlv_iosf_sb_unit unit, bool write) return write ? SB_CRWRDA_NP : SB_CRRDDA_NP; } -u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr) { + struct drm_i915_private *i915 = to_i915(drm); u32 devfn, port, opcode, val = 0; devfn = unit_to_devfn(unit); @@ -182,8 +187,9 @@ u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, return val; } -int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { + struct drm_i915_private *i915 = to_i915(drm); u32 devfn, port, opcode; devfn = unit_to_devfn(unit); diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index f4fb7213fe377..6c9b94922de96 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -10,6 +10,7 @@ #include "vlv_iosf_sb_reg.h" +struct drm_device; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -27,10 +28,10 @@ enum vlv_iosf_sb_unit { void vlv_iosf_sb_init(struct drm_i915_private *i915); void vlv_iosf_sb_fini(struct drm_i915_private *i915); -void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports); -void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports); +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports); -u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); -int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); +u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); +int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); #endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index e34d9c72a587f..69e1935e9cdf5 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -10,7 +10,7 @@ #include "vlv_iosf_sb_reg.h" -struct drm_i915_private; +struct drm_device; enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, @@ -24,18 +24,18 @@ enum vlv_iosf_sb_unit { VLV_IOSF_SB_PUNIT, }; -static inline void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) +static inline void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) { } -static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +static inline u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr) { return 0; } -static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +static inline int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { return 0; } -static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) +static inline void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) { } -- GitLab From 52d8361531d605d6a3f9b40203412c439eb52b0c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:58 +0300 Subject: [PATCH 038/902] drm/i915: rename VLV IOSF SB ports parameter to unit_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify what the parameter is about through proper naming. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/b1be9a4089dfbf48ea1434944a4841d2ac4c4acc.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 8 ++++---- drivers/gpu/drm/i915/vlv_iosf_sb.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 9101b5c97bf17..c8f8589ee0be6 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -57,23 +57,23 @@ static void __vlv_punit_put(struct drm_i915_private *i915) iosf_mbi_punit_release(); } -void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); - if (ports & BIT(VLV_IOSF_SB_PUNIT)) + if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); } -void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); mutex_unlock(&i915->vlv_iosf_sb.lock); - if (ports & BIT(VLV_IOSF_SB_PUNIT)) + if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_put(i915); } diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 6c9b94922de96..e2fea29a30ea2 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -28,8 +28,8 @@ enum vlv_iosf_sb_unit { void vlv_iosf_sb_init(struct drm_i915_private *i915); void vlv_iosf_sb_fini(struct drm_i915_private *i915); -void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports); -void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports); +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask); +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask); u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); -- GitLab From 11b5b1bd97ef927ab8c5c41ce35d3397f590384a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:59 +0300 Subject: [PATCH 039/902] drm/i915: ensure correct VLV IOSF SB units have been get/put MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some extra paranoia to check correct use of the VLV IOSF SB get/put/read/write. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/be6f029adf7148198821e5fe01dcf5d5406aa1fe.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/vlv_iosf_sb.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d0e1980dcba2c..93b4c504b7100 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -230,6 +230,7 @@ struct drm_i915_private { /* VLV/CHV IOSF sideband */ struct { struct mutex lock; /* protect sideband access */ + unsigned long locked_unit_mask; struct pm_qos_request qos; } vlv_iosf_sb; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index c8f8589ee0be6..f4b435555f3bd 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -65,12 +65,18 @@ void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); + + i915->vlv_iosf_sb.locked_unit_mask |= unit_mask; } void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); + i915->vlv_iosf_sb.locked_unit_mask &= ~unit_mask; + + drm_WARN_ON(drm, i915->vlv_iosf_sb.locked_unit_mask); + mutex_unlock(&i915->vlv_iosf_sb.lock); if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) @@ -182,6 +188,8 @@ u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 add if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) return 0; + drm_WARN_ON(&i915->drm, !(i915->vlv_iosf_sb.locked_unit_mask & BIT(unit))); + vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); return val; @@ -199,6 +207,8 @@ int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 ad if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) return -EINVAL; + drm_WARN_ON(&i915->drm, !(i915->vlv_iosf_sb.locked_unit_mask & BIT(unit))); + return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); } -- GitLab From 16fa6b89990a76302446f5c4e866991ef08bcf1e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 12 May 2025 08:20:47 +0100 Subject: [PATCH 040/902] drm/i915: Use provided dma_fence_is_chain Replace open-coded helper with the subsystem one. Signed-off-by: Tvrtko Ursulin Reviewed-by: Matthew Brost Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20250512072047.56851-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 7127e90c1a8f1..991666fd9f85f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -106,11 +106,6 @@ static void fence_set_priority(struct dma_fence *fence, rcu_read_unlock(); } -static inline bool __dma_fence_is_chain(const struct dma_fence *fence) -{ - return fence->ops == &dma_fence_chain_ops; -} - void i915_gem_fence_wait_priority(struct dma_fence *fence, const struct i915_sched_attr *attr) { @@ -126,7 +121,7 @@ void i915_gem_fence_wait_priority(struct dma_fence *fence, for (i = 0; i < array->num_fences; i++) fence_set_priority(array->fences[i], attr); - } else if (__dma_fence_is_chain(fence)) { + } else if (dma_fence_is_chain(fence)) { struct dma_fence *iter; /* The chain is ordered; if we boost the last, we boost all */ -- GitLab From 2d278488761f0b5be651a3db41e615a964123d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 13 May 2025 08:48:13 +0300 Subject: [PATCH 041/902] drm/i915/alpm: Make intel_alpm_enable_sink available for PSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to enable sink ALPM from PSR code. Make intel_alpm_enable_sink available for PSR. v2: do not add kerneldoc comments Reviewed-by: Suraj Kandpal Signed-off-by: Jouni Högander Link: https://lore.kernel.org/r/20250513054814.3702977-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 4 ++-- drivers/gpu/drm/i915/display/intel_alpm.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 1bf08b80c23f9..da70a98a1292e 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -426,8 +426,8 @@ void intel_alpm_pre_plane_update(struct intel_atomic_state *state, } } -static void intel_alpm_enable_sink(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +void intel_alpm_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { u8 val; diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index d7126d65b60fb..c9fe21e3e72ce 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -23,6 +23,8 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, struct drm_connector_state *conn_state); void intel_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +void intel_alpm_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_alpm_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_alpm_post_plane_update(struct intel_atomic_state *state, -- GitLab From a8eb102ce0944a9de2a62aa9d195861b7f26668a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 13 May 2025 08:48:14 +0300 Subject: [PATCH 042/902] drm/i915/alpm: Stop writing ALPM registers when PSR is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are seeing these on PTL: xe 0000:00:02.0: [drm] *ERROR* Timeout waiting for DDI BUF A to get active These seem to be caused by writing ALPM registers while Panel Replay is enabled. Fix this by writing ALPM registers only when Panel Replay is about to be enabled. v4: improve comment on intel_psr_panel_replay_enable_sink call v3: enable/disable ALPM from PSR code Fixes: 172757acd6f6 ("drm/i915/lobf: Add lobf enablement in post plane update") Signed-off-by: Jouni Högander Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20250513054814.3702977-3-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 4 ++-- drivers/gpu/drm/i915/display/intel_psr.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index da70a98a1292e..c176bdbc19a34 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -453,8 +453,8 @@ void intel_alpm_post_plane_update(struct intel_atomic_state *state, intel_atomic_get_old_crtc_state(state, crtc); struct intel_encoder *encoder; - if ((!crtc_state->has_lobf || - crtc_state->has_lobf == old_crtc_state->has_lobf) && !crtc_state->has_psr) + if (crtc_state->has_psr || !crtc_state->has_lobf || + crtc_state->has_lobf == old_crtc_state->has_lobf) return; for_each_intel_encoder_mask(display->drm, encoder, diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index ccd66bbc72f79..430ad4ef71466 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -800,6 +800,8 @@ static void _psr_enable_sink(struct intel_dp *intel_dp, static void intel_psr_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { + intel_alpm_enable_sink(intel_dp, crtc_state); + crtc_state->has_panel_replay ? _panel_replay_enable_sink(intel_dp, crtc_state) : _psr_enable_sink(intel_dp, crtc_state); @@ -1962,6 +1964,8 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) && !intel_dp->psr.panel_replay_enabled) intel_dmc_block_pkgc(display, intel_dp->psr.pipe, true); + + intel_alpm_configure(intel_dp, crtc_state); } static bool psr_interrupt_error_check(struct intel_dp *intel_dp) @@ -2029,8 +2033,9 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, intel_dp->psr.sel_update_enabled ? "2" : "1"); /* - * Enabling here only for PSR. Panel Replay enable bit is already - * written at this point. See + * Enabling sink PSR/Panel Replay here only for PSR. Panel Replay enable + * bit is already written at this point. Sink ALPM is enabled here for + * PSR and Panel Replay. See * intel_psr_panel_replay_enable_sink. Modifiers/options: * - Selective Update * - Region Early Transport @@ -2172,6 +2177,9 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) if (intel_dp_is_edp(intel_dp)) intel_snps_phy_update_psr_power_state(&dp_to_dig_port(intel_dp)->base, false); + if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) + intel_alpm_disable(intel_dp); + /* Disable PSR on Sink */ if (!intel_dp->psr.panel_replay_enabled) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); @@ -3498,7 +3506,6 @@ static void psr_alpm_check(struct intel_dp *intel_dp) if (intel_alpm_get_error(intel_dp)) { intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; - intel_alpm_disable(intel_dp); } } -- GitLab From 59cbff3a8f766adede869a955fb92924bb3707a9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:41 +0300 Subject: [PATCH 043/902] drm/i915/pps: drop dependency on intel_display_conversion.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the PPS register users have been converted to struct intel_display. The backward compat conversion to struct drm_i915_private is no longer needed. Drop it, along with the include, and convert the dev_priv macro parameter names to display while at it. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/4c23fd8dfcadefeeb52189045421084bcfd50d57.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_pps_regs.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps_regs.h b/drivers/gpu/drm/i915/display/intel_pps_regs.h index 8f9dbfab95233..2f014d929d327 100644 --- a/drivers/gpu/drm/i915/display/intel_pps_regs.h +++ b/drivers/gpu/drm/i915/display/intel_pps_regs.h @@ -6,7 +6,6 @@ #ifndef __INTEL_PPS_REGS_H__ #define __INTEL_PPS_REGS_H__ -#include "intel_display_conversion.h" #include "intel_display_reg_defs.h" /* Panel power sequencing */ @@ -14,11 +13,11 @@ #define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) #define PCH_PPS_BASE 0xC7200 -#define _MMIO_PPS(dev_priv, pps_idx, reg) \ - _MMIO(__to_intel_display(dev_priv)->pps.mmio_base - PPS_BASE + (reg) + (pps_idx) * 0x100) +#define _MMIO_PPS(display, pps_idx, reg) \ + _MMIO((display)->pps.mmio_base - PPS_BASE + (reg) + (pps_idx) * 0x100) #define _PP_STATUS 0x61200 -#define PP_STATUS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_STATUS) +#define PP_STATUS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_STATUS) #define PP_ON REG_BIT(31) /* * Indicates that all dependencies of the panel are on: @@ -45,7 +44,7 @@ #define PP_SEQUENCE_STATE_RESET REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xf) #define _PP_CONTROL 0x61204 -#define PP_CONTROL(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_CONTROL) +#define PP_CONTROL(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_CONTROL) #define PANEL_UNLOCK_MASK REG_GENMASK(31, 16) #define PANEL_UNLOCK_REGS REG_FIELD_PREP(PANEL_UNLOCK_MASK, 0xabcd) #define BXT_POWER_CYCLE_DELAY_MASK REG_GENMASK(8, 4) @@ -55,7 +54,7 @@ #define PANEL_POWER_ON REG_BIT(0) #define _PP_ON_DELAYS 0x61208 -#define PP_ON_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_ON_DELAYS) +#define PP_ON_DELAYS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_ON_DELAYS) #define PANEL_PORT_SELECT_MASK REG_GENMASK(31, 30) #define PANEL_PORT_SELECT_LVDS REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 0) #define PANEL_PORT_SELECT_DPA REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 1) @@ -66,12 +65,12 @@ #define PANEL_LIGHT_ON_DELAY_MASK REG_GENMASK(12, 0) #define _PP_OFF_DELAYS 0x6120C -#define PP_OFF_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_OFF_DELAYS) +#define PP_OFF_DELAYS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_OFF_DELAYS) #define PANEL_POWER_DOWN_DELAY_MASK REG_GENMASK(28, 16) #define PANEL_LIGHT_OFF_DELAY_MASK REG_GENMASK(12, 0) #define _PP_DIVISOR 0x61210 -#define PP_DIVISOR(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_DIVISOR) +#define PP_DIVISOR(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_DIVISOR) #define PP_REFERENCE_DIVIDER_MASK REG_GENMASK(31, 8) #define PANEL_POWER_CYCLE_DELAY_MASK REG_GENMASK(4, 0) -- GitLab From c00d3615969e9bba610c83050f308aee75341156 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:42 +0300 Subject: [PATCH 044/902] drm/i915/rps: pass struct intel_display to DISPLAY_VER() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid passing drm_i915_private to DISPLAY_VER(). Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/5e97ee7675b32397163eb4fba17184fc1c5a04cd.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index 678b241159512..0f1c95d70843b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -45,12 +45,13 @@ static int do_rps_boost(struct wait_queue_entry *_wait, void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct dma_fence *fence) { + struct intel_display *display = to_intel_display(crtc->dev); struct wait_rps_boost *wait; if (!dma_fence_is_i915(fence)) return; - if (DISPLAY_VER(to_i915(crtc->dev)) < 6) + if (DISPLAY_VER(display) < 6) return; if (drm_crtc_vblank_get(crtc)) -- GitLab From 1882dc90dfb13450f3c1ca5e529fa6a4f80c6e44 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:43 +0300 Subject: [PATCH 045/902] drm/i915/display: drop unused declarations from intel_display.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've accumulated lots of forward declarations in intel_display.h that are no longer necessary. Clean them up. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/5ad046b74040e84fab51786c346ff9a445e351bc.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index fa857c0e03c70..37e2ab301a80e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -30,37 +30,21 @@ #include "i915_reg_defs.h" #include "intel_display_limits.h" -enum drm_scaling_filter; -struct dpll; struct drm_atomic_state; -struct drm_connector; struct drm_device; struct drm_display_mode; struct drm_encoder; -struct drm_file; -struct drm_format_info; -struct drm_framebuffer; -struct drm_mode_fb_cmd2; struct drm_modeset_acquire_ctx; -struct drm_plane; -struct drm_plane_state; -struct i915_address_space; -struct i915_gtt_view; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; struct intel_digital_port; struct intel_display; -struct intel_dp; struct intel_encoder; -struct intel_initial_plane_config; struct intel_link_m_n; struct intel_plane; struct intel_plane_state; struct intel_power_domain_mask; -struct pci_dev; -struct work_struct; - #define pipe_name(p) ((p) + 'A') -- GitLab From a1216d84f13ca53c107cba99311a90177eeaa508 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:44 +0300 Subject: [PATCH 046/902] drm/i915/gem: drop intel_display.h include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include is not needed since commit 44a34dec43e8 ("drm/i915: Calculate the VT-d guard size in the display code"). Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/80ea203e004b7378c14f2367258b5785e40bf126.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 75a143d996e0e..50f5ec84574e0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -4,7 +4,6 @@ * Copyright © 2014-2016 Intel Corporation */ -#include "display/intel_display.h" #include "gt/intel_gt.h" #include "i915_drv.h" -- GitLab From e2e02eb978c590e7278413eecd93142218609419 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:45 +0300 Subject: [PATCH 047/902] drm/i915/display: drop unnecessary includes on i915 core headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These includes have become unnecessary. Drop them. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/6ca3be3e3fbbd99c169345c3add4b76315390e77.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 1 - drivers/gpu/drm/i915/display/intel_crt.c | 1 - drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_display_debugfs.c | 1 - drivers/gpu/drm/i915/display/intel_dp.c | 1 - drivers/gpu/drm/i915/display/intel_dsb.c | 1 - 6 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 7276179df8786..d41f2bd5bdfa5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -42,7 +42,6 @@ #include #include "gem/i915_gem_object.h" -#include "i915_config.h" #include "i915_scheduler_types.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 38b50a779b6bb..04ef729dae0ba 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -34,7 +34,6 @@ #include #include -#include "i915_irq.h" #include "i915_reg.h" #include "intel_connector.h" #include "intel_crt.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e0928f28d7116..91ca467b069b2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -105,7 +105,6 @@ #include "intel_panel.h" #include "intel_pch_display.h" #include "intel_pch_refclk.h" -#include "intel_pcode.h" #include "intel_pfit.h" #include "intel_pipe_crc.h" #include "intel_plane_initial.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index a9b1ec4cf0f75..9df8995e5bac6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -13,7 +13,6 @@ #include #include "hsw_ips.h" -#include "i915_irq.h" #include "i915_reg.h" #include "i9xx_wm_regs.h" #include "intel_alpm.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 91a34d474463a..21297bc4cc00d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -51,7 +51,6 @@ #include #include "g4x_dp.h" -#include "i915_irq.h" #include "i915_reg.h" #include "i915_utils.h" #include "intel_alpm.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 481488d1fe677..393ea07947b41 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -7,7 +7,6 @@ #include #include -#include "i915_irq.h" #include "i915_reg.h" #include "i915_utils.h" #include "intel_crtc.h" -- GitLab From d0bf684bd42db22e7d131a038f8f78927fa6a72a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 12 May 2025 17:26:00 +0300 Subject: [PATCH 048/902] drm/i915/ptl: Use everywhere the correct DDI port clock select mask The PTL XELPDP_PORT_CLOCK_CTL register XELPDP_DDI_CLOCK_SELECT field's size is 5 bits vs. the earlier platforms where its size is 4 bits. Make sure the field is read-out/programmed everywhere correctly, according to the above. Cc: Mika Kahola Cc: stable@vger.kernel.org # v6.13+ Tested-by: Mika Kahola Reviewed-by: Mika Kahola Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250512142600.824347-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 +++++++------------ .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 15 ++++++++--- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index b09f724c3046b..a82b93cbc81d2 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2763,9 +2763,9 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, val |= XELPDP_FORWARD_CLOCK_UNGATE; if (!is_dp && is_hdmi_frl(port_clock)) - val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK); else - val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK); /* TODO: HDMI FRL */ /* DP2.0 10G and 20G rates enable MPLLA*/ @@ -2776,7 +2776,7 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | - XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLA | + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_SSC_ENABLE_PLLA | XELPDP_SSC_ENABLE_PLLB, val); } @@ -3099,10 +3099,7 @@ int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); - if (DISPLAY_VER(display) >= 30) - clock = REG_FIELD_GET(XE3_DDI_CLOCK_SELECT_MASK, val); - else - clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val); + clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); drm_WARN_ON(display->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE)); drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_REQUEST)); @@ -3170,13 +3167,9 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, * clock muxes, gating and SSC */ - if (DISPLAY_VER(display) >= 30) { - mask = XE3_DDI_CLOCK_SELECT_MASK; - val |= XE3_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); - } else { - mask = XELPDP_DDI_CLOCK_SELECT_MASK; - val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); - } + mask = XELPDP_DDI_CLOCK_SELECT_MASK(display); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, + intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); mask |= XELPDP_FORWARD_CLOCK_UNGATE; val |= XELPDP_FORWARD_CLOCK_UNGATE; @@ -3289,7 +3282,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder) /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_DDI_CLOCK_SELECT_MASK, 0); + XELPDP_DDI_CLOCK_SELECT_MASK(display), 0); intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), XELPDP_FORWARD_CLOCK_UNGATE, 0); @@ -3338,7 +3331,7 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) * 5. Program PORT CLOCK CTRL register to disable and gate clocks */ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_DDI_CLOCK_SELECT_MASK | + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_FORWARD_CLOCK_UNGATE, 0); /* 6. Program DDI_CLK_VALFREQ to 0. */ @@ -3367,7 +3360,7 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, * handling is done via the standard shared DPLL framework. */ val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); - clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val); + clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK || clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index 960f7f778fb81..59c22beaf1de5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -192,10 +192,17 @@ #define XELPDP_TBT_CLOCK_REQUEST REG_BIT(19) #define XELPDP_TBT_CLOCK_ACK REG_BIT(18) -#define XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) -#define XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) -#define XELPDP_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val) -#define XE3_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XE3_DDI_CLOCK_SELECT_MASK, val) +#define _XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) +#define _XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) +#define XELPDP_DDI_CLOCK_SELECT_MASK(display) (DISPLAY_VER(display) >= 30 ? \ + _XE3_DDI_CLOCK_SELECT_MASK : _XELPDP_DDI_CLOCK_SELECT_MASK) +#define XELPDP_DDI_CLOCK_SELECT_PREP(display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_PREP(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_PREP(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) +#define XELPDP_DDI_CLOCK_SELECT_GET(display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_GET(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_GET(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) + #define XELPDP_DDI_CLOCK_SELECT_NONE 0x0 #define XELPDP_DDI_CLOCK_SELECT_MAXPCLK 0x8 #define XELPDP_DDI_CLOCK_SELECT_DIV18CLK 0x9 -- GitLab From 745df157e4f2d695a9149ff964abe77490b1e96c Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:14 +0530 Subject: [PATCH 049/902] drm/xe: Introduce xe_vma_op_prefetch_range struct for prefetch of ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add xe_vma_op_prefetch_range struct for svm ranges prefetching, including an xarray of SVM range pointers, range count, and target memory region. -v2: Fix doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-2-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm_types.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 1662604c4486d..0afd0296a57e9 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -374,6 +374,16 @@ struct xe_vma_op_unmap_range { struct xe_svm_range *range; }; +/** struct xe_vma_op_prefetch_range - VMA prefetch range operation */ +struct xe_vma_op_prefetch_range { + /** @range: xarray for SVM ranges data */ + struct xarray range; + /** @ranges_count: number of svm ranges to map */ + u32 ranges_count; + /** @region: memory region to prefetch to */ + u32 region; +}; + /** enum xe_vma_op_flags - flags for VMA operation */ enum xe_vma_op_flags { /** @XE_VMA_OP_COMMITTED: VMA operation committed */ @@ -416,6 +426,8 @@ struct xe_vma_op { struct xe_vma_op_map_range map_range; /** @unmap_range: VMA unmap range operation specific data */ struct xe_vma_op_unmap_range unmap_range; + /** @prefetch_range: VMA prefetch range operation specific data */ + struct xe_vma_op_prefetch_range prefetch_range; }; }; -- GitLab From 686a526dad183e1ca7fc2f38df34b1dd3c7c387e Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:15 +0530 Subject: [PATCH 050/902] drm/xe: Make xe_svm_alloc_vram public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function will be used in prefetch too, hence make it public. v2: - Add kernel-doc (Matthew Brost) - Rebase v3: - Move CONFIG_DRM_XE_DEVMEM_MIRROR stub out to xe_svm.c (Matthew Brost) Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-3-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/xe/xe_svm.h | 12 ++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index ab88b4194e574..875376bddc886 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -677,9 +677,19 @@ static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) return &tile->mem.vram; } -static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, - struct xe_svm_range *range, - const struct drm_gpusvm_ctx *ctx) +/** + * xe_svm_alloc_vram()- Allocate device memory pages for range, + * migrating existing data. + * @vm: The VM. + * @tile: tile to allocate vram from + * @range: SVM range + * @ctx: DRM GPU SVM context + * + * Return: 0 on success, error code on failure. + */ +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) { struct mm_struct *mm = vm->svm.gpusvm.mm; struct xe_vram_region *vr = tile_to_vr(tile); @@ -733,13 +743,6 @@ unlock: return err; } -#else -static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, - struct xe_svm_range *range, - const struct drm_gpusvm_ctx *ctx) -{ - return -EOPNOTSUPP; -} #endif static bool supports_4K_migration(struct xe_device *xe) @@ -1025,6 +1028,13 @@ int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr) return 0; } #else +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) +{ + return -EOPNOTSUPP; +} + int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr) { return 0; diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 30fc78b85b30f..36e245ec64225 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -70,6 +70,9 @@ int xe_svm_bo_evict(struct xe_bo *bo); void xe_svm_range_debug(struct xe_svm_range *range, const char *operation); +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx); /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -97,6 +100,7 @@ void xe_svm_flush(struct xe_vm *vm); #include struct drm_pagemap_device_addr; +struct drm_gpusvm_ctx; struct xe_bo; struct xe_gt; struct xe_vm; @@ -167,6 +171,14 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation) { } +static inline +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) +{ + return -EOPNOTSUPP; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From eb07c2fc10bf9b98fb5df8a78ce707e3a20b5443 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:16 +0530 Subject: [PATCH 051/902] drm/xe/svm: Helper to add tile masks to svm ranges Introduce a helper to add tile mask of binding present and invalidated for the range. Add a lockdep_assert to ensure it is protected by GPU SVM notifier lock. -v7 rebased Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-4-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_pt.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index b04756a97cdcf..4d248d06bfa57 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -2216,6 +2216,18 @@ static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile, } } +static void range_present_and_invalidated_tile(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_id) +{ + /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ + + lockdep_assert_held(&vm->svm.gpusvm.notifier_lock); + + WRITE_ONCE(range->tile_present, range->tile_present | BIT(tile_id)); + WRITE_ONCE(range->tile_invalidated, range->tile_invalidated & ~BIT(tile_id)); +} + static void op_commit(struct xe_vm *vm, struct xe_tile *tile, struct xe_vm_pgtable_update_ops *pt_update_ops, @@ -2271,19 +2283,13 @@ static void op_commit(struct xe_vm *vm, case DRM_GPUVA_OP_DRIVER: { /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ - - if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { - WRITE_ONCE(op->map_range.range->tile_present, - op->map_range.range->tile_present | - BIT(tile->id)); - WRITE_ONCE(op->map_range.range->tile_invalidated, - op->map_range.range->tile_invalidated & - ~BIT(tile->id)); - } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { + if (op->subop == XE_VMA_SUBOP_MAP_RANGE) + range_present_and_invalidated_tile(vm, op->map_range.range, tile->id); + else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) WRITE_ONCE(op->unmap_range.range->tile_present, op->unmap_range.range->tile_present & ~BIT(tile->id)); - } + break; } default: -- GitLab From 18211ff4d57381476cf34bc6a8883eccee9a893a Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:17 +0530 Subject: [PATCH 052/902] drm/xe/svm: Make to_xe_range a public function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The to_xe_range function will be used in other files. Therefore, make it public and add kernel-doc documentation Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-5-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 5 ----- drivers/gpu/drm/xe/xe_svm.h | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 875376bddc886..77740730e8215 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -103,11 +103,6 @@ static void xe_svm_range_free(struct drm_gpusvm_range *range) kfree(range); } -static struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) -{ - return container_of(r, struct xe_svm_range, base); -} - static void xe_svm_garbage_collector_add_range(struct xe_vm *vm, struct xe_svm_range *range, const struct mmu_notifier_range *mmu_range) diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 36e245ec64225..e9257f0b3ffcc 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -85,6 +85,20 @@ static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range) return range->base.flags.has_dma_mapping; } +/** + * to_xe_range - Convert a drm_gpusvm_range pointer to a xe_svm_range + * @r: Pointer to the drm_gpusvm_range structure + * + * This function takes a pointer to a drm_gpusvm_range structure and + * converts it to a pointer to the containing xe_svm_range structure. + * + * Return: Pointer to the xe_svm_range structure + */ +static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) +{ + return container_of(r, struct xe_svm_range, base); +} + #define xe_svm_assert_in_notifier(vm__) \ lockdep_assert_held_write(&(vm__)->svm.gpusvm.notifier_lock) @@ -101,6 +115,7 @@ void xe_svm_flush(struct xe_vm *vm); struct drm_pagemap_device_addr; struct drm_gpusvm_ctx; +struct drm_gpusvm_range; struct xe_bo; struct xe_gt; struct xe_vm; @@ -179,6 +194,11 @@ int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, return -EOPNOTSUPP; } +static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) +{ + return NULL; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From da2eb41004e955293675a4049da94084ebd41241 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:18 +0530 Subject: [PATCH 053/902] drm/xe/svm: Make xe_svm_range_* end/start/size public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions will be used in prefetch too, therefore make them public. v2 - Fix kernel doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-6-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 15 ------------ drivers/gpu/drm/xe/xe_svm.h | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 77740730e8215..6cfe92b8adbe1 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -45,21 +45,6 @@ static struct xe_vm *range_to_vm(struct drm_gpusvm_range *r) return gpusvm_to_vm(r->gpusvm); } -static unsigned long xe_svm_range_start(struct xe_svm_range *range) -{ - return drm_gpusvm_range_start(&range->base); -} - -static unsigned long xe_svm_range_end(struct xe_svm_range *range) -{ - return drm_gpusvm_range_end(&range->base); -} - -static unsigned long xe_svm_range_size(struct xe_svm_range *range) -{ - return drm_gpusvm_range_size(&range->base); -} - #define range_debug(r__, operaton__) \ vm_dbg(&range_to_vm(&(r__)->base)->xe->drm, \ "%s: asid=%u, gpusvm=%p, vram=%d,%d, seqno=%lu, " \ diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index e9257f0b3ffcc..a69bbdc736082 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -99,6 +99,39 @@ static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) return container_of(r, struct xe_svm_range, base); } +/** + * xe_svm_range_start() - SVM range start address + * @range: SVM range + * + * Return: start address of range. + */ +static inline unsigned long xe_svm_range_start(struct xe_svm_range *range) +{ + return drm_gpusvm_range_start(&range->base); +} + +/** + * xe_svm_range_end() - SVM range end address + * @range: SVM range + * + * Return: end address of range. + */ +static inline unsigned long xe_svm_range_end(struct xe_svm_range *range) +{ + return drm_gpusvm_range_end(&range->base); +} + +/** + * xe_svm_range_size() - SVM range size + * @range: SVM range + * + * Return: Size of range. + */ +static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) +{ + return drm_gpusvm_range_size(&range->base); +} + #define xe_svm_assert_in_notifier(vm__) \ lockdep_assert_held_write(&(vm__)->svm.gpusvm.notifier_lock) @@ -199,6 +232,21 @@ static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) return NULL; } +static inline unsigned long xe_svm_range_start(struct xe_svm_range *range) +{ + return 0; +} + +static inline unsigned long xe_svm_range_end(struct xe_svm_range *range) +{ + return 0; +} + +static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) +{ + return 0; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 34ebb62723aa766be85ea38fac7e651bfaca6a61 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:19 +0530 Subject: [PATCH 054/902] drm/xe/vm: Update xe_vma_ops_incr_pt_update_ops to take an increment value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefetch for SVM ranges can have more than one operation to increment, hence modify the function to accept an increment value as input. v2: - Call xe_vma_ops_incr_pt_update_ops only once for REMAP (Matthew Brost) - Add check for 0 ops v3: - s/u8/int for inc_val and num_remap_ops (Matthew Brost) Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-7-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 79323c78130f3..f4382386b34c9 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -806,13 +806,16 @@ static void xe_vma_ops_fini(struct xe_vma_ops *vops) kfree(vops->pt_update_ops[i].ops); } -static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask) +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask, int inc_val) { int i; + if (!inc_val) + return; + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) if (BIT(i) & tile_mask) - ++vops->pt_update_ops[i].num_ops; + vops->pt_update_ops[i].num_ops += inc_val; } static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, @@ -842,7 +845,7 @@ static int xe_vm_ops_add_rebind(struct xe_vma_ops *vops, struct xe_vma *vma, xe_vm_populate_rebind(op, vma, tile_mask); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, tile_mask, 1); return 0; } @@ -977,7 +980,7 @@ xe_vm_ops_add_range_rebind(struct xe_vma_ops *vops, xe_vm_populate_range_rebind(op, vma, range, tile_mask); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, tile_mask, 1); return 0; } @@ -1062,7 +1065,7 @@ xe_vm_ops_add_range_unbind(struct xe_vma_ops *vops, xe_vm_populate_range_unbind(op, range); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, range->tile_present); + xe_vma_ops_incr_pt_update_ops(vops, range->tile_present, 1); return 0; } @@ -2493,7 +2496,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, !op->map.is_cpu_addr_mirror) || op->map.invalidate_on_bind) xe_vma_ops_incr_pt_update_ops(vops, - op->tile_mask); + op->tile_mask, 1); break; } case DRM_GPUVA_OP_REMAP: @@ -2502,6 +2505,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, gpuva_to_vma(op->base.remap.unmap->va); bool skip = xe_vma_is_cpu_addr_mirror(old); u64 start = xe_vma_start(old), end = xe_vma_end(old); + int num_remap_ops = 0; if (op->base.remap.prev) start = op->base.remap.prev->va.addr + @@ -2554,7 +2558,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, (ULL)op->remap.start, (ULL)op->remap.range); } else { - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; } } @@ -2583,11 +2587,13 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, (ULL)op->remap.start, (ULL)op->remap.range); } else { - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; } } if (!skip) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; + + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, num_remap_ops); break; } case DRM_GPUVA_OP_UNMAP: @@ -2599,7 +2605,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, return -EBUSY; if (!xe_vma_is_cpu_addr_mirror(vma)) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); break; case DRM_GPUVA_OP_PREFETCH: vma = gpuva_to_vma(op->base.prefetch.va); @@ -2611,7 +2617,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, } if (!xe_vma_is_cpu_addr_mirror(vma)) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); -- GitLab From bd1d1b46fe42a248916172cdf3cded07b7d93f8a Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:20 +0530 Subject: [PATCH 055/902] drm/xe/vm: Add an identifier in xe_vma_ops for svm prefetch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag in xe_vma_ops to determine whether it has svm prefetch ops or not. v2: - s/false/0 (Matthew Brost) v3: - s/XE_VMA_OPS_HAS_SVM_PREFETCH/XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-8-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 1 + drivers/gpu/drm/xe/xe_vm_types.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index f4382386b34c9..21564ecf87657 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3240,6 +3240,7 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm, vops->q = q; vops->syncs = syncs; vops->num_syncs = num_syncs; + vops->flags = 0; } static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 0afd0296a57e9..bfc145baad496 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -445,6 +445,9 @@ struct xe_vma_ops { u32 num_syncs; /** @pt_update_ops: page table update operations */ struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE]; + /** @flag: signify the properties within xe_vma_ops*/ +#define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0) + u32 flags; #ifdef TEST_VM_OPS_ERROR /** @inject_error: inject error to test error handling */ bool inject_error; -- GitLab From da05e5ddc652d1ab66efddc52e32a8770a89cbd9 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:21 +0530 Subject: [PATCH 056/902] drm/xe: Rename lookup_vma function to xe_find_vma_by_addr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update renames the lookup_vma function to xe_vm_find_vma_by_addr and makes it accessible externally. The function, which looks up a VMA by its address within a specified VM, will be utilized in upcoming patches. v2 - Fix doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-9-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 24 +---------------------- drivers/gpu/drm/xe/xe_vm.c | 29 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_vm.h | 2 ++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 10622ca471a28..7a8f87709e39c 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -72,28 +72,6 @@ static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma) !(BIT(tile->id) & vma->tile_invalidated); } -static bool vma_matches(struct xe_vma *vma, u64 page_addr) -{ - if (page_addr > xe_vma_end(vma) - 1 || - page_addr + SZ_4K - 1 < xe_vma_start(vma)) - return false; - - return true; -} - -static struct xe_vma *lookup_vma(struct xe_vm *vm, u64 page_addr) -{ - struct xe_vma *vma = NULL; - - if (vm->usm.last_fault_vma) { /* Fast lookup */ - if (vma_matches(vm->usm.last_fault_vma, page_addr)) - vma = vm->usm.last_fault_vma; - } - if (!vma) - vma = xe_vm_find_overlapping_vma(vm, page_addr, SZ_4K); - - return vma; -} static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma, bool atomic, unsigned int id) @@ -231,7 +209,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) goto unlock_vm; } - vma = lookup_vma(vm, pf->page_addr); + vma = xe_vm_find_vma_by_addr(vm, pf->page_addr); if (!vma) { err = -EINVAL; goto unlock_vm; diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 21564ecf87657..cb79a37d2132b 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2139,6 +2139,35 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data, return err; } +static bool vma_matches(struct xe_vma *vma, u64 page_addr) +{ + if (page_addr > xe_vma_end(vma) - 1 || + page_addr + SZ_4K - 1 < xe_vma_start(vma)) + return false; + + return true; +} + +/** + * xe_vm_find_vma_by_addr() - Find a VMA by its address + * + * @vm: the xe_vm the vma belongs to + * @page_addr: address to look up + */ +struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr) +{ + struct xe_vma *vma = NULL; + + if (vm->usm.last_fault_vma) { /* Fast lookup */ + if (vma_matches(vm->usm.last_fault_vma, page_addr)) + vma = vm->usm.last_fault_vma; + } + if (!vma) + vma = xe_vm_find_overlapping_vma(vm, page_addr, SZ_4K); + + return vma; +} + static const u32 region_to_mem_type[] = { XE_PL_TT, XE_PL_VRAM0, diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 0ef811fc2bdee..99e164852f637 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -169,6 +169,8 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma) !xe_vma_is_cpu_addr_mirror(vma); } +struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr); + /** * to_userptr_vma() - Return a pointer to an embedding userptr vma * @vma: Pointer to the embedded struct xe_vma -- GitLab From e0ff0d7cf928fdd0e52565dd6285c46ccf3bce89 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:22 +0530 Subject: [PATCH 057/902] drm/xe/svm: Refactor usage of drm_gpusvm* function in xe_svm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define xe_svm_range_find_or_insert function wrapping drm_gpusvm_range_find_or_insert for reusing in prefetch. Define xe_svm_range_get_pages function wrapping drm_gpusvm_range_get_pages for reusing in prefetch. -v2 pass pagefault defined drm_gpu_svm context as parameter in xe_svm_range_find_or_insert(Matthew Brost) Cc: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-10-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 65 ++++++++++++++++++++++++++++++++----- drivers/gpu/drm/xe/xe_svm.h | 21 ++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6cfe92b8adbe1..6e593733d473f 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -785,7 +785,6 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, vm->xe->atomic_svm_timeslice_ms : 0, }; struct xe_svm_range *range; - struct drm_gpusvm_range *r; struct drm_exec exec; struct dma_fence *fence; struct xe_tile *tile = gt_to_tile(gt); @@ -804,16 +803,14 @@ retry: if (err) return err; - r = drm_gpusvm_range_find_or_insert(&vm->svm.gpusvm, fault_addr, - xe_vma_start(vma), xe_vma_end(vma), - &ctx); - if (IS_ERR(r)) - return PTR_ERR(r); + range = xe_svm_range_find_or_insert(vm, fault_addr, vma, &ctx); - if (ctx.devmem_only && !r->flags.migrate_devmem) + if (IS_ERR(range)) + return PTR_ERR(range); + + if (ctx.devmem_only && !range->base.flags.migrate_devmem) return -EACCES; - range = to_xe_range(r); if (xe_svm_range_is_valid(range, tile, ctx.devmem_only)) return 0; @@ -839,7 +836,7 @@ retry: } range_debug(range, "GET PAGES"); - err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); + err = xe_svm_range_get_pages(vm, range, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ @@ -930,6 +927,56 @@ int xe_svm_bo_evict(struct xe_bo *bo) return drm_gpusvm_evict_to_ram(&bo->devmem_allocation); } +/** + * xe_svm_range_find_or_insert- Find or insert GPU SVM range + * @vm: xe_vm pointer + * @addr: address for which range needs to be found/inserted + * @vma: Pointer to struct xe_vma which mirrors CPU + * @ctx: GPU SVM context + * + * This function finds or inserts a newly allocated a SVM range based on the + * address. + * + * Return: Pointer to the SVM range on success, ERR_PTR() on failure. + */ +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx) +{ + struct drm_gpusvm_range *r; + + r = drm_gpusvm_range_find_or_insert(&vm->svm.gpusvm, max(addr, xe_vma_start(vma)), + xe_vma_start(vma), xe_vma_end(vma), ctx); + if (IS_ERR(r)) + return ERR_PTR(PTR_ERR(r)); + + return to_xe_range(r); +} + +/** + * xe_svm_range_get_pages() - Get pages for a SVM range + * @vm: Pointer to the struct xe_vm + * @range: Pointer to the xe SVM range structure + * @ctx: GPU SVM context + * + * This function gets pages for a SVM range and ensures they are mapped for + * DMA access. In case of failure with -EOPNOTSUPP, it evicts the range. + * + * Return: 0 on success, negative error code on failure. + */ +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx) +{ + int err = 0; + + err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, &range->base, ctx); + if (err == -EOPNOTSUPP) { + range_debug(range, "PAGE FAULT - EVICT PAGES"); + drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); + } + + return err; +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct drm_pagemap_device_addr diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index a69bbdc736082..e304d147d309b 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -73,6 +73,13 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation); int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, struct xe_svm_range *range, const struct drm_gpusvm_ctx *ctx); + +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx); + +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -227,6 +234,20 @@ int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, return -EOPNOTSUPP; } +static inline +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx) +{ + return ERR_PTR(-EINVAL); +} + +static inline +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx) +{ + return -EINVAL; +} + static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) { return NULL; -- GitLab From cc795e0410342076a4ad65ca2b5450cda779f784 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:23 +0530 Subject: [PATCH 058/902] drm/xe/svm: Make xe_svm_range_needs_migrate_to_vram() public xe_svm_range_needs_migrate_to_vram() determines whether range needs migration to vram or not, modify it to accept region preference parameter too, so we can use it in prefetch too. v2 - add assert instead of warn (Matthew Brost) Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-11-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 26 ++++++++++++++++++-------- drivers/gpu/drm/xe/xe_svm.h | 10 ++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6e593733d473f..c6505350c8ffd 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -733,22 +733,32 @@ static bool supports_4K_migration(struct xe_device *xe) return true; } -static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, - struct xe_vma *vma) +/** + * xe_svm_range_needs_migrate_to_vram() - SVM range needs migrate to VRAM or not + * @range: SVM range for which migration needs to be decided + * @vma: vma which has range + * @preferred_region_is_vram: preferred region for range is vram + * + * Return: True for range needing migration and migration is supported else false + */ +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + bool preferred_region_is_vram) { struct xe_vm *vm = range_to_vm(&range->base); u64 range_size = xe_svm_range_size(range); - if (!range->base.flags.migrate_devmem) + if (!range->base.flags.migrate_devmem || !preferred_region_is_vram) return false; - if (xe_svm_range_in_vram(range)) { - drm_dbg(&vm->xe->drm, "Range is already in VRAM\n"); + xe_assert(vm->xe, IS_DGFX(vm->xe)); + + if (preferred_region_is_vram && xe_svm_range_in_vram(range)) { + drm_info(&vm->xe->drm, "Range is already in VRAM\n"); return false; } - if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { - drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); + if (preferred_region_is_vram && range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + drm_warn(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); return false; } @@ -817,7 +827,7 @@ retry: range_debug(range, "PAGE FAULT"); if (--migrate_try_count >= 0 && - xe_svm_range_needs_migrate_to_vram(range, vma)) { + xe_svm_range_needs_migrate_to_vram(range, vma, IS_DGFX(vm->xe))) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (err) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index e304d147d309b..0ee845e35b3ee 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -80,6 +80,9 @@ struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, struct drm_gpusvm_ctx *ctx); +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + bool preferred_region_is_vram); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -268,6 +271,13 @@ static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) return 0; } +static inline +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + u32 region) +{ + return false; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 6275362f1837ba538956d05e1c6120db3a635631 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:24 +0530 Subject: [PATCH 059/902] drm/xe/svm: Add xe_svm_range_validate() and xe_svm_range_migrate_to_smem() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe_svm_range_validate() function checks if a range is valid and located in the desired memory region. xe_svm_range_migrate_to_smem() checks if range have pages in devmem and migrate them to smem. v2 - Fix function stub in xe_svm.h - Fix doc v3 (Matthew Brost) - Remove extra new line - s/range->base.flags.has_devmem_pages/xe_svm_range_in_vram v4 (Matthew Brost) - s/xe_svm_range_in_vram/range->base.flags.has_devmem_pages - Move eviction logic to separate function Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-12-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 41 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_svm.h | 19 +++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index c6505350c8ffd..248f615a343e6 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -651,6 +651,47 @@ static bool xe_svm_range_is_valid(struct xe_svm_range *range, (!devmem_only || xe_svm_range_in_vram(range)); } +/** xe_svm_range_migrate_to_smem() - Move range pages from VRAM to SMEM + * @vm: xe_vm pointer + * @range: Pointer to the SVM range structure + * + * The xe_svm_range_migrate_to_smem() checks range has pages in VRAM + * and migrates them to SMEM + */ +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range) +{ + if (xe_svm_range_in_vram(range)) + drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); +} + +/** + * xe_svm_range_validate() - Check if the SVM range is valid + * @vm: xe_vm pointer + * @range: Pointer to the SVM range structure + * @tile_mask: Mask representing the tiles to be checked + * @devmem_preferred : if true range needs to be in devmem + * + * The xe_svm_range_validate() function checks if a range is + * valid and located in the desired memory region. + * + * Return: true if the range is valid, false otherwise + */ +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred) +{ + bool ret; + + xe_svm_notifier_lock(vm); + + ret = (range->tile_present & ~range->tile_invalidated & tile_mask) == tile_mask && + (devmem_preferred == range->base.flags.has_devmem_pages); + + xe_svm_notifier_unlock(vm); + + return ret; +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 0ee845e35b3ee..42be9e5d04445 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -83,6 +83,12 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, bool preferred_region_is_vram); +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range); + +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -278,6 +284,19 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm return false; } +static inline +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range) +{ +} + +static inline +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred) +{ + return false; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 72fa870957f53314bfa4b75bd3d402b72fab17ee Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:25 +0530 Subject: [PATCH 060/902] drm/gpusvm: Introduce drm_gpusvm_find_vma_start() function The drm_gpusvm_find_vma_start() function is used to determine the starting address of a CPU VMA within a specified user range. If the range does not contain any VMA, the function returns ULONG_MAX. v2 - Rename function as drm_gpusvm_find_vma_start() (Matthew Brost) - mmget/mmput v3 - s/mmget/mmget_not_zero/ Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-13-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/drm_gpusvm.c | 34 ++++++++++++++++++++++++++++++++++ include/drm/drm_gpusvm.h | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 4b2f32889f00f..7bb9eb71c9aa5 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -980,6 +980,40 @@ static void drm_gpusvm_driver_lock_held(struct drm_gpusvm *gpusvm) } #endif +/** + * drm_gpusvm_find_vma_start() - Find start address for first VMA in range + * @gpusvm: Pointer to the GPU SVM structure + * @start: The inclusive start user address. + * @end: The exclusive end user address. + * + * Returns: The start address of first VMA within the provided range, + * ULONG_MAX otherwise. Assumes start_addr < end_addr. + */ +unsigned long +drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm, + unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = gpusvm->mm; + struct vm_area_struct *vma; + unsigned long addr = ULONG_MAX; + + if (!mmget_not_zero(mm)) + return addr; + + mmap_read_lock(mm); + + vma = find_vma_intersection(mm, start, end); + if (vma) + addr = vma->vm_start; + + mmap_read_unlock(mm); + mmput(mm); + + return addr; +} +EXPORT_SYMBOL_GPL(drm_gpusvm_find_vma_start); + /** * drm_gpusvm_range_find_or_insert() - Find or insert GPU SVM range * @gpusvm: Pointer to the GPU SVM structure diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index eaf704d3d05e8..6a5156476bf47 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -327,6 +327,11 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm); void drm_gpusvm_free(struct drm_gpusvm *gpusvm); +unsigned long +drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm, + unsigned long start, + unsigned long end); + struct drm_gpusvm_range * drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm, unsigned long fault_addr, -- GitLab From c904d4e2d73216c31487501b774afa9e3ed8be29 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:26 +0530 Subject: [PATCH 061/902] drm/xe/svm: Add xe_svm_find_vma_start() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helper xe_svm_find_vma_start() function to determine start of cpu vma in input range. Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-14-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_svm.h | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 248f615a343e6..4432685936ed4 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -692,6 +692,28 @@ bool xe_svm_range_validate(struct xe_vm *vm, return ret; } +/** + * xe_svm_find_vma_start - Find start of CPU VMA + * @vm: xe_vm pointer + * @start: start address + * @end: end address + * @vma: Pointer to struct xe_vma + * + * + * This function searches for a cpu vma, within the specified + * range [start, end] in the given VM. It adjusts the range based on the + * xe_vma start and end addresses. If no cpu VMA is found, it returns ULONG_MAX. + * + * Return: The starting address of the VMA within the range, + * or ULONG_MAX if no VMA is found + */ +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 start, u64 end, struct xe_vma *vma) +{ + return drm_gpusvm_find_vma_start(&vm->svm.gpusvm, + max(start, xe_vma_start(vma)), + min(end, xe_vma_end(vma))); +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 42be9e5d04445..19ce4f2754a78 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -89,6 +89,8 @@ bool xe_svm_range_validate(struct xe_vm *vm, struct xe_svm_range *range, u8 tile_mask, bool devmem_preferred); +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vma); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -297,6 +299,12 @@ bool xe_svm_range_validate(struct xe_vm *vm, return false; } +static inline +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vma) +{ + return ULONG_MAX; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 09ba0a8f06cd69d93eef0dc3bee33546880e46f8 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:27 +0530 Subject: [PATCH 062/902] drm/xe/svm: Implement prefetch support for SVM ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds prefetch support for SVM ranges, utilizing the existing ioctl vm_bind functionality to achieve this. v2: rebase v3: - use xa_for_each() instead of manual loop - check range is valid and in preferred location before adding to xarray - Fix naming conventions - Fix return condition as -ENODATA instead of -EAGAIN (Matthew Brost) - Handle sparsely populated cpu vma range (Matthew Brost) v4: - fix end address to find next cpu vma in case of -ENOENT v5: - Move find next vma logic to drm gpusvm layer - Avoid mixing declaration and logic v6: - Use new function names - Move eviction logic to prefetch_ranges v7: - devmem_only assigned 0 - nit address v8: - initialize ctx with 0 Cc: Matthew Brost Acked-by: Thomas Hellström Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-15-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_pt.c | 58 ++++++++--- drivers/gpu/drm/xe/xe_vm.c | 196 +++++++++++++++++++++++++++++++++++-- 2 files changed, 233 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 4d248d06bfa57..c9c41fbe125c6 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1458,6 +1458,7 @@ static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update) struct xe_vm *vm = pt_update->vops->vm; struct xe_vma_ops *vops = pt_update->vops; struct xe_vma_op *op; + unsigned long i; int err; err = xe_pt_pre_commit(pt_update); @@ -1467,20 +1468,35 @@ static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update) xe_svm_notifier_lock(vm); list_for_each_entry(op, &vops->list, link) { - struct xe_svm_range *range = op->map_range.range; + struct xe_svm_range *range = NULL; if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) continue; - xe_svm_range_debug(range, "PRE-COMMIT"); + if (op->base.op == DRM_GPUVA_OP_PREFETCH) { + xe_assert(vm->xe, + xe_vma_is_cpu_addr_mirror(gpuva_to_vma(op->base.prefetch.va))); + xa_for_each(&op->prefetch_range.range, i, range) { + xe_svm_range_debug(range, "PRE-COMMIT"); - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma)); - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE); + if (!xe_svm_range_pages_valid(range)) { + xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); + xe_svm_notifier_unlock(vm); + return -ENODATA; + } + } + } else { + xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma)); + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE); + range = op->map_range.range; - if (!xe_svm_range_pages_valid(range)) { - xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); - xe_svm_notifier_unlock(vm); - return -EAGAIN; + xe_svm_range_debug(range, "PRE-COMMIT"); + + if (!xe_svm_range_pages_valid(range)) { + xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); + xe_svm_notifier_unlock(vm); + return -EAGAIN; + } } } @@ -2065,11 +2081,20 @@ static int op_prepare(struct xe_vm *vm, { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - if (xe_vma_is_cpu_addr_mirror(vma)) - break; + if (xe_vma_is_cpu_addr_mirror(vma)) { + struct xe_svm_range *range; + unsigned long i; - err = bind_op_prepare(vm, tile, pt_update_ops, vma, false); - pt_update_ops->wait_vm_kernel = true; + xa_for_each(&op->prefetch_range.range, i, range) { + err = bind_range_prepare(vm, tile, pt_update_ops, + vma, range); + if (err) + return err; + } + } else { + err = bind_op_prepare(vm, tile, pt_update_ops, vma, false); + pt_update_ops->wait_vm_kernel = true; + } break; } case DRM_GPUVA_OP_DRIVER: @@ -2275,9 +2300,16 @@ static void op_commit(struct xe_vm *vm, { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - if (!xe_vma_is_cpu_addr_mirror(vma)) + if (xe_vma_is_cpu_addr_mirror(vma)) { + struct xe_svm_range *range = NULL; + unsigned long i; + + xa_for_each(&op->prefetch_range.range, i, range) + range_present_and_invalidated_tile(vm, range, tile->id); + } else { bind_op_commit(vm, tile, pt_update_ops, vma, fence, fence2, false); + } break; } case DRM_GPUVA_OP_DRIVER: diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index cb79a37d2132b..842af808c39b7 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -798,10 +798,33 @@ static int xe_vma_ops_alloc(struct xe_vma_ops *vops, bool array_of_binds) } ALLOW_ERROR_INJECTION(xe_vma_ops_alloc, ERRNO); +static void xe_vma_svm_prefetch_op_fini(struct xe_vma_op *op) +{ + struct xe_vma *vma; + + vma = gpuva_to_vma(op->base.prefetch.va); + + if (op->base.op == DRM_GPUVA_OP_PREFETCH && xe_vma_is_cpu_addr_mirror(vma)) + xa_destroy(&op->prefetch_range.range); +} + +static void xe_vma_svm_prefetch_ops_fini(struct xe_vma_ops *vops) +{ + struct xe_vma_op *op; + + if (!(vops->flags & XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH)) + return; + + list_for_each_entry(op, &vops->list, link) + xe_vma_svm_prefetch_op_fini(op); +} + static void xe_vma_ops_fini(struct xe_vma_ops *vops) { int i; + xe_vma_svm_prefetch_ops_fini(vops); + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) kfree(vops->pt_update_ops[i].ops); } @@ -2248,13 +2271,25 @@ static bool __xe_vm_needs_clear_scratch_pages(struct xe_vm *vm, u32 bind_flags) return true; } +static void xe_svm_prefetch_gpuva_ops_fini(struct drm_gpuva_ops *ops) +{ + struct drm_gpuva_op *__op; + + drm_gpuva_for_each_op(__op, ops) { + struct xe_vma_op *op = gpuva_op_to_vma_op(__op); + + xe_vma_svm_prefetch_op_fini(op); + } +} + /* * Create operations list from IOCTL arguments, setup operations fields so parse * and commit steps are decoupled from IOCTL arguments. This step can fail. */ static struct drm_gpuva_ops * -vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, - u64 bo_offset_or_userptr, u64 addr, u64 range, +vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, + struct xe_bo *bo, u64 bo_offset_or_userptr, + u64 addr, u64 range, u32 operation, u32 flags, u32 prefetch_region, u16 pat_index) { @@ -2262,6 +2297,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, struct drm_gpuva_ops *ops; struct drm_gpuva_op *__op; struct drm_gpuvm_bo *vm_bo; + u64 range_end = addr + range; int err; lockdep_assert_held_write(&vm->lock); @@ -2323,14 +2359,77 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, op->map.invalidate_on_bind = __xe_vm_needs_clear_scratch_pages(vm, flags); } else if (__op->op == DRM_GPUVA_OP_PREFETCH) { - op->prefetch.region = prefetch_region; - } + struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); + struct xe_svm_range *svm_range; + struct drm_gpusvm_ctx ctx = {}; + struct xe_tile *tile; + u8 id, tile_mask = 0; + u32 i; + + if (!xe_vma_is_cpu_addr_mirror(vma)) { + op->prefetch.region = prefetch_region; + break; + } + + ctx.read_only = xe_vma_read_only(vma); + ctx.devmem_possible = IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR); + + for_each_tile(tile, vm->xe, id) + tile_mask |= 0x1 << id; + + xa_init_flags(&op->prefetch_range.range, XA_FLAGS_ALLOC); + op->prefetch_range.region = prefetch_region; + op->prefetch_range.ranges_count = 0; +alloc_next_range: + svm_range = xe_svm_range_find_or_insert(vm, addr, vma, &ctx); + + if (PTR_ERR(svm_range) == -ENOENT) { + u64 ret = xe_svm_find_vma_start(vm, addr, range_end, vma); + + addr = ret == ULONG_MAX ? 0 : ret; + if (addr) + goto alloc_next_range; + else + goto print_op_label; + } + + if (IS_ERR(svm_range)) { + err = PTR_ERR(svm_range); + goto unwind_prefetch_ops; + } + + if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) + goto check_next_range; + + err = xa_alloc(&op->prefetch_range.range, + &i, svm_range, xa_limit_32b, + GFP_KERNEL); + if (err) + goto unwind_prefetch_ops; + + op->prefetch_range.ranges_count++; + vops->flags |= XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH; +check_next_range: + if (range_end > xe_svm_range_end(svm_range) && + xe_svm_range_end(svm_range) < xe_vma_end(vma)) { + addr = xe_svm_range_end(svm_range); + goto alloc_next_range; + } + } +print_op_label: print_op(vm->xe, __op); } return ops; + +unwind_prefetch_ops: + xe_svm_prefetch_gpuva_ops_fini(ops); + drm_gpuva_ops_free(&vm->gpuvm, ops); + return ERR_PTR(err); } + ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_create, ERRNO); static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op, @@ -2645,8 +2744,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, return err; } - if (!xe_vma_is_cpu_addr_mirror(vma)) + if (xe_vma_is_cpu_addr_mirror(vma)) + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, + op->prefetch_range.ranges_count); + else xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); + break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); @@ -2772,6 +2875,55 @@ static int check_ufence(struct xe_vma *vma) return 0; } +static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) +{ + bool devmem_possible = IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR); + struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); + int err = 0; + + struct xe_svm_range *svm_range; + struct drm_gpusvm_ctx ctx = {}; + struct xe_tile *tile; + unsigned long i; + u32 region; + + if (!xe_vma_is_cpu_addr_mirror(vma)) + return 0; + + region = op->prefetch_range.region; + + ctx.read_only = xe_vma_read_only(vma); + ctx.devmem_possible = devmem_possible; + ctx.check_pages_threshold = devmem_possible ? SZ_64K : 0; + + /* TODO: Threading the migration */ + xa_for_each(&op->prefetch_range.range, i, svm_range) { + if (!region) + xe_svm_range_migrate_to_smem(vm, svm_range); + + if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, region)) { + tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0]; + err = xe_svm_alloc_vram(vm, tile, svm_range, &ctx); + if (err) { + drm_dbg(&vm->xe->drm, "VRAM allocation failed, retry from userspace, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + return -ENODATA; + } + } + + err = xe_svm_range_get_pages(vm, svm_range, &ctx); + if (err) { + if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) + err = -ENODATA; + drm_dbg(&vm->xe->drm, "Get pages failed, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + return err; + } + } + + return err; +} + static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, struct xe_vma_op *op) { @@ -2809,7 +2961,12 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, case DRM_GPUVA_OP_PREFETCH: { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - u32 region = op->prefetch.region; + u32 region; + + if (xe_vma_is_cpu_addr_mirror(vma)) + region = op->prefetch_range.region; + else + region = op->prefetch.region; xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type)); @@ -2828,6 +2985,25 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, return err; } +static int vm_bind_ioctl_ops_prefetch_ranges(struct xe_vm *vm, struct xe_vma_ops *vops) +{ + struct xe_vma_op *op; + int err; + + if (!(vops->flags & XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH)) + return 0; + + list_for_each_entry(op, &vops->list, link) { + if (op->base.op == DRM_GPUVA_OP_PREFETCH) { + err = prefetch_ranges(vm, op); + if (err) + return err; + } + } + + return 0; +} + static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, struct xe_vma_ops *vops) @@ -3477,7 +3653,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) u32 prefetch_region = bind_ops[i].prefetch_mem_region_instance; u16 pat_index = bind_ops[i].pat_index; - ops[i] = vm_bind_ioctl_ops_create(vm, bos[i], obj_offset, + ops[i] = vm_bind_ioctl_ops_create(vm, &vops, bos[i], obj_offset, addr, range, op, flags, prefetch_region, pat_index); if (IS_ERR(ops[i])) { @@ -3510,6 +3686,10 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (err) goto unwind_ops; + err = vm_bind_ioctl_ops_prefetch_ranges(vm, &vops); + if (err) + goto unwind_ops; + fence = vm_bind_ioctl_ops_execute(vm, &vops); if (IS_ERR(fence)) err = PTR_ERR(fence); @@ -3579,7 +3759,7 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, xe_vma_ops_init(&vops, vm, q, NULL, 0); - ops = vm_bind_ioctl_ops_create(vm, bo, 0, addr, bo->size, + ops = vm_bind_ioctl_ops_create(vm, &vops, bo, 0, addr, bo->size, DRM_XE_VM_BIND_OP_MAP, 0, 0, vm->xe->pat.idx[cache_lvl]); if (IS_ERR(ops)) { -- GitLab From 5aee6e33e19593dafc42f9afb59fd2c53f75141f Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:28 +0530 Subject: [PATCH 063/902] drm/xe/vm: Add debug prints for SVM range prefetch Introduce debug logs for the prefetch operation of SVM ranges. Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-16-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 842af808c39b7..5a978da411b03 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2399,8 +2399,10 @@ alloc_next_range: goto unwind_prefetch_ops; } - if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) + if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) { + xe_svm_range_debug(svm_range, "PREFETCH - RANGE IS VALID"); goto check_next_range; + } err = xa_alloc(&op->prefetch_range.range, &i, svm_range, xa_limit_32b, @@ -2411,6 +2413,7 @@ alloc_next_range: op->prefetch_range.ranges_count++; vops->flags |= XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH; + xe_svm_range_debug(svm_range, "PREFETCH - RANGE CREATED"); check_next_range: if (range_end > xe_svm_range_end(svm_range) && xe_svm_range_end(svm_range) < xe_vma_end(vma)) { @@ -2909,6 +2912,7 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); return -ENODATA; } + xe_svm_range_debug(svm_range, "PREFETCH - RANGE MIGRATED TO VRAM"); } err = xe_svm_range_get_pages(vm, svm_range, &ctx); @@ -2919,6 +2923,7 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); return err; } + xe_svm_range_debug(svm_range, "PREFETCH - RANGE GET PAGES DONE"); } return err; -- GitLab From b86babc9d92f0a5fbbc7ab4c7d09bce688f94ebf Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 13 May 2025 00:00:17 +0200 Subject: [PATCH 064/902] drm/xe/guc: Unblock GuC buffer cache for all modes Today we were using GuC buffer cache only in the PF mode, but shortly we will want to use it also in native and VF mode. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Matthew Brost Reviewed-by: Daniele Ceraolo Spurio Link: https://lore.kernel.org/r/20250512220018.172-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc.c | 4 ++++ drivers/gpu/drm/xe/xe_guc_buf.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index bac5471a1a780..350434a8b9537 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -710,6 +710,10 @@ static int vf_guc_init_post_hwconfig(struct xe_guc *guc) if (err) return err; + err = xe_guc_buf_cache_init(&guc->buf); + if (err) + return err; + /* XXX xe_guc_db_mgr_init not needed for now */ return 0; diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index 0193c94dd6a00..14a07dca48e7b 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -37,10 +37,6 @@ int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) struct xe_gt *gt = cache_to_gt(cache); struct xe_sa_manager *sam; - /* XXX: currently it's useful only for the PF actions */ - if (!IS_SRIOV_PF(gt_to_xe(gt))) - return 0; - sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0, sizeof(u32)); if (IS_ERR(sam)) return PTR_ERR(sam); -- GitLab From 3dbab383e3afe999d9e9513cd9a67883b6750358 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 13 May 2025 00:00:18 +0200 Subject: [PATCH 065/902] drm/xe/guc: Don't allocate managed BO for each policy change We shouldn't use xe_managed_bo_create_from_data() to allocate temporary BO, as it will be released only on unload and every change in wedge_mode policy will consume resources (including precious GGTT). Instead just switchover to GuC buffer cache. Signed-off-by: Michal Wajdeczko Cc: John Harrison Cc: Rodrigo Vivi Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250512220018.172-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_ads.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 44c1fa2fe7c85..07a0277556271 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -20,6 +20,7 @@ #include "xe_gt_ccs_mode.h" #include "xe_gt_printk.h" #include "xe_guc.h" +#include "xe_guc_buf.h" #include "xe_guc_capture.h" #include "xe_guc_ct.h" #include "xe_hw_engine.h" @@ -994,6 +995,16 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off return xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0); } +static int guc_ads_update_policies(struct xe_guc_ads *ads, const struct guc_policies *policies) +{ + CLASS(xe_guc_buf_from_data, buf)(&ads_to_guc(ads)->buf, policies, sizeof(*policies)); + + if (!xe_guc_buf_is_valid(buf)) + return -ENOBUFS; + + return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf)); +} + /** * xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy * @ads: Additional data structures object @@ -1005,11 +1016,8 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) { struct xe_device *xe = ads_to_xe(ads); - struct xe_gt *gt = ads_to_gt(ads); - struct xe_tile *tile = gt_to_tile(gt); struct guc_policies *policies; - struct xe_bo *bo; - int ret = 0; + int ret; policies = kmalloc(sizeof(*policies), GFP_KERNEL); if (!policies) @@ -1023,16 +1031,7 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) else policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET; - bo = xe_managed_bo_create_from_data(xe, tile, policies, sizeof(struct guc_policies), - XE_BO_FLAG_VRAM_IF_DGFX(tile) | - XE_BO_FLAG_GGTT); - if (IS_ERR(bo)) { - ret = PTR_ERR(bo); - goto out; - } - - ret = guc_ads_action_update_policies(ads, xe_bo_ggtt_addr(bo)); -out: + ret = guc_ads_update_policies(ads, policies); kfree(policies); return ret; } -- GitLab From eaa287069a70aa80e5e95d5162445962809d8158 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 13 May 2025 07:25:49 -0700 Subject: [PATCH 066/902] drm/xe/guc_submit: Simplify and fix diff calculation With a u32 type, there's no need to check which one is greater: the current is always the latest and if it's less than the previous, it's because it wrapped: just do the unsigned calculation that will lead to the same result, or better the correct one. It fixes an off-by-one in the wrapped calculation, however that doesn't really matter for the timeout calculation. Reviewed-by: Raag Jadav Reviewed-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513-time-wrap-v1-1-fba9a69a65c8@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_guc_submit.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index fb125f940de8f..80f748baad3f3 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -976,10 +976,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) */ xe_gt_assert(gt, timeout_ms < 100 * MSEC_PER_SEC); - if (ctx_timestamp < ctx_job_timestamp) - diff = ctx_timestamp + U32_MAX - ctx_job_timestamp; - else - diff = ctx_timestamp - ctx_job_timestamp; + diff = ctx_timestamp - ctx_job_timestamp; /* * Ensure timeout is within 5% to account for an GuC scheduling latency -- GitLab From d6e020819612a4a06207af858e0978be4d3e3140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 21:22:15 +0200 Subject: [PATCH 067/902] drm/i915/gem: Allow EXEC_CAPTURE on recoverable contexts on DG1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel-media-driver is currently broken on DG1 because it uses EXEC_CAPTURE with recovarable contexts. Relax the check to allow that. I've also submitted a fix for the intel-media-driver: https://github.com/intel/media-driver/pull/1920 Cc: stable@vger.kernel.org # v6.0+ Cc: Matthew Auld Cc: Thomas Hellström Testcase: igt/gem_exec_capture/capture-invisible Fixes: 71b1669ea9bd ("drm/i915/uapi: tweak error capture on recoverable contexts") Reviewed-by: Andi Shyti Signed-off-by: Ville Syrjälä Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250411144313.11660-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 02c59808cbe48..7d44aadcd5a5c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2013,7 +2013,7 @@ static int eb_capture_stage(struct i915_execbuffer *eb) continue; if (i915_gem_context_is_recoverable(eb->gem_context) && - (IS_DGFX(eb->i915) || GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 0))) + GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 10)) return -EINVAL; for_each_batch_create_order(eb, j) { -- GitLab From 9b961744a83a3027b8d4b97fe1fc587334883ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 21:22:16 +0200 Subject: [PATCH 068/902] drm/i915/pci: Remove force_probe requirement for DG1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dunno why we still have .require_force_probe=1 on DG1 after all this time. I'm not aware of any real problems with DG1, so get rid of the force_probe requirement. Generally the difficulty with DG1 is that it requires a 4GiB BAR for the local memory, and that's not something that works on every system. Reviewed-by: Andi Shyti Signed-off-by: Ville Syrjälä Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250411144313.11660-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 21006c7f615c2..b2e311f4791a0 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -663,7 +663,6 @@ static const struct intel_device_info dg1_info = { DGFX_FEATURES, .__runtime.graphics.ip.rel = 10, PLATFORM(INTEL_DG1), - .require_force_probe = 1, .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), -- GitLab From fddf8cdd4b9b7373f32f77e7a89123394e630188 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:21 -0700 Subject: [PATCH 069/902] drm/xe/guc: Remove double blank line An earlier patch moved a drm_print a few lines lower but accidentally left a double blank line behind. So fix that. Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-2-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/xe_guc_ct.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index ff6edf1b14f49..b09dd5788a270 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -2013,7 +2013,6 @@ static void ct_dead_print(struct xe_dead_ct *dead) return; } - /* Can't generate a genuine core dump at this point, so just do the good bits */ drm_puts(&lp, "**** Xe Device Coredump ****\n"); drm_printf(&lp, "Reason: CTB is dead - 0x%X\n", dead->reason); -- GitLab From 12373b30e27cffd4244453ed3bceb52504d7563f Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:22 -0700 Subject: [PATCH 070/902] drm/xe/guc: Add missing H2G error code definitions These error codes are not actually used in the driver but it is extremely useful to have them available to understand error messages. v2: Add a bunch more error codes and drop 'status' from names (review feedback by Michal W). v3: Drop 'SUCCESS' response as meaningless in current API (review feedback by Michal W). Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-3-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/abi/guc_errors_abi.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/abi/guc_errors_abi.h b/drivers/gpu/drm/xe/abi/guc_errors_abi.h index 2c627a21648f7..ecf748fd87df3 100644 --- a/drivers/gpu/drm/xe/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_errors_abi.h @@ -6,8 +6,7 @@ #ifndef _ABI_GUC_ERRORS_ABI_H #define _ABI_GUC_ERRORS_ABI_H -enum xe_guc_response_status { - XE_GUC_RESPONSE_STATUS_SUCCESS = 0x0, +enum xe_guc_response { XE_GUC_RESPONSE_ERROR_PROTOCOL = 0x04, XE_GUC_RESPONSE_INVALID_STATE = 0x0A, XE_GUC_RESPONSE_UNSUPPORTED_VERSION = 0x0B, @@ -21,12 +20,20 @@ enum xe_guc_response_status { XE_GUC_RESPONSE_CANNOT_COMPLETE_ACTION = 0x41, XE_GUC_RESPONSE_INVALID_KLV_DATA = 0x50, XE_GUC_RESPONSE_INVALID_PARAMS = 0x60, + XE_GUC_RESPONSE_INVALID_CONTEXT_INDEX = 0x61, + XE_GUC_RESPONSE_INVALID_CONTEXT_REGISTRATION = 0x62, + XE_GUC_RESPONSE_INVALID_DOORBELL_ID = 0x63, + XE_GUC_RESPONSE_INVALID_ENGINE_ID = 0x64, XE_GUC_RESPONSE_INVALID_BUFFER_RANGE = 0x70, XE_GUC_RESPONSE_INVALID_BUFFER = 0x71, + XE_GUC_RESPONSE_BUFFER_ALREADY_REGISTERED = 0x72, XE_GUC_RESPONSE_INVALID_GGTT_ADDRESS = 0x80, XE_GUC_RESPONSE_PENDING_ACTION = 0x90, + XE_GUC_RESPONSE_CONTEXT_NOT_REGISTERED = 0x100, + XE_GUC_RESPONSE_CONTEXT_ALREADY_REGISTERED = 0X101, XE_GUC_RESPONSE_INVALID_SIZE = 0x102, XE_GUC_RESPONSE_MALFORMED_KLV = 0x103, + XE_GUC_RESPONSE_INVALID_CONTEXT = 0x104, XE_GUC_RESPONSE_INVALID_KLV_KEY = 0x105, XE_GUC_RESPONSE_DATA_TOO_LARGE = 0x106, XE_GUC_RESPONSE_VF_MIGRATED = 0x107, @@ -40,10 +47,11 @@ enum xe_guc_response_status { XE_GUC_RESPONSE_CTB_NOT_REGISTERED = 0x304, XE_GUC_RESPONSE_CTB_IN_USE = 0x305, XE_GUC_RESPONSE_CTB_INVALID_DESC = 0x306, + XE_GUC_RESPONSE_HW_TIMEOUT = 0x30C, XE_GUC_RESPONSE_CTB_SOURCE_INVALID_DESCRIPTOR = 0x30D, XE_GUC_RESPONSE_CTB_DESTINATION_INVALID_DESCRIPTOR = 0x30E, XE_GUC_RESPONSE_INVALID_CONFIG_STATE = 0x30F, - XE_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, + XE_GUC_RESPONSE_GENERIC_FAIL = 0xF000, }; enum xe_guc_load_status { -- GitLab From d7d97890e2a7e3e306494dcbfb0e468a5089380d Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:23 -0700 Subject: [PATCH 071/902] drm/xe/guc: Rename CONFIG_XE_LARGE_GUC_BUFFER Rename XE_LARGE_GUC_BUFFER to XE_DEBUG_GUC to allow for more debug only code (in subsequent patch) without adding more config defines that each control only a single thing. Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-4-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/Kconfig.debug | 8 +++++--- drivers/gpu/drm/xe/xe_guc_log.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug index 0d749ed448786..db063a513b1e5 100644 --- a/drivers/gpu/drm/xe/Kconfig.debug +++ b/drivers/gpu/drm/xe/Kconfig.debug @@ -86,12 +86,14 @@ config DRM_XE_KUNIT_TEST If in doubt, say "N". -config DRM_XE_LARGE_GUC_BUFFER - bool "Enable larger guc log buffer" +config DRM_XE_DEBUG_GUC + bool "Enable extra GuC related debug options" + depends on DRM_XE_DEBUG default n help Choose this option when debugging guc issues. - Buffer should be large enough for complex issues. + The GuC log buffer is increased to the maximum allowed, which should + be large enough for complex issues. Recommended for driver developers only. diff --git a/drivers/gpu/drm/xe/xe_guc_log.h b/drivers/gpu/drm/xe/xe_guc_log.h index 5b896f5fafafa..f1e2b0be90a9f 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.h +++ b/drivers/gpu/drm/xe/xe_guc_log.h @@ -12,7 +12,7 @@ struct drm_printer; struct xe_device; -#if IS_ENABLED(CONFIG_DRM_XE_LARGE_GUC_BUFFER) +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) #define CRASH_BUFFER_SIZE SZ_1M #define DEBUG_BUFFER_SIZE SZ_8M #define CAPTURE_BUFFER_SIZE SZ_2M -- GitLab From 16b7e65d299d56442879405ac85800877fa51355 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:24 -0700 Subject: [PATCH 072/902] drm/xe/guc: Track FAST_REQ H2Gs to report where errors came from Most H2G messages are FAST_REQ which means no synchronous response is expected. The messages are sent as fire-and-forget with no tracking. However, errors can still be returned when something goes unexpectedly wrong. That leads to confusion due to not being able to match up the error response to the originating H2G. So add support for tracking the FAST_REQ H2Gs and matching up an error response to its originator. This is only enabled in XE_DEBUG builds given that such errors should never happen in a working system and there is an overhead for the tracking. Further, if XE_DEBUG_GUC is enabled then even more memory and time is used to record the call stack of each H2G and report that with the error. That makes it much easier to work out where a specific H2G came from if there are multiple code paths that can send it. v2: Some re-wording of comments and prints, more consistent use of #if vs stub functions - review feedback from Daniele & Michal). v3: Split config change to separate patch, improve a debug print (review feedback from Michal). v4: Bunch of minor tweaks (review feedback from Michal). Original-i915-code: Michal Wajdeczko Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-5-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/Kconfig.debug | 5 +- drivers/gpu/drm/xe/xe_guc_ct.c | 115 ++++++++++++++++++++++----- drivers/gpu/drm/xe/xe_guc_ct_types.h | 15 ++++ 3 files changed, 115 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug index db063a513b1e5..01735c6ece8ba 100644 --- a/drivers/gpu/drm/xe/Kconfig.debug +++ b/drivers/gpu/drm/xe/Kconfig.debug @@ -90,10 +90,13 @@ config DRM_XE_DEBUG_GUC bool "Enable extra GuC related debug options" depends on DRM_XE_DEBUG default n + select STACKDEPOT help Choose this option when debugging guc issues. The GuC log buffer is increased to the maximum allowed, which should - be large enough for complex issues. + be large enough for complex issues. The tracking of FAST_REQ messages + is extended to include a record of the calling stack, which is then + dumped on a FAST_REQ error notification. Recommended for driver developers only. diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index b09dd5788a270..822f4c33f7305 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -628,6 +628,47 @@ static void g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len) spin_unlock_irq(&ct->fast_lock); } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) +{ + unsigned int slot = fence % ARRAY_SIZE(ct->fast_req); +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + unsigned long entries[SZ_32]; + unsigned int n; + + n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); + + /* May be called under spinlock, so avoid sleeping */ + ct->fast_req[slot].stack = stack_depot_save(entries, n, GFP_NOWAIT); +#endif + ct->fast_req[slot].fence = fence; + ct->fast_req[slot].action = action; +} +#else +static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) +{ +} +#endif + +/* + * The CT protocol accepts a 16 bits fence. This field is fully owned by the + * driver, the GuC will just copy it to the reply message. Since we need to + * be able to distinguish between replies to REQUEST and FAST_REQUEST messages, + * we use one bit of the seqno as an indicator for that and a rolling counter + * for the remaining 15 bits. + */ +#define CT_SEQNO_MASK GENMASK(14, 0) +#define CT_SEQNO_UNTRACKED BIT(15) +static u16 next_ct_seqno(struct xe_guc_ct *ct, bool is_g2h_fence) +{ + u32 seqno = ct->fence_seqno++ & CT_SEQNO_MASK; + + if (!is_g2h_fence) + seqno |= CT_SEQNO_UNTRACKED; + + return seqno; +} + #define H2G_CT_HEADERS (GUC_CTB_HDR_LEN + 1) /* one DW CTB header and one DW HxG header */ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, @@ -704,6 +745,9 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | GUC_HXG_EVENT_MSG_0_DATA0, action[0]); } else { + fast_req_track(ct, ct_fence_value, + FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, action[0])); + cmd[1] = FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_FAST_REQUEST) | FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | @@ -736,25 +780,6 @@ corrupted: return -EPIPE; } -/* - * The CT protocol accepts a 16 bits fence. This field is fully owned by the - * driver, the GuC will just copy it to the reply message. Since we need to - * be able to distinguish between replies to REQUEST and FAST_REQUEST messages, - * we use one bit of the seqno as an indicator for that and a rolling counter - * for the remaining 15 bits. - */ -#define CT_SEQNO_MASK GENMASK(14, 0) -#define CT_SEQNO_UNTRACKED BIT(15) -static u16 next_ct_seqno(struct xe_guc_ct *ct, bool is_g2h_fence) -{ - u32 seqno = ct->fence_seqno++ & CT_SEQNO_MASK; - - if (!is_g2h_fence) - seqno |= CT_SEQNO_UNTRACKED; - - return seqno; -} - static int __guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len, u32 g2h_len, u32 num_g2h, struct g2h_fence *g2h_fence) @@ -1146,6 +1171,55 @@ static int guc_crash_process_msg(struct xe_guc_ct *ct, u32 action) return 0; } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +static void fast_req_report(struct xe_guc_ct *ct, u16 fence) +{ + u16 fence_min = U16_MAX, fence_max = 0; + struct xe_gt *gt = ct_to_gt(ct); + bool found = false; + unsigned int n; +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + char *buf; +#endif + + lockdep_assert_held(&ct->lock); + + for (n = 0; n < ARRAY_SIZE(ct->fast_req); n++) { + if (ct->fast_req[n].fence < fence_min) + fence_min = ct->fast_req[n].fence; + if (ct->fast_req[n].fence > fence_max) + fence_max = ct->fast_req[n].fence; + + if (ct->fast_req[n].fence != fence) + continue; + found = true; + +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + buf = kmalloc(SZ_4K, GFP_NOWAIT); + if (buf && stack_depot_snprint(ct->fast_req[n].stack, buf, SZ_4K, 0)) + xe_gt_err(gt, "Fence 0x%x was used by action %#04x sent at:\n%s", + fence, ct->fast_req[n].action, buf); + else + xe_gt_err(gt, "Fence 0x%x was used by action %#04x [failed to retrieve stack]\n", + fence, ct->fast_req[n].action); + kfree(buf); +#else + xe_gt_err(gt, "Fence 0x%x was used by action %#04x\n", + fence, ct->fast_req[n].action); +#endif + break; + } + + if (!found) + xe_gt_warn(gt, "Fence 0x%x not found - tracking buffer wrapped? [range = 0x%x -> 0x%x, next = 0x%X]\n", + fence, fence_min, fence_max, ct->fence_seqno); +} +#else +static void fast_req_report(struct xe_guc_ct *ct, u16 fence) +{ +} +#endif + static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) { struct xe_gt *gt = ct_to_gt(ct); @@ -1174,6 +1248,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) else xe_gt_err(gt, "unexpected response %u for FAST_REQ H2G fence 0x%x!\n", type, fence); + + fast_req_report(ct, fence); + CT_DEAD(ct, NULL, PARSE_G2H_RESPONSE); return -EPROTO; diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h index 8e1b9d981d61e..8b03b50313d9f 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct_types.h +++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,18 @@ struct xe_dead_ct { /** snapshot_log: copy of GuC log at point of error */ struct xe_guc_log_snapshot *snapshot_log; }; + +/** struct xe_fast_req_fence - Used to track FAST_REQ messages by fence to match error responses */ +struct xe_fast_req_fence { + /** @fence: sequence number sent in H2G and return in G2H error */ + u16 fence; + /** @action: H2G action code */ + u16 action; +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + /** @stack: call stack from when the H2G was sent */ + depot_stack_handle_t stack; +#endif +}; #endif /** @@ -152,6 +165,8 @@ struct xe_guc_ct { #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) /** @dead: information for debugging dead CTs */ struct xe_dead_ct dead; + /** @fast_req: history of FAST_REQ messages for matching with G2H error responses */ + struct xe_fast_req_fence fast_req[SZ_32]; #endif }; -- GitLab From 5779b26aafeebb177430f9b56832fcf716f32c53 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:33 +0300 Subject: [PATCH 073/902] drm/xe/rpm: use to_xe_device() instead of container_of Drop the dependency on display being a sub-struct of xe_device. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/3528f2cd5965e97248c161b8aa25a9df69606a39.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/xe/display/xe_display_rpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c index 1955153aadba0..ef76efe42e9f8 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rpm.c +++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c @@ -2,12 +2,13 @@ /* Copyright © 2025 Intel Corporation */ #include "intel_display_rpm.h" +#include "xe_device.h" #include "xe_device_types.h" #include "xe_pm.h" static struct xe_device *display_to_xe(struct intel_display *display) { - return container_of(display, struct xe_device, display); + return to_xe_device(display->drm); } struct ref_tracker *intel_display_rpm_get_raw(struct intel_display *display) -- GitLab From bfd43f9d1e858667f34fd5d7e6dafa5ba97986be Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:34 +0300 Subject: [PATCH 074/902] drm/xe/display: do not reference xe->display inline Always use a local variable for display instead of referencing xe->display inline. This makes it easier to convert xe->display into a pointer. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/c99483ad86022d02f780bac73445baaf27a6edce.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 15 ++++++++++----- drivers/gpu/drm/xe/display/xe_fb_pin.c | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 68f064f33d4b8..b8030492fbd10 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -38,7 +38,9 @@ static bool has_display(struct xe_device *xe) { - return HAS_DISPLAY(&xe->display); + struct intel_display *display = &xe->display; + + return HAS_DISPLAY(display); } /** @@ -84,8 +86,9 @@ static void unset_display_features(struct xe_device *xe) static void display_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); + struct intel_display *display = &xe->display; - destroy_workqueue(xe->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); } /** @@ -101,9 +104,11 @@ static void display_destroy(struct drm_device *dev, void *dummy) */ int xe_display_create(struct xe_device *xe) { - spin_lock_init(&xe->display.fb_tracking.lock); + struct intel_display *display = &xe->display; + + spin_lock_init(&display->fb_tracking.lock); - xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); + display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } @@ -362,7 +367,7 @@ void xe_display_pm_suspend(struct xe_device *xe) if (has_display(xe)) { intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&xe->display); + intel_encoder_suspend_all(display); } intel_opregion_suspend(display, s2idle ? PCI_D1 : PCI_D3cold); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index d918ae1c80618..e95ca979e1fe3 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -389,6 +389,7 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, { struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); struct xe_device *xe = to_xe_device(fb->base.dev); + struct intel_display *display = &xe->display; struct i915_vma *vma; if (old_plane_state->hw.fb == new_plane_state->hw.fb && @@ -399,8 +400,8 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, goto found; } - if (fb == intel_fbdev_framebuffer(xe->display.fbdev.fbdev)) { - vma = intel_fbdev_vma_pointer(xe->display.fbdev.fbdev); + if (fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) { + vma = intel_fbdev_vma_pointer(display->fbdev.fbdev); if (vma) goto found; } -- GitLab From 702f530a647f00cf5730cfc88e4cd0e699f22351 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:35 +0300 Subject: [PATCH 075/902] drm/i915: do not reference i915->display inline Always use a local variable for display instead of referencing i915->display inline. This makes it easier to convert i915->display into a pointer. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/afcf305e8c4ea452cee37479530958f36a10c840.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_driver.c | 20 ++++++++++++-------- drivers/gpu/drm/i915/intel_clock_gating.c | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 2b0bcb9aa3c72..134a1c3d1f9d1 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,6 +115,8 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + /* * The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -133,8 +135,8 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) if (dev_priv->wq == NULL) goto out_err; - dev_priv->display.hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (dev_priv->display.hotplug.dp_wq == NULL) + display->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); + if (!display->hotplug.dp_wq) goto out_free_wq; /* @@ -150,7 +152,7 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) return 0; out_free_dp_wq: - destroy_workqueue(dev_priv->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); out_free_wq: destroy_workqueue(dev_priv->wq); out_err: @@ -161,8 +163,10 @@ out_err: static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + destroy_workqueue(dev_priv->unordered_wq); - destroy_workqueue(dev_priv->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(dev_priv->wq); } @@ -991,10 +995,10 @@ void i915_driver_shutdown(struct drm_i915_private *i915) if (HAS_DISPLAY(i915)) intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&i915->display); - intel_encoder_shutdown_all(&i915->display); + intel_encoder_suspend_all(display); + intel_encoder_shutdown_all(display); - intel_dmc_suspend(&i915->display); + intel_dmc_suspend(display); i915_gem_suspend(i915); @@ -1074,7 +1078,7 @@ static int i915_drm_suspend(struct drm_device *dev) if (HAS_DISPLAY(dev_priv)) intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&dev_priv->display); + intel_encoder_suspend_all(display); /* Must be called before GGTT is suspended. */ intel_dpt_suspend(display); diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 8aec8c638fd81..892b1e19d9461 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -201,6 +201,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *i915) static void cpt_init_clock_gating(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; enum pipe pipe; u32 val; @@ -220,7 +221,7 @@ static void cpt_init_clock_gating(struct drm_i915_private *i915) val = intel_uncore_read(&i915->uncore, TRANS_CHICKEN2(pipe)); val |= TRANS_CHICKEN2_TIMING_OVERRIDE; val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; - if (i915->display.vbt.fdi_rx_polarity_inverted) + if (display->vbt.fdi_rx_polarity_inverted) val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH; -- GitLab From 96b451d53ae9760858c547081532b01038f00912 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 18:22:54 +0300 Subject: [PATCH 076/902] drm/{i915,xe}: convert i915 and xe display members into pointers As the first step towards making struct intel_display an opaque pointer in i915 and xe drivers, convert the struct drm_i915_private and struct xe_device display members into pointers. Initially, add temporary struct intel_display __display members, and point display at it to avoid dynamic allocation. In the future, we can drop this, and switch to dynamic allocation. The conversion is done simply with sed: sed -i 's/&\([a-zA-Z0-9_>.-]*\)\(dev_priv\|i915\|xe\)->display\([^.]\)/\1\2->display\3/g' \ $(git ls-files -- drivers/gpu/drm/i915 drivers/gpu/drm/xe) sed -i 's/\(dev_priv\|i915\|xe\)->display\./\1->display->/g' \ $(git ls-files -- drivers/gpu/drm/i915 drivers/gpu/drm/xe) With a couple of manual tweaks on top. v2: Initialize i915->display also in selftest mock_gem_device() Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/20250507152254.2398934-1-jani.nikula@intel.com --- .../i915/display/intel_display_conversion.c | 2 +- drivers/gpu/drm/i915/display/intel_dpt.c | 2 +- drivers/gpu/drm/i915/display/intel_vbt_defs.h | 2 +- .../i915/gem/i915_gem_object_frontbuffer.h | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 4 +- drivers/gpu/drm/i915/gt/intel_reset.c | 4 +- drivers/gpu/drm/i915/gt/intel_rps.c | 4 +- drivers/gpu/drm/i915/gvt/cmd_parser.c | 6 +-- drivers/gpu/drm/i915/gvt/display.c | 10 ++-- drivers/gpu/drm/i915/gvt/fb_decoder.c | 6 +-- drivers/gpu/drm/i915/gvt/handlers.c | 8 +-- drivers/gpu/drm/i915/i915_driver.c | 41 ++++++++------- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_getparam.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 50 +++++++++--------- drivers/gpu/drm/i915/intel_clock_gating.c | 2 +- .../gpu/drm/i915/selftests/mock_gem_device.c | 3 ++ drivers/gpu/drm/xe/display/xe_display.c | 51 ++++++++++--------- drivers/gpu/drm/xe/display/xe_fb_pin.c | 2 +- drivers/gpu/drm/xe/xe_device_types.h | 3 +- 22 files changed, 111 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_conversion.c b/drivers/gpu/drm/i915/display/intel_display_conversion.c index 0578b68404da7..151d83fdbe379 100644 --- a/drivers/gpu/drm/i915/display/intel_display_conversion.c +++ b/drivers/gpu/drm/i915/display/intel_display_conversion.c @@ -5,7 +5,7 @@ struct intel_display *__i915_to_display(struct drm_i915_private *i915) { - return &i915->display; + return i915->display; } struct intel_display *__drm_to_display(struct drm_device *drm) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 43bd97e4f5898..8684cf8e4b7f0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -126,7 +126,7 @@ struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm, unsigned int alignment) { struct drm_i915_private *i915 = vm->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct i915_dpt *dpt = i915_vm_to_dpt(vm); struct ref_tracker *wakeref; struct i915_vma *vma; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index e9b809568cd42..92c04811aa28e 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -446,7 +446,7 @@ enum vbt_gmbus_ddi { * basically any of the fields to ensure the correct interpretation for the BDB * version in question. * - * When we copy the child device configs to dev_priv->display.vbt.child_dev, we + * When we copy the child device configs to display->vbt.child_dev, we * reserve space for the full structure below, and initialize the tail not * actually present in VBT to zeros. Accessing those fields is fine, as long as * the default zero is taken into account, again according to the BDB version. diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h b/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h index 9fbf14867a2a6..b6dc3d1b9bb13 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h @@ -77,7 +77,7 @@ i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj) * Set object's frontbuffer pointer. If frontbuffer is already set for the * object keep it and return it's pointer to the caller. Please note that RCU * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. This - * function is protected by i915->display.fb_tracking.lock + * function is protected by i915->display->fb_tracking.lock * * Return: pointer to frontbuffer which was set. */ diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index 0c723e7c71a2b..889e61843ff30 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -328,7 +328,7 @@ static bool fence_is_active(const struct i915_fence_reg *fence) static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt) { - struct intel_display *display = &ggtt->vm.i915->display; + struct intel_display *display = ggtt->vm.i915->display; struct i915_fence_reg *active = NULL; struct i915_fence_reg *fence, *fn; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 3182f19b98376..3b77b4bb88e33 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -70,7 +70,7 @@ static int __gt_unpark(struct intel_wakeref *wf) { struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; GT_TRACE(gt, "\n"); @@ -104,7 +104,7 @@ static int __gt_park(struct intel_wakeref *wf) struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); intel_wakeref_t wakeref = fetch_and_zero(>->awake); struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; GT_TRACE(gt, "\n"); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index dbdcfe130ad41..971fbff1211c3 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1205,7 +1205,7 @@ void intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t stalled_mask, const char *reason) { - struct intel_display *display = >->i915->display; + struct intel_display *display = gt->i915->display; intel_engine_mask_t awake; int ret; @@ -1423,7 +1423,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, /* Use a watchdog to ensure that our reset completes */ intel_wedge_on_timeout(&w, gt, 60 * HZ) { struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; bool need_display_reset; bool reset_display; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c619c6e2a76f4..74658835de1ac 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -550,7 +550,7 @@ static unsigned int init_emon(struct intel_uncore *uncore) static bool gen5_rps_enable(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_uncore *uncore = rps_to_uncore(rps); u8 fstart, vstart; u32 rgvmodectl; @@ -620,7 +620,7 @@ static bool gen5_rps_enable(struct intel_rps *rps) static void gen5_rps_disable(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_uncore *uncore = rps_to_uncore(rps); u16 rgvswctl; diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index f25ee2953baf5..2b5094e8de5e3 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1286,7 +1286,7 @@ static int gen8_decode_mi_display_flip(struct parser_exec_state *s, struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct plane_code_mapping gen8_plane_code[] = { [0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE}, [1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE}, @@ -1333,7 +1333,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s, struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu *vgpu = s->vgpu; u32 dword0 = cmd_val(s, 0); u32 dword1 = cmd_val(s, 1); @@ -1421,7 +1421,7 @@ static int gen8_update_plane_mmio_from_mi_display_flip( struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu *vgpu = s->vgpu; set_mask_bits(&vgpu_vreg_t(vgpu, info->surf_reg), GENMASK(31, 12), diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 1e1af5e545a41..b77e8f3ff75c8 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -69,7 +69,7 @@ static int get_edp_pipe(struct intel_vgpu *vgpu) static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; if (!(vgpu_vreg_t(vgpu, TRANSCONF(display, TRANSCODER_EDP)) & TRANSCONF_ENABLE)) return 0; @@ -82,7 +82,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; if (drm_WARN_ON(&dev_priv->drm, pipe < PIPE_A || pipe >= I915_MAX_PIPES)) @@ -183,7 +183,7 @@ static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { static void emulate_monitor_status_change(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int pipe; if (IS_BROXTON(dev_priv)) { @@ -634,7 +634,7 @@ void vgpu_update_vblank_emulation(struct intel_vgpu *vgpu, bool turnon) static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu_irq *irq = &vgpu->irq; int vblank_event[] = { [PIPE_A] = PIPE_A_VBLANK, @@ -664,7 +664,7 @@ static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) void intel_vgpu_emulate_vblank(struct intel_vgpu *vgpu) { struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; int pipe; mutex_lock(&vgpu->vgpu_lock); diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c index f9f7ef131371f..4cfe8d7f368d2 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.c +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -154,7 +154,7 @@ static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, u32 tiled, int stride_mask, int bpp) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(display, pipe)) & stride_mask; u32 stride = stride_reg; @@ -211,7 +211,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, struct intel_vgpu_primary_plane_format *plane) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 val, fmt; int pipe; @@ -342,7 +342,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, struct intel_vgpu_cursor_plane_format *plane) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 val, mode, index; u32 alpha_plane, alpha_force; int pipe; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 1344e6d20a34f..11cb8bf1fa4aa 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -658,7 +658,7 @@ static u32 skl_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; enum port port; u32 dp_br, link_m, link_n, htotal, vtotal; @@ -1022,7 +1022,7 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 pipe = DSPSURF_TO_PIPE(display, offset); int event = SKL_FLIP_EVENT(pipe, PLANE_PRIMARY); @@ -1064,7 +1064,7 @@ static int reg50080_mmio_write(struct intel_vgpu *vgpu, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; enum pipe pipe = REG_50080_TO_PIPE(offset); enum plane_id plane = REG_50080_TO_PLANE(offset); int event = SKL_FLIP_EVENT(pipe, plane); @@ -2200,7 +2200,7 @@ static int csfe_chicken1_mmio_write(struct intel_vgpu *vgpu, static int init_generic_mmio_info(struct intel_gvt *gvt) { struct drm_i915_private *dev_priv = gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int ret; MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 134a1c3d1f9d1..5c69d14a7673e 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,7 +115,7 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; /* * The i915 workqueue is primarily used for batched retirement of @@ -163,7 +163,7 @@ out_err: static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; destroy_workqueue(dev_priv->unordered_wq); destroy_workqueue(display->hotplug.dp_wq); @@ -226,7 +226,7 @@ static void sanitize_gpu(struct drm_i915_private *i915) */ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int ret = 0; if (i915_inject_probe_failure(dev_priv)) @@ -289,7 +289,7 @@ err_workqueues: */ static void i915_driver_late_release(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; intel_irq_fini(dev_priv); intel_power_domains_cleanup(display); @@ -317,7 +317,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) */ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; int ret, i; @@ -464,7 +464,7 @@ static int i915_pcode_init(struct drm_i915_private *i915) */ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); int ret; @@ -603,7 +603,7 @@ err_perf: */ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); i915_perf_fini(dev_priv); @@ -623,7 +623,7 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) */ static int i915_driver_register(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; unsigned int i; int ret; @@ -674,7 +674,7 @@ static int i915_driver_register(struct drm_i915_private *dev_priv) */ static void i915_driver_unregister(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; unsigned int i; @@ -760,6 +760,9 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, match_info); + /* TODO: Allocate display dynamically. */ + i915->display = &i915->__display; + intel_display_device_probe(pdev); return i915; @@ -794,7 +797,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return PTR_ERR(i915); } - display = &i915->display; + display = i915->display; ret = i915_driver_early_probe(i915); if (ret < 0) @@ -886,7 +889,7 @@ out_pci_disable: void i915_driver_remove(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; intel_wakeref_t wakeref; wakeref = intel_runtime_pm_get(&i915->runtime_pm); @@ -919,7 +922,7 @@ void i915_driver_remove(struct drm_i915_private *i915) static void i915_driver_release(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; intel_wakeref_t wakeref; @@ -973,7 +976,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) void i915_driver_shutdown(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; disable_rpm_wakeref_asserts(&i915->runtime_pm); intel_runtime_pm_disable(&i915->runtime_pm); @@ -1053,7 +1056,7 @@ static int i915_drm_prepare(struct drm_device *dev) static int i915_drm_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); pci_power_t opregion_target_state; @@ -1103,7 +1106,7 @@ static int i915_drm_suspend(struct drm_device *dev) static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct intel_gt *gt; @@ -1175,7 +1178,7 @@ int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, static int i915_drm_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; int ret, i; @@ -1260,7 +1263,7 @@ static int i915_drm_resume(struct drm_device *dev) static int i915_drm_resume_early(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_gt *gt; int ret, i; @@ -1492,7 +1495,7 @@ static int i915_pm_restore(struct device *kdev) static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct pci_dev *root_pdev; @@ -1591,7 +1594,7 @@ static int intel_runtime_suspend(struct device *kdev) static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct pci_dev *root_pdev; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 93b4c504b7100..0841988c4a671 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -177,7 +177,8 @@ struct i915_selftest_stash { struct drm_i915_private { struct drm_device drm; - struct intel_display display; + struct intel_display *display; + struct intel_display __display; /* Transitional. Do not use directly. */ /* FIXME: Device release actions should all be moved to drmm_ */ bool do_release; diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index be8149e462817..6fcda6d7b5b73 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -16,7 +16,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_i915_private *i915 = to_i915(dev); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct pci_dev *pdev = to_pci_dev(dev->dev); const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu; drm_i915_getparam_t *param = data; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 4f785cdbd1553..f434b6825fc28 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -2067,7 +2067,7 @@ static struct i915_gpu_coredump * __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct i915_gpu_coredump *error; /* Check if GPU capture has been disabled */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index cc05f347555ad..351928481cd9e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -230,7 +230,7 @@ out: static irqreturn_t valleyview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -324,7 +324,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) static irqreturn_t cherryview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -418,7 +418,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) static irqreturn_t ilk_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; void __iomem * const regs = intel_uncore_regs(&i915->uncore); u32 de_iir, gt_iir, de_ier, sde_ier = 0; irqreturn_t ret = IRQ_NONE; @@ -507,7 +507,7 @@ static inline void gen8_master_intr_enable(void __iomem * const regs) static irqreturn_t gen8_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; void __iomem * const regs = intel_uncore_regs(&dev_priv->uncore); u32 master_ctl; @@ -558,7 +558,7 @@ static inline void gen11_master_intr_enable(void __iomem * const regs) static irqreturn_t gen11_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; void __iomem * const regs = intel_uncore_regs(&i915->uncore); struct intel_gt *gt = to_gt(i915); u32 master_ctl; @@ -616,7 +616,7 @@ static inline void dg1_master_intr_enable(void __iomem * const regs) static irqreturn_t dg1_irq_handler(int irq, void *arg) { struct drm_i915_private * const i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_gt *gt = to_gt(i915); void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 master_tile_ctl, master_ctl; @@ -660,7 +660,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) static void ilk_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; gen2_irq_reset(uncore, DE_IRQ_REGS); @@ -681,7 +681,7 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv) static void valleyview_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); @@ -693,7 +693,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv) static void gen8_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; gen8_master_intr_disable(intel_uncore_regs(uncore)); @@ -705,7 +705,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) static void gen11_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt = to_gt(dev_priv); struct intel_uncore *uncore = gt->uncore; @@ -720,7 +720,7 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv) static void dg1_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; struct intel_gt *gt; unsigned int i; @@ -740,7 +740,7 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv) static void cherryview_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); @@ -755,7 +755,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen5_gt_irq_postinstall(to_gt(dev_priv)); @@ -764,7 +764,7 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen5_gt_irq_postinstall(to_gt(dev_priv)); @@ -776,7 +776,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen8_gt_irq_postinstall(to_gt(dev_priv)); gen8_de_irq_postinstall(display); @@ -786,7 +786,7 @@ static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt = to_gt(dev_priv); struct intel_uncore *uncore = gt->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; @@ -802,7 +802,7 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; struct intel_gt *gt; @@ -821,7 +821,7 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen8_gt_irq_postinstall(to_gt(dev_priv)); @@ -894,7 +894,7 @@ static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, static void i915_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; i9xx_display_irq_reset(display); @@ -906,7 +906,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) static void i915_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; @@ -941,7 +941,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv) static irqreturn_t i915_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -996,7 +996,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) static void i965_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; i9xx_display_irq_reset(display); @@ -1027,7 +1027,7 @@ static u32 i965_error_mask(struct drm_i915_private *i915) static void i965_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; @@ -1059,7 +1059,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv) static irqreturn_t i965_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -1256,7 +1256,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv) */ void intel_irq_uninstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int irq = to_pci_dev(dev_priv->drm.dev)->irq; if (drm_WARN_ON(&dev_priv->drm, !dev_priv->irqs_enabled)) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 892b1e19d9461..5bbf891ccc32c 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -201,7 +201,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *i915) static void cpt_init_clock_gating(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; enum pipe pipe; u32 val; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index a77e5b26542ce..0ea12c68cedb2 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -180,6 +180,9 @@ struct drm_i915_private *mock_gem_device(void) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, &mock_info); + /* TODO: Allocate display dynamically. */ + i915->display = &i915->__display; + intel_display_device_probe(pdev); dev_pm_domain_set(&pdev->dev, &pm_domain); diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b8030492fbd10..699f401eff101 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -38,7 +38,7 @@ static bool has_display(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; return HAS_DISPLAY(display); } @@ -86,7 +86,7 @@ static void unset_display_features(struct xe_device *xe) static void display_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; destroy_workqueue(display->hotplug.dp_wq); } @@ -104,7 +104,10 @@ static void display_destroy(struct drm_device *dev, void *dummy) */ int xe_display_create(struct xe_device *xe) { - struct intel_display *display = &xe->display; + /* TODO: Allocate display dynamically. */ + struct intel_display *display = &xe->__display; + + xe->display = &xe->__display; spin_lock_init(&display->fb_tracking.lock); @@ -116,7 +119,7 @@ int xe_display_create(struct xe_device *xe) static void xe_display_fini_early(void *arg) { struct xe_device *xe = arg; - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -129,7 +132,7 @@ static void xe_display_fini_early(void *arg) int xe_display_init_early(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; int err; if (!xe->info.probe_display) @@ -173,7 +176,7 @@ err_opregion: static void xe_display_fini(void *arg) { struct xe_device *xe = arg; - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; intel_hpd_poll_fini(display); intel_hdcp_component_fini(display); @@ -183,7 +186,7 @@ static void xe_display_fini(void *arg) int xe_display_init(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; int err; if (!xe->info.probe_display) @@ -198,7 +201,7 @@ int xe_display_init(struct xe_device *xe) void xe_display_register(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -209,7 +212,7 @@ void xe_display_register(struct xe_device *xe) void xe_display_unregister(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -222,7 +225,7 @@ void xe_display_unregister(struct xe_device *xe) void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -233,7 +236,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -244,7 +247,7 @@ void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) void xe_display_irq_reset(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -254,7 +257,7 @@ void xe_display_irq_reset(struct xe_device *xe) void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -295,7 +298,7 @@ static void xe_display_flush_cleanup_work(struct xe_device *xe) static void xe_display_enable_d3cold(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -318,7 +321,7 @@ static void xe_display_enable_d3cold(struct xe_device *xe) static void xe_display_disable_d3cold(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -342,7 +345,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe) void xe_display_pm_suspend(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); if (!xe->info.probe_display) @@ -377,7 +380,7 @@ void xe_display_pm_suspend(struct xe_device *xe) void xe_display_pm_shutdown(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -408,7 +411,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) void xe_display_pm_runtime_suspend(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -423,7 +426,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe) void xe_display_pm_suspend_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); if (!xe->info.probe_display) @@ -434,7 +437,7 @@ void xe_display_pm_suspend_late(struct xe_device *xe) void xe_display_pm_runtime_suspend_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -452,7 +455,7 @@ void xe_display_pm_runtime_suspend_late(struct xe_device *xe) void xe_display_pm_shutdown_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -467,7 +470,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe) void xe_display_pm_resume_early(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -477,7 +480,7 @@ void xe_display_pm_resume_early(struct xe_device *xe) void xe_display_pm_resume(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -512,7 +515,7 @@ void xe_display_pm_resume(struct xe_device *xe) void xe_display_pm_runtime_resume(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index e95ca979e1fe3..c2b4be72f7a00 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -389,7 +389,7 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, { struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); struct xe_device *xe = to_xe_device(fb->base.dev); - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; struct i915_vma *vma; if (old_plane_state->hw.fb == new_plane_state->hw.fb && diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 06c65dace0264..634ac4aa7674b 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -587,7 +587,8 @@ struct xe_device { * drm_i915_private during build. After cleanup these should go away, * migrating to the right sub-structs */ - struct intel_display display; + struct intel_display *display; + struct intel_display __display; /* Transitional. Do not use directly. */ struct dram_info { bool wm_lv_0_adjust_needed; -- GitLab From 24560c53664881ed833ace50febc48366b0d56a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:52 +0300 Subject: [PATCH 077/902] drm/i915/dmc: Drop PIPEDMC faults from the fault mask on LNL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On LNL+ PIPEDMC faults are reported via PIPEDMC interrupts instead of the direct DE_PIPE_* reporting used on earlier platforms. Drop the relevant bits from the fault mask. The bits are tied to zero on LNL, so there is no danger of spurious fault interrupts even with an incorrect mask. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-2-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_display_irq.c | 10 +++++++++- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 3e73832e5e813..a7130b14aacee 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -1016,7 +1016,15 @@ static u32 gen8_de_port_aux_mask(struct intel_display *display) static u32 gen8_de_pipe_fault_mask(struct intel_display *display) { - if (DISPLAY_VER(display) >= 14) + if (DISPLAY_VER(display) >= 20) + return MTL_PLANE_ATS_FAULT | + GEN9_PIPE_CURSOR_FAULT | + GEN11_PIPE_PLANE5_FAULT | + GEN9_PIPE_PLANE4_FAULT | + GEN9_PIPE_PLANE3_FAULT | + GEN9_PIPE_PLANE2_FAULT | + GEN9_PIPE_PLANE1_FAULT; + else if (DISPLAY_VER(display) >= 14) return MTL_PIPEDMC_ATS_FAULT | MTL_PLANE_ATS_FAULT | GEN12_PIPEDMC_FAULT | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2e4190da3e0d8..2d0e04eae7630 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2126,8 +2126,8 @@ #define GEN8_PIPE_CDCLK_CRC_ERROR REG_BIT(29) #define GEN8_PIPE_CDCLK_CRC_DONE REG_BIT(28) #define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */ -#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl+ */ -#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl+ */ +#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl-mtl */ +#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl */ #define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */ #define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */ -- GitLab From f91ee1a21c3716fb853d5a0d83850a1906675a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 14 May 2025 20:42:57 +0300 Subject: [PATCH 078/902] drm/i915/dmc: Hook up PIPEDMC interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hook up PIPEDMC interrupts. We'll need these for: - flip queue signalling - GTT/ATS faults on LNL+ - unclaimed register access errors (supposedly that is what the error interrupt indicated according to Windows code). On LNL+ we get a new level of interrupts registers PIPEDMC_INTERRUPT*. On earlier platforms we only have the INT_VECTOR field in the PIPEDMC_STATUS registers, whose values are defined by the firmware. For now we'll enable the interrupts on LNL+ only. For earlier platforms it's not clear that there is any use for these interrupts, and some ADL machines have exhibited spurious DE_PIPE interrupts with the PIPEDMC interrupts unmasked/enabled. We can revisit enabling these for earlier platforms in the future. For some unknown reason LNL pipe B triggers the error interrupt during the first DC state transition (subsequent transitions are maybe OK?). No clear idea what's going on here yet, so keep the error interrupt disabled for now. Similar to DSB interrupt registers, the unused bits in PIPEDMC_INTERRUPT* seem to act like randomg r/w bits (instead of being hardwired to 0 like one would expect), and so we'll try to avoid setting them so that we don't mistake them for real interrupts. v2: Only enable/unmask for LNL+ Keep the flip queue interrupt masked off for now since we don't have a use for it yet v3: Also keep the error interrupt masked off for now due to LNL pipe B triggering it Reviewed-by: Luca Coelho Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250514174257.8708-1-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_device.h | 1 + .../gpu/drm/i915/display/intel_display_irq.c | 8 +++ drivers/gpu/drm/i915/display/intel_dmc.c | 49 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 2 + drivers/gpu/drm/i915/display/intel_dmc_regs.h | 22 +++++++++ drivers/gpu/drm/i915/i915_reg.h | 2 + 6 files changed, 84 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index fe14a92ae8c65..f0ea56cc5def5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -182,6 +182,7 @@ struct intel_display_platforms { #define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14) #define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12) #define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay) +#define HAS_PIPEDMC(__display) (DISPLAY_VER(__display) >= 12) #define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr) #define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking) #define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index a7130b14aacee..c24841f57aac4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -17,6 +17,7 @@ #include "intel_display_rps.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_dmc.h" #include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" @@ -1449,6 +1450,9 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) intel_dsb_irq_handler(display, pipe, INTEL_DSB_2); } + if (HAS_PIPEDMC(display) && iir & GEN12_PIPEDMC_INTERRUPT) + intel_pipedmc_irq_handler(display, pipe); + if (iir & GEN8_PIPE_CDCLK_CRC_DONE) hsw_pipe_crc_irq_handler(display, pipe); @@ -2266,6 +2270,10 @@ void gen8_de_irq_postinstall(struct intel_display *display) GEN12_DSB_INT(INTEL_DSB_1) | GEN12_DSB_INT(INTEL_DSB_2); + /* TODO figure PIPEDMC interrupts for pre-LNL */ + if (DISPLAY_VER(display) >= 20) + de_pipe_masked |= GEN12_PIPEDMC_INTERRUPT; + de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(display); diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index b58189d24e7e4..16dc52a8302c8 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -27,9 +27,11 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_crtc.h" #include "intel_de.h" #include "intel_display_rpm.h" #include "intel_display_power_well.h" +#include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dmc_regs.h" #include "intel_step.h" @@ -490,6 +492,17 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable) adlp_pipedmc_clock_gating_wa(display, enable); } +static u32 pipedmc_interrupt_mask(struct intel_display *display) +{ + /* + * FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B + * triggering it during the first DC state transition. Figure + * out what is going on... + */ + return PIPEDMC_GTT_FAULT | + PIPEDMC_ATS_FAULT; +} + void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe) { enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe); @@ -497,6 +510,11 @@ void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe) if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id)) return; + if (DISPLAY_VER(display) >= 20) { + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display)); + intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~pipedmc_interrupt_mask(display)); + } + if (DISPLAY_VER(display) >= 14) intel_de_rmw(display, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe)); else @@ -514,6 +532,11 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe) intel_de_rmw(display, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0); else intel_de_rmw(display, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0); + + if (DISPLAY_VER(display) >= 20) { + intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~0); + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display)); + } } /** @@ -1403,3 +1426,29 @@ void intel_dmc_debugfs_register(struct intel_display *display) debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root, display, &intel_dmc_debugfs_status_fops); } + +void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe) +{ + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); + u32 tmp; + + if (DISPLAY_VER(display) >= 20) { + tmp = intel_de_read(display, PIPEDMC_INTERRUPT(pipe)); + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), tmp); + + if (tmp & PIPEDMC_ATS_FAULT) + drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC ATS fault\n", + crtc->base.base.id, crtc->base.name); + if (tmp & PIPEDMC_GTT_FAULT) + drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC GTT fault\n", + crtc->base.base.id, crtc->base.name); + if (tmp & PIPEDMC_ERROR) + drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC error\n", + crtc->base.base.id, crtc->base.name); + } + + tmp = intel_de_read(display, PIPEDMC_STATUS(pipe)) & PIPEDMC_INT_VECTOR_MASK; + if (tmp) + drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC interrupt vector 0x%x\n", + crtc->base.base.id, crtc->base.name, tmp); +} diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index bd1c459b00757..a98e8deff13aa 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -34,4 +34,6 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display, bool star void assert_dmc_loaded(struct intel_display *display); +void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe); + #endif /* __INTEL_DMC_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index e16ea3f16ed88..e8ac0e1be7649 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -27,6 +27,28 @@ _MTL_PIPEDMC_EVT_CTL_4_A, \ _MTL_PIPEDMC_EVT_CTL_4_B) +#define _PIPEDMC_STATUS_A 0x5f06c +#define _PIPEDMC_STATUS_B 0x5f46c +#define PIPEDMC_STATUS(pipe) _MMIO_PIPE((pipe), _PIPEDMC_STATUS_A, _PIPEDMC_STATUS_B) +#define PIPEDMC_SSP REG_GENMASK(31, 16) +#define PIPEDMC_INT_VECTOR_MASK REG_GENMASK(15, 8) +/* PIPEDMC_INT_VECTOR values defined by firmware */ +#define PIPEDMC_INT_VECTOR_SCANLINE_COMP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x1) +#define PIPEDMC_INT_VECTOR_DC6V_FLIPQ_OVERLAP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x2) +#define PIPEDMC_INT_VECTOR_FLIPQ_PROG_DONE REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0xff) /* Wa_16018781658:lnl[a0] */ +#define PIPEDMC_EVT_PENDING REG_GENMASK(7, 0) + +#define _PIPEDMC_INTERRUPT_A 0x5f190 /* lnl+ */ +#define _PIPEDMC_INTERRUPT_B 0x5f590 /* lnl+ */ +#define PIPEDMC_INTERRUPT(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_A, _PIPEDMC_INTERRUPT_B) +#define _PIPEDMC_INTERRUPT_MASK_A 0x5f194 /* lnl+ */ +#define _PIPEDMC_INTERRUPT_MASK_B 0x5f594 /* lnl+ */ +#define PIPEDMC_INTERRUPT_MASK(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_MASK_A, _PIPEDMC_INTERRUPT_MASK_B) +#define PIPEDMC_FLIPQ_PROG_DONE REG_BIT(3) +#define PIPEDMC_ERROR REG_BIT(2) +#define PIPEDMC_GTT_FAULT REG_BIT(1) +#define PIPEDMC_ATS_FAULT REG_BIT(0) + #define PIPEDMC_BLOCK_PKGC_SW_A 0x5f1d0 #define PIPEDMC_BLOCK_PKGC_SW_B 0x5F5d0 #define PIPEDMC_BLOCK_PKGC_SW(pipe) _MMIO_PIPE(pipe, \ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2d0e04eae7630..8822c639a4f4b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2128,12 +2128,14 @@ #define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */ #define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl-mtl */ #define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl */ +#define GEN12_PIPEDMC_FLIPQ_DONE REG_BIT(24) /* tgl-adl */ #define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */ #define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */ #define GEN12_PIPE_VBLANK_UNMOD REG_BIT(19) /* tgl+ */ #define MTL_PLANE_ATS_FAULT REG_BIT(18) /* mtl+ */ #define GEN11_PIPE_PLANE7_FLIP_DONE REG_BIT(18) /* icl/tgl */ +#define MTL_PIPEDMC_FLIPQ_DONE REG_BIT(17) /* mtl */ #define GEN11_PIPE_PLANE6_FLIP_DONE REG_BIT(17) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FLIP_DONE REG_BIT(16) /* icl+ */ #define GEN12_DSB_2_INT REG_BIT(15) /* tgl+ */ -- GitLab From 50a9875122ac0de222d617b233871f85418c7eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:54 +0300 Subject: [PATCH 079/902] drm/i915/dmc: Define all DMC event IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define all the DMC event IDs to make life less misrable when having to deal with these. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-4-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 12 +- drivers/gpu/drm/i915/display/intel_dmc_regs.h | 271 +++++++++++++++++- 2 files changed, 272 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 16dc52a8302c8..e9aee3d5daf69 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -427,7 +427,7 @@ static void disable_event_handler(struct intel_display *display, REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE)); + DMC_EVENT_FALSE)); intel_de_write(display, htp_reg, 0); } @@ -576,10 +576,10 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_VBLANK_A); + PIPEDMC_EVENT_VBLANK); else val = REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE) | + DMC_EVENT_FALSE) | REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1); @@ -620,12 +620,12 @@ static bool disable_dmc_evt(struct intel_display *display, /* also disable the flip queue event on the main DMC on TGL */ if (display->platform.tigerlake && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_CLK_MSEC) + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_CLK_MSEC) return true; /* also disable the HRR event on the main DMC on TGL/ADLS */ if ((display->platform.tigerlake || display->platform.alderlake_s) && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_VBLANK_A) + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_VBLANK_A) return true; return false; @@ -641,7 +641,7 @@ static u32 dmc_mmiodata(struct intel_display *display, return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE); + DMC_EVENT_FALSE); else return dmc->dmc_info[dmc_id].mmiodata[i]; } diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index e8ac0e1be7649..edd4e69319b97 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -8,6 +8,272 @@ #include "i915_reg_defs.h" +enum dmc_event_id { + DMC_EVENT_TRUE = 0x0, + DMC_EVENT_FALSE = 0x1, +}; + +enum maindmc_event_id { + MAINDMC_EVENT_CMP_ZERO = 0x8, + MAINDMC_EVENT_CMP_ODD = 0x9, + MAINDMC_EVENT_CMP_NEG = 0xa, + MAINDMC_EVENT_CMP_CARRY = 0xb, + + MAINDMC_EVENT_TMR0_DONE = 0x14, + MAINDMC_EVENT_TMR1_DONE = 0x15, + MAINDMC_EVENT_TMR2_DONE = 0x16, + MAINDMC_EVENT_COUNT0_DONE = 0x17, + MAINDMC_EVENT_COUNT1_DONE = 0x18, + MAINDMC_EVENT_PERF_CNTR_DARBF = 0x19, + + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_A_TRIGGER = 0x22, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_B_TRIGGER = 0x23, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_C_TRIGGER = 0x24, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_D_TRIGGER = 0x25, + MAINDMC_EVENT_1KHZ_FQ_A_TRIGGER = 0x26, + MAINDMC_EVENT_1KHZ_FQ_B_TRIGGER = 0x27, + MAINDMC_EVENT_1KHZ_FQ_C_TRIGGER = 0x28, + MAINDMC_EVENT_1KHZ_FQ_D_TRIGGER = 0x29, + MAINDMC_EVENT_SCANLINE_COMP_A = 0x2a, + MAINDMC_EVENT_SCANLINE_COMP_B = 0x2b, + MAINDMC_EVENT_SCANLINE_COMP_C = 0x2c, + MAINDMC_EVENT_SCANLINE_COMP_D = 0x2d, + MAINDMC_EVENT_VBLANK_DELAYED_A = 0x2e, + MAINDMC_EVENT_VBLANK_DELAYED_B = 0x2f, + MAINDMC_EVENT_VBLANK_DELAYED_C = 0x30, + MAINDMC_EVENT_VBLANK_DELAYED_D = 0x31, + MAINDMC_EVENT_VBLANK_A = 0x32, + MAINDMC_EVENT_VBLANK_B = 0x33, + MAINDMC_EVENT_VBLANK_C = 0x34, + MAINDMC_EVENT_VBLANK_D = 0x35, + MAINDMC_EVENT_HBLANK_A = 0x36, + MAINDMC_EVENT_HBLANK_B = 0x37, + MAINDMC_EVENT_HBLANK_C = 0x38, + MAINDMC_EVENT_HBLANK_D = 0x39, + MAINDMC_EVENT_VSYNC_A = 0x3a, + MAINDMC_EVENT_VSYNC_B = 0x3b, + MAINDMC_EVENT_VSYNC_C = 0x3c, + MAINDMC_EVENT_VSYNC_D = 0x3d, + MAINDMC_EVENT_SCANLINE_A = 0x3e, + MAINDMC_EVENT_SCANLINE_B = 0x3f, + MAINDMC_EVENT_SCANLINE_C = 0x40, + MAINDMC_EVENT_SCANLINE_D = 0x41, + + MAINDMC_EVENT_PLANE1_FLIP_A = 0x42, + MAINDMC_EVENT_PLANE2_FLIP_A = 0x43, + MAINDMC_EVENT_PLANE3_FLIP_A = 0x44, + MAINDMC_EVENT_PLANE4_FLIP_A = 0x45, + MAINDMC_EVENT_PLANE5_FLIP_A = 0x46, + MAINDMC_EVENT_PLANE6_FLIP_A = 0x47, + MAINDMC_EVENT_PLANE7_FLIP_A = 0x48, + MAINDMC_EVENT_PLANE1_FLIP_B = 0x49, + MAINDMC_EVENT_PLANE2_FLIP_B = 0x4a, + MAINDMC_EVENT_PLANE3_FLIP_B = 0x4b, + MAINDMC_EVENT_PLANE4_FLIP_B = 0x4c, + MAINDMC_EVENT_PLANE5_FLIP_B = 0x4d, + MAINDMC_EVENT_PLANE6_FLIP_B = 0x4e, + MAINDMC_EVENT_PLANE7_FLIP_B = 0x4f, + MAINDMC_EVENT_PLANE1_FLIP_C = 0x50, + MAINDMC_EVENT_PLANE2_FLIP_C = 0x51, + MAINDMC_EVENT_PLANE3_FLIP_C = 0x52, + MAINDMC_EVENT_PLANE4_FLIP_C = 0x53, + MAINDMC_EVENT_PLANE5_FLIP_C = 0x54, + MAINDMC_EVENT_PLANE6_FLIP_C = 0x55, + MAINDMC_EVENT_PLANE7_FLIP_C = 0x56, + MAINDMC_EVENT_PLANE1_FLIP_D = 0x57, + MAINDMC_EVENT_PLANE2_FLIP_D = 0x58, + MAINDMC_EVENT_PLANE3_FLIP_D = 0x59, + MAINDMC_EVENT_PLANE4_FLIP_D = 0x5a, + MAINDMC_EVENT_PLANE5_FLIP_D = 0x5b, + MAINDMC_EVENT_PLANE6_FLIP_D = 0x5c, + MAINDMC_EVENT_PLANE7_FLIP_D = 0x5d, + MAINDMC_EVENT_PLANE1_FLIP_DONE_A = 0x5e, + MAINDMC_EVENT_PLANE2_FLIP_DONE_A = 0x5f, + MAINDMC_EVENT_PLANE3_FLIP_DONE_A = 0x60, + MAINDMC_EVENT_PLANE4_FLIP_DONE_A = 0x61, + MAINDMC_EVENT_PLANE5_FLIP_DONE_A = 0x62, + MAINDMC_EVENT_PLANE6_FLIP_DONE_A = 0x63, + MAINDMC_EVENT_PLANE7_FLIP_DONE_A = 0x64, + MAINDMC_EVENT_PLANE1_FLIP_DONE_B = 0x65, + MAINDMC_EVENT_PLANE2_FLIP_DONE_B = 0x66, + MAINDMC_EVENT_PLANE3_FLIP_DONE_B = 0x67, + MAINDMC_EVENT_PLANE4_FLIP_DONE_B = 0x68, + MAINDMC_EVENT_PLANE5_FLIP_DONE_B = 0x69, + MAINDMC_EVENT_PLANE6_FLIP_DONE_B = 0x6a, + MAINDMC_EVENT_PLANE7_FLIP_DONE_B = 0x6b, + MAINDMC_EVENT_PLANE1_FLIP_DONE_C = 0x6c, + MAINDMC_EVENT_PLANE2_FLIP_DONE_C = 0x6d, + MAINDMC_EVENT_PLANE3_FLIP_DONE_C = 0x6e, + MAINDMC_EVENT_PLANE4_FLIP_DONE_C = 0x6f, + MAINDMC_EVENT_PLANE5_FLIP_DONE_C = 0x70, + MAINDMC_EVENT_PLANE6_FLIP_DONE_C = 0x71, + MAINDMC_EVENT_PLANE7_FLIP_DONE_C = 0x72, + MAINDMC_EVENT_PLANE1_FLIP_DONE_D = 0x73, + MAINDMC_EVENT_PLANE2_FLIP_DONE_D = 0x74, + MAINDMC_EVENT_PLANE3_FLIP_DONE_D = 0x75, + MAINDMC_EVENT_PLANE4_FLIP_DONE_D = 0x76, + MAINDMC_EVENT_PLANE5_FLIP_DONE_D = 0x77, + MAINDMC_EVENT_PLANE6_FLIP_DONE_D = 0x78, + MAINDMC_EVENT_PLANE7_FLIP_DONE_D = 0x79, + + MAINDMC_EVENT_WIDI_GTT_FAULT_SL1 = 0x7d, + MAINDMC_EVENT_WIDI_GTT_FAULT_SL2 = 0x7e, + MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL1 = 0x7f, + MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL2 = 0x80, + + MAINDMC_EVENT_RENUKE_A = 0x85, + MAINDMC_EVENT_RENUKE_B = 0x86, + MAINDMC_EVENT_RENUKE_C = 0x87, + MAINDMC_EVENT_RENUKE_D = 0x88, + MAINDMC_EVENT_DPFC_FIFO_FULL_A = 0x89, + MAINDMC_EVENT_DPFC_FIFO_FULL_B = 0x8a, + MAINDMC_EVENT_DPFC_FIFO_FULL_C = 0x8b, + MAINDMC_EVENT_DPFC_FIFO_FULL_D = 0x8c, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_A = 0x8d, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_B = 0x8e, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_C = 0x8f, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_D = 0x90, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_A = 0x91, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_B = 0x92, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_C = 0x93, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_D = 0x94, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_A = 0x95, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_B = 0x96, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_C = 0x97, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_D = 0x98, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_A = 0x99, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_B = 0x9a, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_C = 0x9b, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_D = 0x9c, + MAINDMC_EVENT_DISP_PCH_INT = 0x9d, + MAINDMC_EVENT_GTT_ERR = 0x9e, + MAINDMC_EVENT_VTD_ERR = 0x9f, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_A = 0xa0, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_B = 0xa1, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_C = 0xa2, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_D = 0xa3, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_A = 0xa4, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_B = 0xa5, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_C = 0xa6, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_D = 0xa7, + + MAINDMC_EVENT_DC_CLOCK_OFF_START_EDP = 0xb2, + MAINDMC_EVENT_DC_CLOCK_OFF_START_DSI = 0xb3, + MAINDMC_EVENT_DCPR_DMC_CSR_START = 0xb4, + MAINDMC_EVENT_IN_PSR = 0xb5, + + MAINDMC_EVENT_IN_MEMUP = 0xb7, + MAINDMC_EVENT_IN_VGA = 0xb8, + + MAINDMC_EVENT_IN_KVM_SESSION = 0xba, + MAINDMC_EVENT_DEWAKE = 0xbb, + + MAINDMC_EVENT_TRAP_HIT = 0xbd, + MAINDMC_EVENT_CLK_USEC = 0xbe, + MAINDMC_EVENT_CLK_MSEC = 0xbf, + + MAINDMC_EVENT_CHICKEN1 = 0xc8, + MAINDMC_EVENT_CHICKEN2 = 0xc9, + MAINDMC_EVENT_CHICKEN3 = 0xca, + MAINDMC_EVENT_DDT_UBP = 0xcb, + + MAINDMC_EVENT_HP_LATENCY = 0xcd, + MAINDMC_EVENT_LP_LATENCY = 0xce, + MAINDMC_EVENT_WIDI_LP_REQ_SL1 = 0xcf, + MAINDMC_EVENT_WIDI_LP_REQ_SL2 = 0xd0, + + MAINDMC_EVENT_DG_DMC_EVT_0 = 0xd3, + MAINDMC_EVENT_DG_DMC_EVT_1 = 0xd4, + MAINDMC_EVENT_DG_DMC_EVT_2 = 0xd5, + MAINDMC_EVENT_DG_DMC_EVT_3 = 0xd6, + MAINDMC_EVENT_DG_DMC_EVT_4 = 0xd7, + MAINDMC_EVENT_DACFE_CLK_STOP = 0xd8, + MAINDMC_EVENT_DACFE_AZILIA_SDI_WAKE = 0xd9, + MAINDMC_EVENT_AUDIO_DOUBLE_FUNC_GRP_RST = 0xda, + MAINDMC_EVENT_AUDIO_CMD_VALID = 0xdb, + MAINDMC_EVENT_AUDIO_FRM_SYNC_BCLK = 0xdc, + MAINDMC_EVENT_AUDIO_FRM_SYNC_CDCLK = 0xdd, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_A = 0xde, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_B = 0xdf, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_C = 0xe0, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_E = 0xe1, + MAINDMC_EVENT_CMTG_SCANLINE_IN_GB_DC6v = 0xe2, + MAINDMC_EVENT_DCPR_CMTG_SCANLINE_OUTSIDE_GB = 0xe3, + MAINDMC_EVENT_DC6v_BACKWARD_COMPAT = 0xe4, + MAINDMC_EVENT_DPMA_PM_ABORT = 0xe5, + + MAINDMC_EVENT_STACK_OVF = 0xfc, + MAINDMC_EVENT_NO_CLAIM = 0xfd, + MAINDMC_EVENT_UNK_CMD = 0xfe, + MAINDMC_EVENT_HTP_MOD = 0xff, +}; + +enum pipedmc_event_id { + PIPEDMC_EVENT_TMR0_DONE = 0x14, + PIPEDMC_EVENT_TMR1_DONE = 0x15, + PIPEDMC_EVENT_TMR2_DONE = 0x16, + PIPEDMC_EVENT_COUNT0_DONE = 0x17, + PIPEDMC_EVENT_COUNT1_DONE = 0x18, + PIPEDMC_EVENT_PGA_PGB_RESTORE_DONE = 0x19, + PIPEDMC_EVENT_PG1_PG2_RESTORE_DONE = 0x1a, + PIPEDMC_EVENT_PGA_PGB_SAVE_DONE = 0x1b, + PIPEDMC_EVENT_PG1_PG2_SAVE_DONE = 0x1c, + + PIPEDMC_EVENT_FULL_FQ_WAKE_TRIGGER = 0x2b, + PIPEDMC_EVENT_1KHZ_FQ_TRIGGER = 0x2c, + PIPEDMC_EVENT_SCANLINE_INRANGE_FQ_TRIGGER = 0x2d, + PIPEDMC_EVENT_SCANLINE_INRANGE = 0x2e, + PIPEDMC_EVENT_SCANLINE_OUTRANGE = 0x2f, + PIPEDMC_EVENT_SCANLINE_EQUAL = 0x30, + PIPEDMC_EVENT_DELAYED_VBLANK = 0x31, + PIPEDMC_EVENT_VBLANK = 0x32, + PIPEDMC_EVENT_HBLANK = 0x33, + PIPEDMC_EVENT_VSYNC = 0x34, + PIPEDMC_EVENT_SCANLINE_FROM_DMUX = 0x35, + PIPEDMC_EVENT_PLANE1_FLIP = 0x36, + PIPEDMC_EVENT_PLANE2_FLIP = 0x37, + PIPEDMC_EVENT_PLANE3_FLIP = 0x38, + PIPEDMC_EVENT_PLANE4_FLIP = 0x39, + PIPEDMC_EVENT_PLANE5_FLIP = 0x3a, + PIPEDMC_EVENT_PLANE6_FLIP = 0x3b, + PIPEDMC_EVENT_PLANE7_FLIP = 0x3c, + PIPEDMC_EVENT_ADAPTIVE_DCB_TRIGGER = 0x3d, + + PIPEDMC_EVENT_PLANE1_FLIP_DONE = 0x56, + PIPEDMC_EVENT_PLANE2_FLIP_DONE = 0x57, + PIPEDMC_EVENT_PLANE3_FLIP_DONE = 0x58, + PIPEDMC_EVENT_PLANE4_FLIP_DONE = 0x59, + PIPEDMC_EVENT_PLANE5_FLIP_DONE = 0x5a, + PIPEDMC_EVENT_PLANE6_FLIP_DONE = 0x5b, + PIPEDMC_EVENT_PLANE7_FLIP_DONE = 0x5c, + + PIPEDMC_EVENT_GTT_ERR = 0x9b, + + PIPEDMC_EVENT_IN_PSR = 0xb5, + PIPEDMC_EVENT_DSI_DMC_IDLE = 0xb6, + PIPEDMC_EVENT_PSR2_DMC_IDLE = 0xb7, + PIPEDMC_EVENT_IN_VGA = 0xb8, + + PIPEDMC_EVENT_TRAP_HIT = 0xbd, + PIPEDMC_EVENT_CLK_USEC = 0xbe, + PIPEDMC_EVENT_CLK_MSEC = 0xbf, + + PIPEDMC_EVENT_CHICKEN1 = 0xc8, + PIPEDMC_EVENT_CHICKEN2 = 0xc9, + PIPEDMC_EVENT_CHICKEN3 = 0xca, + PIPEDMC_EVENT_DDT_UBP = 0xcb, + + PIPEDMC_EVENT_LP_LATENCY = 0xce, + + PIPEDMC_EVENT_LACE_PART_A_HIST_TRIGGER = 0xdf, + PIPEDMC_EVENT_LACE_PART_B_HIST_TRIGGER = 0xe0, + + PIPEDMC_EVENT_STACK_OVF = 0xfc, + PIPEDMC_EVENT_NO_CLAIM = 0xfd, + PIPEDMC_EVENT_UNK_CMD = 0xfe, + PIPEDMC_EVENT_HTP_MOD = 0xff, +}; + #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 @@ -93,12 +359,7 @@ #define DMC_EVT_CTL_TYPE_LEVEL_1 1 #define DMC_EVT_CTL_TYPE_EDGE_1_0 2 #define DMC_EVT_CTL_TYPE_EDGE_0_1 3 - #define DMC_EVT_CTL_EVENT_ID_MASK REG_GENMASK(15, 8) -#define DMC_EVT_CTL_EVENT_ID_FALSE 0x01 -#define DMC_EVT_CTL_EVENT_ID_VBLANK_A 0x32 /* main DMC */ -/* An event handler scheduled to run at a 1 kHz frequency. */ -#define DMC_EVT_CTL_EVENT_ID_CLK_MSEC 0xbf #define DMC_HTP_ADDR_SKL 0x00500034 #define DMC_SSP_BASE _MMIO(0x8F074) -- GitLab From 4c47d656f89a207562f99a174181789d45f571f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:55 +0300 Subject: [PATCH 080/902] drm/i915/dmc: Extract dmc_evt_ctl_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have two copies of the code to generate the "disable this event" value for the DMC_EVT_CTL registers. Extract to a helper. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-5-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index e9aee3d5daf69..af1854cc6d148 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -539,6 +539,14 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe) } } +static u32 dmc_evt_ctl_disable(void) +{ + return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, + DMC_EVT_CTL_TYPE_EDGE_0_1) | + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, + DMC_EVENT_FALSE); +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -578,10 +586,7 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, PIPEDMC_EVENT_VBLANK); else - val = REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVENT_FALSE) | - REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1); + val = dmc_evt_ctl_disable(); intel_de_write(display, MTL_PIPEDMC_EVT_CTL_4(pipe), val); @@ -638,10 +643,7 @@ static u32 dmc_mmiodata(struct intel_display *display, if (disable_dmc_evt(display, dmc_id, dmc->dmc_info[dmc_id].mmioaddr[i], dmc->dmc_info[dmc_id].mmiodata[i])) - return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1) | - REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVENT_FALSE); + return dmc_evt_ctl_disable(); else return dmc->dmc_info[dmc_id].mmiodata[i]; } -- GitLab From 583710251f6380b973bc594d54bcf4c131c81805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:56 +0300 Subject: [PATCH 081/902] drm/i915/dmc: Relocate is_dmc_evt_{ctl,htp}_reg() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move is_dmc_evt_ctl_reg() to a slightly earlier position in the file so that we can reuse it in the pkgc workaround code. Also move is_dmc_evt_htp_reg() just to keep the two together. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-6-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index af1854cc6d148..09a1933657c40 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -547,6 +547,26 @@ static u32 dmc_evt_ctl_disable(void) DMC_EVENT_FALSE); } +static bool is_dmc_evt_ctl_reg(struct intel_display *display, + enum intel_dmc_id dmc_id, i915_reg_t reg) +{ + u32 offset = i915_mmio_reg_offset(reg); + u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)); + u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); + + return offset >= start && offset < end; +} + +static bool is_dmc_evt_htp_reg(struct intel_display *display, + enum intel_dmc_id dmc_id, i915_reg_t reg) +{ + u32 offset = i915_mmio_reg_offset(reg); + u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0)); + u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); + + return offset >= start && offset < end; +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -592,26 +612,6 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display val); } -static bool is_dmc_evt_ctl_reg(struct intel_display *display, - enum intel_dmc_id dmc_id, i915_reg_t reg) -{ - u32 offset = i915_mmio_reg_offset(reg); - u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)); - u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); - - return offset >= start && offset < end; -} - -static bool is_dmc_evt_htp_reg(struct intel_display *display, - enum intel_dmc_id dmc_id, i915_reg_t reg) -{ - u32 offset = i915_mmio_reg_offset(reg); - u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0)); - u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); - - return offset >= start && offset < end; -} - static bool disable_dmc_evt(struct intel_display *display, enum intel_dmc_id dmc_id, i915_reg_t reg, u32 data) -- GitLab From d9dd810dd404ecb7bdfd3294bfb8d932e6066e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:57 +0300 Subject: [PATCH 082/902] drm/i915/dmc: Extract is_event_handler() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the helper to determine if the mmio reg+data are the event handler register (DMC_EVT_CTL) for a specific event. We'll have another use for this for runtime event handler enable/disable. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-7-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 09a1933657c40..9ab3ac3c1658e 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -567,6 +567,15 @@ static bool is_dmc_evt_htp_reg(struct intel_display *display, return offset >= start && offset < end; } +static bool is_event_handler(struct intel_display *display, + enum intel_dmc_id dmc_id, + unsigned int event_id, + i915_reg_t reg, u32 data) +{ + return is_dmc_evt_ctl_reg(display, dmc_id, reg) && + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -625,12 +634,12 @@ static bool disable_dmc_evt(struct intel_display *display, /* also disable the flip queue event on the main DMC on TGL */ if (display->platform.tigerlake && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_CLK_MSEC) + is_event_handler(display, dmc_id, MAINDMC_EVENT_CLK_MSEC, reg, data)) return true; /* also disable the HRR event on the main DMC on TGL/ADLS */ if ((display->platform.tigerlake || display->platform.alderlake_s) && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_VBLANK_A) + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg, data)) return true; return false; -- GitLab From d65c47f976cc4c01ec1b4f9f113606f44f384de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:58 +0300 Subject: [PATCH 083/902] drm/i915/dmc: Introduce dmc_configure_event() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hardcoding the event handler indices (for runtime event handler enable/disable) we can simply look for the handler with the appropriate event type. This isolates us from the firmware details a bit better. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-8-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 39 +++++++++++++------ drivers/gpu/drm/i915/display/intel_dmc_regs.h | 6 --- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 9ab3ac3c1658e..a7ba17361d63b 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -576,6 +576,31 @@ static bool is_event_handler(struct intel_display *display, REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; } +static void dmc_configure_event(struct intel_display *display, + enum intel_dmc_id dmc_id, + unsigned int event_id, + bool enable) +{ + struct intel_dmc *dmc = display_to_dmc(display); + int num_handlers = 0; + int i; + + for (i = 0; i < dmc->dmc_info[dmc_id].mmio_count; i++) { + i915_reg_t reg = dmc->dmc_info[dmc_id].mmioaddr[i]; + u32 data = dmc->dmc_info[dmc_id].mmiodata[i]; + + if (!is_event_handler(display, dmc_id, event_id, reg, data)) + continue; + + intel_de_write(display, reg, enable ? data : dmc_evt_ctl_disable()); + num_handlers++; + } + + drm_WARN_ONCE(display->drm, num_handlers != 1, + "DMC %d has %d handlers for event 0x%x\n", + dmc_id, num_handlers, event_id); +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -606,19 +631,9 @@ void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe, void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display, enum pipe pipe, bool enable) { - u32 val; - - if (enable) - val = DMC_EVT_CTL_ENABLE | DMC_EVT_CTL_RECURRING | - REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1) | - REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - PIPEDMC_EVENT_VBLANK); - else - val = dmc_evt_ctl_disable(); + enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe); - intel_de_write(display, MTL_PIPEDMC_EVT_CTL_4(pipe), - val); + dmc_configure_event(display, dmc_id, PIPEDMC_EVENT_VBLANK, enable); } static bool disable_dmc_evt(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index edd4e69319b97..d8e7156774544 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -287,12 +287,6 @@ enum pipedmc_event_id { #define MTL_PIPEDMC_CONTROL _MMIO(0x45250) #define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4) -#define _MTL_PIPEDMC_EVT_CTL_4_A 0x5f044 -#define _MTL_PIPEDMC_EVT_CTL_4_B 0x5f444 -#define MTL_PIPEDMC_EVT_CTL_4(pipe) _MMIO_PIPE(pipe, \ - _MTL_PIPEDMC_EVT_CTL_4_A, \ - _MTL_PIPEDMC_EVT_CTL_4_B) - #define _PIPEDMC_STATUS_A 0x5f06c #define _PIPEDMC_STATUS_B 0x5f46c #define PIPEDMC_STATUS(pipe) _MMIO_PIPE((pipe), _PIPEDMC_STATUS_A, _PIPEDMC_STATUS_B) -- GitLab From 921ddb37d87c13eb811b8a3280377e4dab73eccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Pi=C3=B3rkowski?= Date: Tue, 13 May 2025 09:13:21 +0200 Subject: [PATCH 084/902] drm/xe/pf: Don't allow LMEM provisioning if LMTT isn't available on the device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The LMEM provisioning is applicable only on platforms with LMTT. v2: - new commit description - use xe_gt_assert in xe_gt_sriov_pf_config_set_lmem instead return error, - disable pf_lmem_info if LMTT is not available v3: fix condition in xe_gt_assert v4: rebase Signed-off-by: Piotr Piórkowski Cc: Michal Wajdeczko Reviewed-by: Stuart Summers Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250513071321.700464-1-piotr.piorkowski@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 6 ++++-- drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 2420a548cacc1..3556c41c041b5 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1520,6 +1520,8 @@ int xe_gt_sriov_pf_config_set_lmem(struct xe_gt *gt, unsigned int vfid, u64 size { int err; + xe_gt_assert(gt, xe_device_has_lmtt(gt_to_xe(gt))); + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); if (vfid) err = pf_provision_vf_lmem(gt, vfid, size); @@ -1629,7 +1631,7 @@ int xe_gt_sriov_pf_config_set_fair_lmem(struct xe_gt *gt, unsigned int vfid, xe_gt_assert(gt, num_vfs); xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - if (!IS_DGFX(gt_to_xe(gt))) + if (!xe_device_has_lmtt(gt_to_xe(gt))) return 0; mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); @@ -2163,7 +2165,7 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) valid_all = valid_all && valid_ggtt; valid_any = valid_any || (valid_ggtt && is_primary); - if (IS_DGFX(xe)) { + if (xe_device_has_lmtt(xe)) { bool valid_lmem = pf_get_vf_config_lmem(primary_gt, vfid); valid_any = valid_any || (valid_lmem && is_primary); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c index 0fe47f41b63c8..13970d5a2867d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c @@ -308,7 +308,7 @@ static void pf_add_config_attrs(struct xe_gt *gt, struct dentry *parent, unsigne if (!xe_gt_is_media_type(gt)) { debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 0644, parent, parent, &ggtt_fops); - if (IS_DGFX(gt_to_xe(gt))) + if (xe_device_has_lmtt(gt_to_xe(gt))) debugfs_create_file_unsafe(vfid ? "lmem_quota" : "lmem_spare", 0644, parent, parent, &lmem_fops); } @@ -558,7 +558,7 @@ void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) drm_debugfs_create_files(pf_ggtt_info, ARRAY_SIZE(pf_ggtt_info), pfdentry, minor); - if (IS_DGFX(gt_to_xe(gt))) + if (xe_device_has_lmtt(gt_to_xe(gt))) drm_debugfs_create_files(pf_lmem_info, ARRAY_SIZE(pf_lmem_info), pfdentry, minor); -- GitLab From a383cf218ef8bb35d4c03958bd956573b65cf778 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 6 May 2025 19:53:00 +0530 Subject: [PATCH 085/902] drm/xe/mocs: Check if all domains awake Check if all domains are awake specially for LNCF regs Fixes: 1182bc74b39b ("drm/xe: Fix MOCS debugfs LNCF readout") Improvements-suggested-by: Himal Prasad Ghimiray Reviewed-by: Badal Nilawar Link: https://patchwork.freedesktop.org/patch/msgid/20250506142300.1865783-1-tejas.upadhyay@intel.com Signed-off-by: Tejas Upadhyay --- drivers/gpu/drm/xe/xe_mocs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c index 31dade91a0897..0c737413fcb68 100644 --- a/drivers/gpu/drm/xe/xe_mocs.c +++ b/drivers/gpu/drm/xe/xe_mocs.c @@ -775,22 +775,23 @@ void xe_mocs_init(struct xe_gt *gt) void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); + enum xe_force_wake_domains domain; struct xe_mocs_info table; unsigned int fw_ref, flags; flags = get_mocs_settings(xe, &table); + domain = flags & HAS_LNCF_MOCS ? XE_FORCEWAKE_ALL : XE_FW_GT; xe_pm_runtime_get_noresume(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), - flags & HAS_LNCF_MOCS ? - XE_FORCEWAKE_ALL : XE_FW_GT); - if (!fw_ref) + fw_ref = xe_force_wake_get(gt_to_fw(gt), domain); + + if (!xe_force_wake_ref_has_domain(fw_ref, domain)) goto err_fw; table.ops->dump(&table, flags, gt, p); - xe_force_wake_put(gt_to_fw(gt), fw_ref); err_fw: + xe_force_wake_put(gt_to_fw(gt), fw_ref); xe_pm_runtime_put(xe); } -- GitLab From 1c57014325ef2b62459c8482768a842f9c40cd0c Mon Sep 17 00:00:00 2001 From: Gareth Yu Date: Fri, 9 May 2025 17:25:39 +0800 Subject: [PATCH 086/902] drm/i915/dsi: Enforce pipeline flush with DSI HS transfer With all of the boundary conditions when streaming the commands B2B in our validation (part of the reason we added the flush), the Flush effectively serializes the transmission of each command enqueued within the command dispatcher to one per V. Blank line which simplifies the behavior of the High Speed Arbitration. So, unless we absolutely have to burst these to the Sink, we should be using the Pipeline Flush bit to serialize the commands. Bspec: 19742, 50193 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14247 Cc: Suraj Kandpal Cc: Jani Nikula Signed-off-by: Gareth Yu Link: https://lore.kernel.org/r/20250509092539.763389-1-gareth.yu@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 4 ++-- drivers/gpu/drm/i915/display/icl_dsi_regs.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ca7033251e916..28dab9320aedd 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -192,12 +192,12 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host, else tmp &= ~PAYLOAD_PRESENT; - tmp &= ~VBLANK_FENCE; + tmp &= ~(VBLANK_FENCE | LP_DATA_TRANSFER | PIPELINE_FLUSH); if (enable_lpdt) tmp |= LP_DATA_TRANSFER; else - tmp &= ~LP_DATA_TRANSFER; + tmp |= PIPELINE_FLUSH; tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK); tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT); diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h index d4845ac65acce..b601b7632339a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h +++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h @@ -272,6 +272,7 @@ #define PAYLOAD_PRESENT (1 << 31) #define LP_DATA_TRANSFER (1 << 30) #define VBLANK_FENCE (1 << 29) +#define PIPELINE_FLUSH (1 << 28) #define PARAM_WC_MASK (0xffff << 8) #define PARAM_WC_LOWER_SHIFT 8 #define PARAM_WC_UPPER_SHIFT 16 -- GitLab From 5666e27a50666755f8a842f53dd68d6983126ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 16 May 2025 09:30:19 +0300 Subject: [PATCH 087/902] drm/i915/psr: Do not read PSR2_SU_STATUS on AlderLake and onwards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bspec comment on PSR2_SU_STATUS: "This register has been tied-off since DG2/ADL-P (it returns zeros only) and it has been removed on Xe2_LPD." v2: fix inversed logic Bspec: 69889 Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250516063019.2126702-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 430ad4ef71466..cd833b63ea6b7 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -4021,24 +4021,30 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) int frame; /* - * Reading all 3 registers before hand to minimize crossing a - * frame boundary between register reads + * PSR2_SU_STATUS register has been tied-off since DG2/ADL-P + * (it returns zeros only) and it has been removed on Xe2_LPD. */ - for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { - val = intel_de_read(display, - PSR2_SU_STATUS(display, cpu_transcoder, frame)); - su_frames_val[frame / 3] = val; - } + if (DISPLAY_VER(display) < 13) { + /* + * Reading all 3 registers before hand to minimize crossing a + * frame boundary between register reads + */ + for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { + val = intel_de_read(display, + PSR2_SU_STATUS(display, cpu_transcoder, frame)); + su_frames_val[frame / 3] = val; + } - seq_puts(m, "Frame:\tPSR2 SU blocks:\n"); + seq_puts(m, "Frame:\tPSR2 SU blocks:\n"); - for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame++) { - u32 su_blocks; + for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame++) { + u32 su_blocks; - su_blocks = su_frames_val[frame / 3] & - PSR2_SU_STATUS_MASK(frame); - su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); - seq_printf(m, "%d\t%d\n", frame, su_blocks); + su_blocks = su_frames_val[frame / 3] & + PSR2_SU_STATUS_MASK(frame); + su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); + seq_printf(m, "%d\t%d\n", frame, su_blocks); + } } seq_printf(m, "PSR2 selective fetch: %s\n", -- GitLab From e1123e617e510a3652fc707155adc43bb3fe4160 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 5 May 2025 09:09:11 +0530 Subject: [PATCH 088/902] drm/i915/vrr: Program EMP_AS_SDP_TL for DP AS SDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The register EMP_AS_SDP_TL (MTL) was introduced for configuring the double buffering point and transmission line for all HDMI2.1 Extended Metadata Packets (VT-EMP for VRR, CVT-EMP for DSC etc). This was also intended to be configured for DP to HDMI2.1 PCON to support VRR. From BMG and LNL+ onwards, this register was extended to Display Port Adaptive Sync SDP to have a common register to configure double buffering point and transmission line for both HDMI EMPs and DP VRR related packets. Currently, we do not support VRR for either native HDMI or via PCON. However we need to configure this for DP SDP case. As per the spec, program the register to set Vsync start as the double buffering point for DP AS SDP. v2: -Make the helper more readable. (Jani) -Add more information in commit message and comment. Bspec:70984, 71197 Signed-off-by: Ankit Nautiyal Tested-by: Jouni Högander Reviewed-by: Jouni Högander Link: https://lore.kernel.org/r/20250505033911.393628-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 23 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vrr_regs.h | 6 +++++ 2 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index c6565baf815a1..c55b8144e234f 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -576,6 +576,25 @@ bool intel_vrr_always_use_vrr_tg(struct intel_display *display) return false; } +static +void intel_vrr_set_db_point_and_transmission_line(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + /* + * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming + * double buffering point and transmission line for VRR packets for + * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. + * Since currently we support VRR only for DP/eDP, so this is programmed + * to for Adaptive Sync SDP to Vsync start. + */ + if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) + intel_de_write(display, + EMP_AS_SDP_TL(display, cpu_transcoder), + EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); +} + void intel_vrr_enable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -595,6 +614,8 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state) TRANS_PUSH_EN); if (!intel_vrr_always_use_vrr_tg(display)) { + intel_vrr_set_db_point_and_transmission_line(crtc_state); + if (crtc_state->cmrr.enable) { intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), VRR_CTL_VRR_ENABLE | VRR_CTL_CMRR_ENABLE | @@ -646,6 +667,8 @@ void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state) intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN); + intel_vrr_set_db_point_and_transmission_line(crtc_state); + intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); } diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h index 6ed0e0dc97e76..09cdd50d6187f 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h @@ -108,6 +108,12 @@ #define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) #define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) +/* Common register for HDMI EMP and DP AS SDP */ +#define _EMP_AS_SDP_TL_A 0x60204 +#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) +#define EMP_AS_SDP_TL(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _EMP_AS_SDP_TL_A) +#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, (db_transmit_line)) + /*CMRR Registers*/ #define _TRANS_CMRR_M_LO_A 0x604F0 -- GitLab From 17486cf3df5320752cc67ee8bcb2379d1b9de76c Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Fri, 16 May 2025 14:19:02 +0000 Subject: [PATCH 089/902] drm/xe/guc: Make creation of SLPC debugfs files conditional Platforms that do not support SLPC are exempted from the GuC PC support. The GuC PC does not get initialized, and neither do its BOs get created. This causes a problem because the GuC PC debugfs file is still being created. Whenever the file is attempted to read, it causes a NULL pointer dereference on the supposed BO of the GuC PC. So, make the creation of SLPC debugfs files conditional to when SLPC features are supported. Fixes: aaab5404b16f ("drm/xe: Introduce GuC PC debugfs") Suggested-by: Matt Roper Reviewed-by: Tejas Upadhyay Reviewed-by: Stuart Summers Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250516141902.5614-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_guc_debugfs.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_debugfs.c b/drivers/gpu/drm/xe/xe_guc_debugfs.c index f33013f8a0f38..0b102ab46c4df 100644 --- a/drivers/gpu/drm/xe/xe_guc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_guc_debugfs.c @@ -113,23 +113,34 @@ static const struct drm_info_list vf_safe_debugfs_list[] = { { "guc_ctb", .show = guc_debugfs_show, .data = guc_ctb }, }; +/* For GuC debugfs files that require the SLPC support */ +static const struct drm_info_list slpc_debugfs_list[] = { + { "guc_pc", .show = guc_debugfs_show, .data = guc_pc }, +}; + /* everything else should be added here */ static const struct drm_info_list pf_only_debugfs_list[] = { { "guc_log", .show = guc_debugfs_show, .data = guc_log }, { "guc_log_dmesg", .show = guc_debugfs_show, .data = guc_log_dmesg }, - { "guc_pc", .show = guc_debugfs_show, .data = guc_pc }, }; void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent) { - struct drm_minor *minor = guc_to_xe(guc)->drm.primary; + struct xe_device *xe = guc_to_xe(guc); + struct drm_minor *minor = xe->drm.primary; drm_debugfs_create_files(vf_safe_debugfs_list, ARRAY_SIZE(vf_safe_debugfs_list), parent, minor); - if (!IS_SRIOV_VF(guc_to_xe(guc))) + if (!IS_SRIOV_VF(xe)) { drm_debugfs_create_files(pf_only_debugfs_list, ARRAY_SIZE(pf_only_debugfs_list), parent, minor); + + if (!xe->info.skip_guc_pc) + drm_debugfs_create_files(slpc_debugfs_list, + ARRAY_SIZE(slpc_debugfs_list), + parent, minor); + } } -- GitLab From a7f87deac2295d11865048bcb9c2de369b52ed93 Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Fri, 16 May 2025 12:43:55 +0000 Subject: [PATCH 090/902] drm/xe: Default auto_link_downgrade status to false xe_pcode_read() can return back successfully without updating the variable 'val'. This can cause an arbitrary value to show up in the sysfs file. Allow the auto_link_downgrade_status to default to 0 to avoid any arbitrary value from coming up. Fixes: 0e414bf7ad01 ("drm/xe: Expose PCIe link downgrade attributes") Reviewed-by: Tejas Upadhyay Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250516124355.4872-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_sysfs.c b/drivers/gpu/drm/xe/xe_device_sysfs.c index 9628e9a0a0af5..2e657692e5b5f 100644 --- a/drivers/gpu/drm/xe/xe_device_sysfs.c +++ b/drivers/gpu/drm/xe/xe_device_sysfs.c @@ -124,7 +124,8 @@ auto_link_downgrade_status_show(struct device *dev, struct device_attribute *att { struct pci_dev *pdev = to_pci_dev(dev); struct xe_device *xe = pdev_to_xe_device(pdev); - u32 val; + /* default the auto_link_downgrade status to 0 */ + u32 val = 0; int ret; xe_pm_runtime_get(xe); -- GitLab From d2662cf8f44a68deb6c76ad9f1d9f29dbf7ba601 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 13 May 2025 15:30:10 +0000 Subject: [PATCH 091/902] drm/xe: Use xe_mmio_read32() to read mtcfg register The mtcfg register is a 32-bit register and should therefore be accessed using xe_mmio_read32(). Other 3 changes per codestyle suggestion: " xe_mmio.c:83: CHECK: Alignment should match open parenthesis xe_mmio.c:131: CHECK: Comparison to NULL could be written "!xe->mmio.regs" xe_mmio.c:315: CHECK: line length of 103 exceeds 100 columns " Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Reviewed-by: Tejas Upadhyay Cc: Matt Roper Signed-off-by: Shuicheng Lin Link: https://lore.kernel.org/r/20250513153010.3464767-1-shuicheng.lin@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_mmio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index 096c38cc51c83..7357458bc0d21 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -75,12 +75,12 @@ static void mmio_multi_tile_setup(struct xe_device *xe, size_t tile_mmio_size) * is fine as it's going to the root tile's mmio, that's * guaranteed to be initialized earlier in xe_mmio_probe_early() */ - mtcfg = xe_mmio_read64_2x32(mmio, XEHP_MTCFG_ADDR); + mtcfg = xe_mmio_read32(mmio, XEHP_MTCFG_ADDR); tile_count = REG_FIELD_GET(TILE_COUNT, mtcfg) + 1; if (tile_count < xe->info.tile_count) { drm_info(&xe->drm, "tile_count: %d, reduced_tile_count %d\n", - xe->info.tile_count, tile_count); + xe->info.tile_count, tile_count); xe->info.tile_count = tile_count; /* @@ -128,7 +128,7 @@ int xe_mmio_probe_early(struct xe_device *xe) */ xe->mmio.size = pci_resource_len(pdev, GTTMMADR_BAR); xe->mmio.regs = pci_iomap(pdev, GTTMMADR_BAR, 0); - if (xe->mmio.regs == NULL) { + if (!xe->mmio.regs) { drm_err(&xe->drm, "failed to map registers\n"); return -EIO; } @@ -312,8 +312,8 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg) return (u64)udw << 32 | ldw; } -static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, - u32 *out_val, bool atomic, bool expect_match) +static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, + u32 timeout_us, u32 *out_val, bool atomic, bool expect_match) { ktime_t cur = ktime_get_raw(); const ktime_t end = ktime_add_us(cur, timeout_us); -- GitLab From 537d00c8fda47250c2a763eea2b8a86708e029b0 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:48 +0530 Subject: [PATCH 092/902] drm/i915/dpll: Rename intel_dpll Rename intel_dpll to intel_dpll_global so that intel_shared_dpll can be renamed to intel_dpll in an effort to move away from the shared naming convention. Also intel_dpll according to it's comment tracks global dpll rather than individual hence making more sense this gets changed. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-2-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index b4937e1023606..6fc213f84e73e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -122,7 +122,7 @@ struct intel_audio { * intel_{prepare,enable,disable}_shared_dpll. Must be global rather than per * dpll, because on some platforms plls share registers. */ -struct intel_dpll { +struct intel_dpll_global { struct mutex lock; int num_shared_dpll; @@ -570,7 +570,7 @@ struct intel_display { /* Grouping using named structs. Keep sorted. */ struct drm_dp_tunnel_mgr *dp_tunnel_mgr; struct intel_audio audio; - struct intel_dpll dpll; + struct intel_dpll_global dpll; struct intel_fbc *fbc[I915_MAX_FBCS]; struct intel_frontbuffer_tracking fb_tracking; struct intel_hotplug hotplug; -- GitLab From e12c9b439f2cbcb574cd71ff7e14121b59ef0fe4 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:49 +0530 Subject: [PATCH 093/902] drm/i915/dpll: Rename intel_dpll_funcs Rename intel_dpll_funcs to intel_dpll_global_funcs so that later on intel_shared_dpll_funcs can be renamed to intel_dpll_funcs. This is done to move away from the shared naming convention since starting MTL dpll's are not shared among PHYs. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-3-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_display_core.h | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll.c | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 6fc213f84e73e..e0221e514326b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -42,7 +42,7 @@ struct intel_color_funcs; struct intel_crtc; struct intel_crtc_state; struct intel_dmc; -struct intel_dpll_funcs; +struct intel_dpll_global_funcs; struct intel_dpll_mgr; struct intel_fbdev; struct intel_fdi_funcs; @@ -300,7 +300,7 @@ struct intel_display { const struct intel_cdclk_funcs *cdclk; /* Display pll funcs */ - const struct intel_dpll_funcs *dpll; + const struct intel_dpll_global_funcs *dpll; /* irq display functions */ const struct intel_hotplug_funcs *hotplug; diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index dd7a29c10b5d8..c13fb37ea584f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -25,7 +25,7 @@ #include "vlv_dpio_phy_regs.h" #include "vlv_sideband.h" -struct intel_dpll_funcs { +struct intel_dpll_global_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, struct intel_crtc *crtc); int (*crtc_get_shared_dpll)(struct intel_atomic_state *state, @@ -1691,45 +1691,45 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static const struct intel_dpll_funcs mtl_dpll_funcs = { +static const struct intel_dpll_global_funcs mtl_dpll_funcs = { .crtc_compute_clock = mtl_crtc_compute_clock, }; -static const struct intel_dpll_funcs dg2_dpll_funcs = { +static const struct intel_dpll_global_funcs dg2_dpll_funcs = { .crtc_compute_clock = dg2_crtc_compute_clock, }; -static const struct intel_dpll_funcs hsw_dpll_funcs = { +static const struct intel_dpll_global_funcs hsw_dpll_funcs = { .crtc_compute_clock = hsw_crtc_compute_clock, .crtc_get_shared_dpll = hsw_crtc_get_shared_dpll, }; -static const struct intel_dpll_funcs ilk_dpll_funcs = { +static const struct intel_dpll_global_funcs ilk_dpll_funcs = { .crtc_compute_clock = ilk_crtc_compute_clock, .crtc_get_shared_dpll = ilk_crtc_get_shared_dpll, }; -static const struct intel_dpll_funcs chv_dpll_funcs = { +static const struct intel_dpll_global_funcs chv_dpll_funcs = { .crtc_compute_clock = chv_crtc_compute_clock, }; -static const struct intel_dpll_funcs vlv_dpll_funcs = { +static const struct intel_dpll_global_funcs vlv_dpll_funcs = { .crtc_compute_clock = vlv_crtc_compute_clock, }; -static const struct intel_dpll_funcs g4x_dpll_funcs = { +static const struct intel_dpll_global_funcs g4x_dpll_funcs = { .crtc_compute_clock = g4x_crtc_compute_clock, }; -static const struct intel_dpll_funcs pnv_dpll_funcs = { +static const struct intel_dpll_global_funcs pnv_dpll_funcs = { .crtc_compute_clock = pnv_crtc_compute_clock, }; -static const struct intel_dpll_funcs i9xx_dpll_funcs = { +static const struct intel_dpll_global_funcs i9xx_dpll_funcs = { .crtc_compute_clock = i9xx_crtc_compute_clock, }; -static const struct intel_dpll_funcs i8xx_dpll_funcs = { +static const struct intel_dpll_global_funcs i8xx_dpll_funcs = { .crtc_compute_clock = i8xx_crtc_compute_clock, }; -- GitLab From 139f267322d617dd9a6ac75d2e2b40110920e94c Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:50 +0530 Subject: [PATCH 094/902] drm/i915/dpll: Rename intel_shared_dpll_state Rename intel_shared_dpll_state to just intel_dpll_state since it may not necessarily store share dpll state info specially since DISPLAY_VER >= 14 PLL's are not shared. Also change the name of variables which may have been associated as a shared_dpll. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-4-suraj.kandpal@intel.com --- .../drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 56 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 8 +-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 056219272c36e..9df7795b9327a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -595,7 +595,7 @@ struct intel_atomic_state { bool dpll_set, modeset; - struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; + struct intel_dpll_state dpll_state[I915_NUM_PLLS]; struct intel_dp_tunnel_inherited_state *inherited_dp_tunnels; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9da051a3f4550..6b4eb230f4b3c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -122,17 +122,17 @@ struct intel_dpll_mgr { static void intel_atomic_duplicate_dpll_state(struct intel_display *display, - struct intel_shared_dpll_state *shared_dpll) + struct intel_dpll_state *dpll_state) { struct intel_shared_dpll *pll; int i; /* Copy shared dpll state */ for_each_shared_dpll(display, pll, i) - shared_dpll[pll->index] = pll->state; + dpll_state[pll->index] = pll->state; } -static struct intel_shared_dpll_state * +static struct intel_dpll_state * intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) { struct intel_atomic_state *state = to_intel_atomic_state(s); @@ -144,10 +144,10 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) state->dpll_set = true; intel_atomic_duplicate_dpll_state(display, - state->shared_dpll); + state->dpll_state); } - return state->shared_dpll; + return state->dpll_state; } /** @@ -365,11 +365,11 @@ intel_find_shared_dpll(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; struct intel_shared_dpll *unused_pll = NULL; enum intel_dpll_id id; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); @@ -381,20 +381,20 @@ intel_find_shared_dpll(struct intel_atomic_state *state, continue; /* Only want to check enabled timings first */ - if (shared_dpll[pll->index].pipe_mask == 0) { + if (dpll_state[pll->index].pipe_mask == 0) { if (!unused_pll) unused_pll = pll; continue; } if (memcmp(dpll_hw_state, - &shared_dpll[pll->index].hw_state, + &dpll_state[pll->index].hw_state, sizeof(*dpll_hw_state)) == 0) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n", crtc->base.base.id, crtc->base.name, pll->info->name, - shared_dpll[pll->index].pipe_mask, + dpll_state[pll->index].pipe_mask, pll->active_mask); return pll; } @@ -415,20 +415,20 @@ intel_find_shared_dpll(struct intel_atomic_state *state, * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken - * @shared_dpll_state: the DPLL atomic state in which the reference is tracked + * @dpll_state: the DPLL atomic state in which the reference is tracked * * Take a reference for @pll tracking the use of it by @crtc. */ static void intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state) + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); - drm_WARN_ON(display->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) != 0); + drm_WARN_ON(display->drm, (dpll_state->pipe_mask & BIT(crtc->pipe)) != 0); - shared_dpll_state->pipe_mask |= BIT(crtc->pipe); + dpll_state->pipe_mask |= BIT(crtc->pipe); drm_dbg_kms(display->drm, "[CRTC:%d:%s] reserving %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); @@ -440,34 +440,34 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, const struct intel_shared_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); - if (shared_dpll[pll->index].pipe_mask == 0) - shared_dpll[pll->index].hw_state = *dpll_hw_state; + if (dpll_state[pll->index].pipe_mask == 0) + dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]); + intel_reference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } /** * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped - * @shared_dpll_state: the DPLL atomic state in which the reference is tracked + * @dpll_state: the DPLL atomic state in which the reference is tracked * * Drop a reference for @pll tracking the end of use of it by @crtc. */ void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state) + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); - drm_WARN_ON(display->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) == 0); + drm_WARN_ON(display->drm, (dpll_state->pipe_mask & BIT(crtc->pipe)) == 0); - shared_dpll_state->pipe_mask &= ~BIT(crtc->pipe); + dpll_state->pipe_mask &= ~BIT(crtc->pipe); drm_dbg_kms(display->drm, "[CRTC:%d:%s] releasing %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); @@ -477,11 +477,11 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_shared_dpll *pll) { - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); - intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]); + intel_unreference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, @@ -514,7 +514,7 @@ static void intel_put_dpll(struct intel_atomic_state *state, void intel_shared_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct intel_shared_dpll_state *shared_dpll = state->shared_dpll; + struct intel_dpll_state *dpll_state = state->dpll_state; struct intel_shared_dpll *pll; int i; @@ -522,7 +522,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) return; for_each_shared_dpll(display, pll, i) - swap(pll->state, shared_dpll[pll->index]); + swap(pll->state, dpll_state[pll->index]); } static bool ibx_pch_dpll_get_hw_state(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index caffb084830ce..fe6c676737bb4 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -280,7 +280,7 @@ struct intel_dpll_hw_state { }; /** - * struct intel_shared_dpll_state - hold the DPLL atomic state + * struct intel_dpll_state - hold the DPLL atomic state * * This structure holds an atomic state for the DPLL, that can represent * either its current state (in struct &intel_shared_dpll) or a desired @@ -289,7 +289,7 @@ struct intel_dpll_hw_state { * * See also intel_reserve_shared_dplls() and intel_release_shared_dplls(). */ -struct intel_shared_dpll_state { +struct intel_dpll_state { /** * @pipe_mask: mask of pipes using this DPLL, active or not */ @@ -353,7 +353,7 @@ struct intel_shared_dpll { * Store the state for the pll, including its hw state * and CRTCs using it. */ - struct intel_shared_dpll_state state; + struct intel_dpll_state state; /** * @index: index for atomic state @@ -406,7 +406,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state); + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, -- GitLab From 958a33200ac7c85e95b5a5c93bb3b2004b752aed Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:51 +0530 Subject: [PATCH 095/902] drm/i915/dpll: Rename macro for_each_shared_dpll Rename the macro for_each_shared_dpll to for_each_dpll since this loop will not necessarily be used for only shared dpll in future. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-5-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 16 ++++++++-------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- drivers/gpu/drm/i915/display/intel_pch_refclk.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 9df8995e5bac6..11a7fec202327 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -627,7 +627,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) display->dpll.ref_clks.nssc, display->dpll.ref_clks.ssc); - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { drm_printf(&p, "DPLL%i: %s, id: %i\n", pll->index, pll->info->name, pll->info->id); drm_printf(&p, " pipe_mask: 0x%x, active: 0x%x, on: %s\n", diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6b4eb230f4b3c..9974fdb6eaeb5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -127,8 +127,8 @@ intel_atomic_duplicate_dpll_state(struct intel_display *display, struct intel_shared_dpll *pll; int i; - /* Copy shared dpll state */ - for_each_shared_dpll(display, pll, i) + /* Copy dpll state */ + for_each_dpll(display, pll, i) dpll_state[pll->index] = pll->state; } @@ -165,7 +165,7 @@ intel_get_shared_dpll_by_id(struct intel_display *display, struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { if (pll->info->id == id) return pll; } @@ -348,7 +348,7 @@ intel_dpll_mask_all(struct intel_display *display) unsigned long dpll_mask = 0; int i; - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { drm_WARN_ON(display->drm, dpll_mask & BIT(pll->info->id)); dpll_mask |= BIT(pll->info->id); @@ -521,7 +521,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) if (!state->dpll_set) return; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) swap(pll->state, dpll_state[pll->index]); } @@ -4542,7 +4542,7 @@ void intel_dpll_readout_hw_state(struct intel_display *display) struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) readout_dpll_hw_state(display, pll); } @@ -4571,7 +4571,7 @@ void intel_dpll_sanitize_state(struct intel_display *display) intel_cx0_pll_power_save_wa(display); - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) sanitize_dpll_state(display, pll); } @@ -4720,6 +4720,6 @@ void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) verify_single_dpll_state(display, pll, NULL, NULL); } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index fe6c676737bb4..d930724868313 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -30,7 +30,7 @@ #include "intel_display_power.h" #include "intel_wakeref.h" -#define for_each_shared_dpll(__display, __pll, __i) \ +#define for_each_dpll(__display, __pll, __i) \ for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \ ((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++) diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 693b90e3dfc3c..8bec55deff9fe 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -535,7 +535,7 @@ static void ilk_init_pch_refclk(struct intel_display *display) } /* Check if any DPLLs are using the SSC source */ - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { u32 temp; temp = intel_de_read(display, PCH_DPLL(pll->info->id)); -- GitLab From 6cc235f79adb7aa594ebe18070d3b3c8d1ae1d30 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:52 +0530 Subject: [PATCH 096/902] drm/i915/dpll: Rename intel_shared_dpll_funcs Rename intel_shared_dpll_funcs to intel_dpll_funcs since it needs to represent both shared and individual dplls. --v2 -Change intel_global_dpll to intel_dpll_global to be more in line with the naming standard where the name should start with the file name [Jani] --v3 -Drop shared and global altogether [Jani] --v4 -Keep declarations sorted [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-6-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 24 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9974fdb6eaeb5..bdad4d72cc013 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -64,7 +64,7 @@ */ /* platform specific hooks for managing DPLLs */ -struct intel_shared_dpll_funcs { +struct intel_dpll_funcs { /* * Hook for enabling the pll, called from intel_enable_shared_dpll() if * the pll is not already enabled. @@ -670,7 +670,7 @@ static bool ibx_compare_hw_state(const struct intel_dpll_hw_state *_a, a->fp1 == b->fp1; } -static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { +static const struct intel_dpll_funcs ibx_pch_dpll_funcs = { .enable = ibx_pch_dpll_enable, .disable = ibx_pch_dpll_disable, .get_hw_state = ibx_pch_dpll_get_hw_state, @@ -1270,14 +1270,14 @@ static bool hsw_compare_hw_state(const struct intel_dpll_hw_state *_a, a->spll == b->spll; } -static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_wrpll_funcs = { .enable = hsw_ddi_wrpll_enable, .disable = hsw_ddi_wrpll_disable, .get_hw_state = hsw_ddi_wrpll_get_hw_state, .get_freq = hsw_ddi_wrpll_get_freq, }; -static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_spll_funcs = { .enable = hsw_ddi_spll_enable, .disable = hsw_ddi_spll_disable, .get_hw_state = hsw_ddi_spll_get_hw_state, @@ -1302,7 +1302,7 @@ static bool hsw_ddi_lcpll_get_hw_state(struct intel_display *display, return true; } -static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_lcpll_funcs = { .enable = hsw_ddi_lcpll_enable, .disable = hsw_ddi_lcpll_disable, .get_hw_state = hsw_ddi_lcpll_get_hw_state, @@ -2004,14 +2004,14 @@ static bool skl_compare_hw_state(const struct intel_dpll_hw_state *_a, a->cfgcr2 == b->cfgcr2; } -static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { +static const struct intel_dpll_funcs skl_ddi_pll_funcs = { .enable = skl_ddi_pll_enable, .disable = skl_ddi_pll_disable, .get_hw_state = skl_ddi_pll_get_hw_state, .get_freq = skl_ddi_pll_get_freq, }; -static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = { +static const struct intel_dpll_funcs skl_ddi_dpll0_funcs = { .enable = skl_ddi_dpll0_enable, .disable = skl_ddi_dpll0_disable, .get_hw_state = skl_ddi_dpll0_get_hw_state, @@ -2486,7 +2486,7 @@ static bool bxt_compare_hw_state(const struct intel_dpll_hw_state *_a, a->pcsdw12 == b->pcsdw12; } -static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { +static const struct intel_dpll_funcs bxt_ddi_pll_funcs = { .enable = bxt_ddi_pll_enable, .disable = bxt_ddi_pll_disable, .get_hw_state = bxt_ddi_pll_get_hw_state, @@ -4129,21 +4129,21 @@ static bool icl_compare_hw_state(const struct intel_dpll_hw_state *_a, a->mg_pll_tdc_coldst_bias == b->mg_pll_tdc_coldst_bias; } -static const struct intel_shared_dpll_funcs combo_pll_funcs = { +static const struct intel_dpll_funcs combo_pll_funcs = { .enable = combo_pll_enable, .disable = combo_pll_disable, .get_hw_state = combo_pll_get_hw_state, .get_freq = icl_ddi_combo_pll_get_freq, }; -static const struct intel_shared_dpll_funcs tbt_pll_funcs = { +static const struct intel_dpll_funcs tbt_pll_funcs = { .enable = tbt_pll_enable, .disable = tbt_pll_disable, .get_hw_state = tbt_pll_get_hw_state, .get_freq = icl_ddi_tbt_pll_get_freq, }; -static const struct intel_shared_dpll_funcs mg_pll_funcs = { +static const struct intel_dpll_funcs mg_pll_funcs = { .enable = mg_pll_enable, .disable = mg_pll_disable, .get_hw_state = mg_pll_get_hw_state, @@ -4191,7 +4191,7 @@ static const struct intel_dpll_mgr ehl_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; -static const struct intel_shared_dpll_funcs dkl_pll_funcs = { +static const struct intel_dpll_funcs dkl_pll_funcs = { .enable = mg_pll_enable, .disable = mg_pll_disable, .get_hw_state = dkl_pll_get_hw_state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index d930724868313..28f464d504fb5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -39,9 +39,9 @@ struct drm_printer; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_dpll_funcs; struct intel_encoder; struct intel_shared_dpll; -struct intel_shared_dpll_funcs; /** * enum intel_dpll_id - possible DPLL ids @@ -314,7 +314,7 @@ struct dpll_info { /** * @funcs: platform specific hooks */ - const struct intel_shared_dpll_funcs *funcs; + const struct intel_dpll_funcs *funcs; /** * @id: unique identifier for this DPLL -- GitLab From 386a183259482f3db971ac3c6b7a9126e8444034 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:53 +0530 Subject: [PATCH 097/902] drm/i915/dpll: Rename intel_shared_dpll Rename intel_shared_dpll to intel_dpll to represent both shared and individual dplls. Since from MTL each PHY has it's own PLL making the shared PLL naming a little outdated. In an effort to make this framework accepting of future changes this needs to be done. --v2 -Use intel_dpll_global to make sure names start with the filename [Jani/Ville] -Explain the need of this rename [Jani] --v3 -Just keep it intel_dpll [Jani] --v4 -Fix comment [Jani] -Use just num_dpll and dplls [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-7-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 52 ++-- drivers/gpu/drm/i915/display/intel_ddi.h | 6 +- drivers/gpu/drm/i915/display/intel_display.c | 12 +- .../gpu/drm/i915/display/intel_display_core.h | 4 +- .../drm/i915/display/intel_display_debugfs.c | 2 +- .../drm/i915/display/intel_display_types.h | 6 +- drivers/gpu/drm/i915/display/intel_dpll.c | 4 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 228 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 18 +- drivers/gpu/drm/i915/display/intel_fdi.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- .../drm/i915/display/intel_modeset_setup.c | 8 +- .../gpu/drm/i915/display/intel_pch_display.c | 10 +- .../gpu/drm/i915/display/intel_pch_refclk.c | 2 +- 15 files changed, 179 insertions(+), 179 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 28dab9320aedd..026361354e6fc 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -658,7 +658,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy; u32 val; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 74132c1d63858..4d631cbc81d28 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -236,7 +236,7 @@ static void intel_wait_ddi_buf_active(struct intel_encoder *encoder) port_name(port)); } -static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) +static u32 hsw_pll_to_ddi_pll_sel(const struct intel_dpll *pll) { switch (pll->info->id) { case DPLL_ID_WRPLL1: @@ -260,7 +260,7 @@ static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; int clock = crtc_state->port_clock; const enum intel_dpll_id id = pll->info->id; @@ -1561,7 +1561,7 @@ static bool _icl_ddi_is_clock_enabled(struct intel_display *display, i915_reg_t return !(intel_de_read(display, reg) & clk_off); } -static struct intel_shared_dpll * +static struct intel_dpll * _icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg, u32 clk_sel_mask, u32 clk_sel_shift) { @@ -1576,7 +1576,7 @@ static void adls_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1606,7 +1606,7 @@ static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder) ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *adls_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1620,7 +1620,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1650,7 +1650,7 @@ static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder) RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1664,7 +1664,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1703,7 +1703,7 @@ static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder) DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1730,7 +1730,7 @@ static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1760,7 +1760,7 @@ static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder) ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder) +struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1774,7 +1774,7 @@ static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -1817,7 +1817,7 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; @@ -1868,7 +1868,7 @@ static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder) return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port)); } -static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum tc_port tc_port = intel_encoder_to_tc(encoder); @@ -1898,7 +1898,7 @@ static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encode return intel_get_shared_dpll_by_id(display, id); } -static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder->base.dev); enum intel_dpll_id id; @@ -1925,7 +1925,7 @@ static void skl_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -1967,7 +1967,7 @@ static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder) return !(intel_de_read(display, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port)); } -static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; @@ -1993,7 +1993,7 @@ void hsw_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -2018,7 +2018,7 @@ bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder) return intel_de_read(display, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE; } -static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; @@ -4187,7 +4187,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, void intel_ddi_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_display *display = to_intel_display(encoder); enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; @@ -4203,7 +4203,7 @@ void intel_ddi_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll, + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, &crtc_state->dpll_hw_state); } @@ -4257,7 +4257,7 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll) +static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) { return pll->info->id == DPLL_ID_ICL_TBTPLL; } @@ -4267,7 +4267,7 @@ icl_ddi_tc_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; if (drm_WARN_ON(display->drm, !pll)) return ICL_PORT_DPLL_DEFAULT; @@ -4290,7 +4290,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder, static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_display *display = to_intel_display(encoder); enum icl_port_dpll_id port_dpll_id; @@ -4313,10 +4313,10 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll)) + if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll)) crtc_state->port_clock = icl_calc_tbt_pll_link(display, encoder->port); else - crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll, + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, &crtc_state->dpll_hw_state); } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 353eb04079e9c..f6f511bb04314 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -16,9 +16,9 @@ struct intel_crtc; struct intel_crtc_state; struct intel_display; struct intel_dp; +struct intel_dpll; struct intel_dpll_hw_state; struct intel_encoder; -struct intel_shared_dpll; enum pipe; enum port; enum transcoder; @@ -40,7 +40,7 @@ void intel_ddi_enable_clock(struct intel_encoder *encoder, void intel_ddi_disable_clock(struct intel_encoder *encoder); void intel_ddi_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll); + struct intel_dpll *pll); void hsw_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void hsw_ddi_disable_clock(struct intel_encoder *encoder); @@ -50,7 +50,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void hsw_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state); -struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder); +struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder); void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_wait_ddi_buf_idle(struct intel_display *display, enum port port); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1b09f8ae76ffe..20a940af0db12 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1325,7 +1325,7 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state) if (intel_crtc_needs_modeset(new_crtc_state)) continue; - new_crtc_state->shared_dpll = old_crtc_state->shared_dpll; + new_crtc_state->intel_dpll = old_crtc_state->intel_dpll; new_crtc_state->dpll_hw_state = old_crtc_state->dpll_hw_state; } } @@ -1663,7 +1663,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); - if (new_crtc_state->shared_dpll) + if (new_crtc_state->intel_dpll) intel_enable_shared_dpll(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1959,7 +1959,7 @@ static void get_crtc_power_domains(struct intel_crtc_state *crtc_state, if (HAS_DDI(display) && crtc_state->has_audio) set_bit(POWER_DOMAIN_AUDIO_MMIO, mask->bits); - if (crtc_state->shared_dpll) + if (crtc_state->intel_dpll) set_bit(POWER_DOMAIN_DISPLAY_CORE, mask->bits); if (crtc_state->dsc.compression_enable) @@ -4509,7 +4509,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state, /* preserve some things from the slave's original crtc state */ saved_state->uapi = secondary_crtc_state->uapi; saved_state->scaler_state = secondary_crtc_state->scaler_state; - saved_state->shared_dpll = secondary_crtc_state->shared_dpll; + saved_state->intel_dpll = secondary_crtc_state->intel_dpll; saved_state->crc_enabled = secondary_crtc_state->crc_enabled; intel_crtc_free_hw_state(secondary_crtc_state); @@ -4572,7 +4572,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, saved_state->uapi = crtc_state->uapi; saved_state->inherited = crtc_state->inherited; saved_state->scaler_state = crtc_state->scaler_state; - saved_state->shared_dpll = crtc_state->shared_dpll; + saved_state->intel_dpll = crtc_state->intel_dpll; saved_state->dpll_hw_state = crtc_state->dpll_hw_state; memcpy(saved_state->icl_port_dplls, crtc_state->icl_port_dplls, sizeof(saved_state->icl_port_dplls)); @@ -5326,7 +5326,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); if (display->dpll.mgr) - PIPE_CONF_CHECK_P(shared_dpll); + PIPE_CONF_CHECK_P(intel_dpll); /* FIXME convert everything over the dpll_mgr */ if (display->dpll.mgr || HAS_GMCH(display)) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index e0221e514326b..5f5dd2722d99c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -125,8 +125,8 @@ struct intel_audio { struct intel_dpll_global { struct mutex lock; - int num_shared_dpll; - struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; + int num_dpll; + struct intel_dpll dplls[I915_NUM_PLLS]; const struct intel_dpll_mgr *mgr; struct { diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 11a7fec202327..3c323f694e694 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -618,7 +618,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) { struct intel_display *display = node_to_intel_display(m->private); struct drm_printer p = drm_seq_file_printer(m); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; drm_modeset_lock_all(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9df7795b9327a..b8836d29a7214 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1079,8 +1079,8 @@ struct intel_crtc_state { * haswell. */ struct dpll dpll; - /* Selected dpll when shared or NULL. */ - struct intel_shared_dpll *shared_dpll; + /* Selected dpll or NULL. */ + struct intel_dpll *intel_dpll; /* Actual register state of the dpll, for shared dpll cross-checking. */ struct intel_dpll_hw_state dpll_hw_state; @@ -1090,7 +1090,7 @@ struct intel_crtc_state { * setting shared_dpll and dpll_hw_state to one of these reserved ones. */ struct icl_port_dpll { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; struct intel_dpll_hw_state hw_state; } icl_port_dplls[ICL_PORT_DPLL_COUNT]; diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c13fb37ea584f..9db46439592ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1768,9 +1768,9 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, int ret; drm_WARN_ON(display->drm, !intel_crtc_needs_modeset(crtc_state)); - drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->shared_dpll); + drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->intel_dpll); - if (!crtc_state->hw.enable || crtc_state->shared_dpll) + if (!crtc_state->hw.enable || crtc_state->intel_dpll) return 0; if (!display->funcs.dpll->crtc_get_shared_dpll) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bdad4d72cc013..6fbbc5e89f3ce 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -70,7 +70,7 @@ struct intel_dpll_funcs { * the pll is not already enabled. */ void (*enable)(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); /* @@ -79,7 +79,7 @@ struct intel_dpll_funcs { * tracked users for it. */ void (*disable)(struct intel_display *display, - struct intel_shared_dpll *pll); + struct intel_dpll *pll); /* * Hook for reading the values currently programmed to the DPLL @@ -87,7 +87,7 @@ struct intel_dpll_funcs { * verification after a mode set. */ bool (*get_hw_state)(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); /* @@ -95,7 +95,7 @@ struct intel_dpll_funcs { * in state. */ int (*get_freq)(struct intel_display *i915, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); }; @@ -124,7 +124,7 @@ static void intel_atomic_duplicate_dpll_state(struct intel_display *display, struct intel_dpll_state *dpll_state) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; /* Copy dpll state */ @@ -158,11 +158,11 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) * Returns: * A pointer to the DPLL with @id */ -struct intel_shared_dpll * +struct intel_dpll * intel_get_shared_dpll_by_id(struct intel_display *display, enum intel_dpll_id id) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) { @@ -176,7 +176,7 @@ intel_get_shared_dpll_by_id(struct intel_display *display, /* For ILK+ */ void assert_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, bool state) { bool cur_state; @@ -205,7 +205,7 @@ enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port) static i915_reg_t intel_combo_pll_enable_reg(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (display->platform.dg1) return DG1_DPLL_ENABLE(pll->info->id); @@ -218,7 +218,7 @@ intel_combo_pll_enable_reg(struct intel_display *display, static i915_reg_t intel_tc_pll_enable_reg(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; enum tc_port tc_port = icl_pll_id_to_tc_port(id); @@ -230,7 +230,7 @@ intel_tc_pll_enable_reg(struct intel_display *display, } static void _intel_enable_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (pll->info->power_domain) pll->wakeref = intel_display_power_get(display, pll->info->power_domain); @@ -240,7 +240,7 @@ static void _intel_enable_shared_dpll(struct intel_display *display, } static void _intel_disable_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { pll->info->funcs->disable(display, pll); pll->on = false; @@ -259,7 +259,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; unsigned int pipe_mask = intel_crtc_joined_pipe_mask(crtc_state); unsigned int old_mask; @@ -305,7 +305,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; unsigned int pipe_mask = intel_crtc_joined_pipe_mask(crtc_state); /* PCH only available on ILK+ */ @@ -344,7 +344,7 @@ out: static unsigned long intel_dpll_mask_all(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; unsigned long dpll_mask = 0; int i; @@ -357,7 +357,7 @@ intel_dpll_mask_all(struct intel_display *display) return dpll_mask; } -static struct intel_shared_dpll * +static struct intel_dpll * intel_find_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_dpll_hw_state *dpll_hw_state, @@ -366,7 +366,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); struct intel_dpll_state *dpll_state; - struct intel_shared_dpll *unused_pll = NULL; + struct intel_dpll *unused_pll = NULL; enum intel_dpll_id id; dpll_state = intel_atomic_get_shared_dpll_state(&state->base); @@ -374,7 +374,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); for_each_set_bit(id, &dpll_mask, fls(dpll_mask_all)) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; pll = intel_get_shared_dpll_by_id(display, id); if (!pll) @@ -421,7 +421,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, */ static void intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -437,7 +437,7 @@ intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, static void intel_reference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { struct intel_dpll_state *dpll_state; @@ -460,7 +460,7 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, */ void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -475,7 +475,7 @@ intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, static void intel_unreference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll) + const struct intel_dpll *pll) { struct intel_dpll_state *dpll_state; @@ -492,12 +492,12 @@ static void intel_put_dpll(struct intel_atomic_state *state, struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - new_crtc_state->shared_dpll = NULL; + new_crtc_state->intel_dpll = NULL; - if (!old_crtc_state->shared_dpll) + if (!old_crtc_state->intel_dpll) return; - intel_unreference_shared_dpll(state, crtc, old_crtc_state->shared_dpll); + intel_unreference_shared_dpll(state, crtc, old_crtc_state->intel_dpll); } /** @@ -515,7 +515,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll_state *dpll_state = state->dpll_state; - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; if (!state->dpll_set) @@ -526,7 +526,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) } static bool ibx_pch_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; @@ -562,7 +562,7 @@ static void ibx_assert_pch_refclk_enabled(struct intel_display *display) } static void ibx_pch_dpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; @@ -591,7 +591,7 @@ static void ibx_pch_dpll_enable(struct intel_display *display, } static void ibx_pch_dpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; @@ -614,7 +614,7 @@ static int ibx_get_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id id; if (HAS_PCH_IBX(display)) { @@ -640,7 +640,7 @@ static int ibx_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -692,7 +692,7 @@ static const struct intel_dpll_mgr pch_pll_mgr = { }; static void hsw_ddi_wrpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -704,7 +704,7 @@ static void hsw_ddi_wrpll_enable(struct intel_display *display, } static void hsw_ddi_spll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -715,7 +715,7 @@ static void hsw_ddi_spll_enable(struct intel_display *display, } static void hsw_ddi_wrpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; @@ -731,7 +731,7 @@ static void hsw_ddi_wrpll_disable(struct intel_display *display, } static void hsw_ddi_spll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { enum intel_dpll_id id = pll->info->id; @@ -747,7 +747,7 @@ static void hsw_ddi_spll_disable(struct intel_display *display, } static bool hsw_ddi_wrpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -769,7 +769,7 @@ static bool hsw_ddi_wrpll_get_hw_state(struct intel_display *display, } static bool hsw_ddi_spll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -996,7 +996,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, } static int hsw_ddi_wrpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -1059,7 +1059,7 @@ hsw_ddi_wrpll_compute_dpll(struct intel_atomic_state *state, return 0; } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1090,11 +1090,11 @@ hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state) } } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id pll_id; int clock = crtc_state->port_clock; @@ -1122,7 +1122,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) } static int hsw_ddi_lcpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { int link_clock = 0; @@ -1162,7 +1162,7 @@ hsw_ddi_spll_compute_dpll(struct intel_atomic_state *state, return 0; } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1174,7 +1174,7 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, } static int hsw_ddi_spll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -1221,7 +1221,7 @@ static int hsw_get_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll = NULL; + struct intel_dpll *pll = NULL; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) pll = hsw_ddi_wrpll_get_dpll(state, crtc); @@ -1236,7 +1236,7 @@ static int hsw_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -1285,18 +1285,18 @@ static const struct intel_dpll_funcs hsw_ddi_spll_funcs = { }; static void hsw_ddi_lcpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *hw_state) { } static void hsw_ddi_lcpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { } static bool hsw_ddi_lcpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return true; @@ -1364,7 +1364,7 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = { }; static void skl_ddi_pll_write_ctrl1(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct skl_dpll_hw_state *hw_state) { const enum intel_dpll_id id = pll->info->id; @@ -1378,7 +1378,7 @@ static void skl_ddi_pll_write_ctrl1(struct intel_display *display, } static void skl_ddi_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1400,7 +1400,7 @@ static void skl_ddi_pll_enable(struct intel_display *display, } static void skl_ddi_dpll0_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1409,7 +1409,7 @@ static void skl_ddi_dpll0_enable(struct intel_display *display, } static void skl_ddi_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const struct skl_dpll_regs *regs = skl_dpll_regs; const enum intel_dpll_id id = pll->info->id; @@ -1420,12 +1420,12 @@ static void skl_ddi_pll_disable(struct intel_display *display, } static void skl_ddi_dpll0_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { } static bool skl_ddi_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1463,7 +1463,7 @@ out: } static bool skl_ddi_dpll0_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1736,7 +1736,7 @@ skip_remaining_dividers: } static int skl_ddi_wrpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1884,7 +1884,7 @@ skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) } static int skl_ddi_lcpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1939,7 +1939,7 @@ static int skl_get_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) pll = intel_find_shared_dpll(state, crtc, @@ -1957,13 +1957,13 @@ static int skl_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } static int skl_ddi_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -2038,7 +2038,7 @@ static const struct intel_dpll_mgr skl_pll_mgr = { }; static void bxt_ddi_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2141,7 +2141,7 @@ static void bxt_ddi_pll_enable(struct intel_display *display, } static void bxt_ddi_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ @@ -2160,7 +2160,7 @@ static void bxt_ddi_pll_disable(struct intel_display *display, } static bool bxt_ddi_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2360,7 +2360,7 @@ static int bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, } static int bxt_ddi_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2429,7 +2429,7 @@ static int bxt_get_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id id; /* 1:1 mapping between ports and PLLs */ @@ -2442,7 +2442,7 @@ static int bxt_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -2755,7 +2755,7 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, } static int icl_ddi_tbt_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { /* @@ -2826,7 +2826,7 @@ icl_calc_wrpll(struct intel_crtc_state *crtc_state, } static int icl_ddi_combo_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3199,7 +3199,7 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, } static int icl_ddi_mg_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3285,7 +3285,7 @@ void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; - crtc_state->shared_dpll = port_dpll->pll; + crtc_state->intel_dpll = port_dpll->pll; crtc_state->dpll_hw_state = port_dpll->hw_state; } @@ -3428,8 +3428,8 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state, return ret; /* this is mainly for the fastset check */ - if (old_crtc_state->shared_dpll && - old_crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL) + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL) icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); else icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY); @@ -3521,7 +3521,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum icl_port_dpll_id id; - new_crtc_state->shared_dpll = NULL; + new_crtc_state->intel_dpll = NULL; for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { const struct icl_port_dpll *old_port_dpll = @@ -3539,7 +3539,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, } static bool mg_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3606,7 +3606,7 @@ out: } static bool dkl_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3678,7 +3678,7 @@ out: } static bool icl_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state, i915_reg_t enable_reg) { @@ -3739,7 +3739,7 @@ out: } static bool combo_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { i915_reg_t enable_reg = intel_combo_pll_enable_reg(display, pll); @@ -3748,14 +3748,14 @@ static bool combo_pll_get_hw_state(struct intel_display *display, } static bool tbt_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return icl_pll_get_hw_state(display, pll, dpll_hw_state, TBT_PLL_ENABLE); } static void icl_dpll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { const enum intel_dpll_id id = pll->info->id; @@ -3797,7 +3797,7 @@ static void icl_dpll_write(struct intel_display *display, } static void icl_mg_pll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); @@ -3840,7 +3840,7 @@ static void icl_mg_pll_write(struct intel_display *display, } static void dkl_pll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); @@ -3905,7 +3905,7 @@ static void dkl_pll_write(struct intel_display *display, } static void icl_pll_power_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { intel_de_rmw(display, enable_reg, 0, PLL_POWER_ENABLE); @@ -3920,7 +3920,7 @@ static void icl_pll_power_enable(struct intel_display *display, } static void icl_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { intel_de_rmw(display, enable_reg, 0, PLL_ENABLE); @@ -3930,7 +3930,7 @@ static void icl_pll_enable(struct intel_display *display, drm_err(display->drm, "PLL %d not locked\n", pll->info->id); } -static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct intel_shared_dpll *pll) +static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct intel_dpll *pll) { u32 val; @@ -3955,7 +3955,7 @@ static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct inte } static void combo_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3979,7 +3979,7 @@ static void combo_pll_enable(struct intel_display *display, } static void tbt_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4000,7 +4000,7 @@ static void tbt_pll_enable(struct intel_display *display, } static void mg_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4025,7 +4025,7 @@ static void mg_pll_enable(struct intel_display *display, } static void icl_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { /* The first steps are done by intel_ddi_post_disable(). */ @@ -4056,7 +4056,7 @@ static void icl_pll_disable(struct intel_display *display, } static void combo_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { i915_reg_t enable_reg = intel_combo_pll_enable_reg(display, pll); @@ -4064,13 +4064,13 @@ static void combo_pll_disable(struct intel_display *display, } static void tbt_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { icl_pll_disable(display, pll, TBT_PLL_ENABLE); } static void mg_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { i915_reg_t enable_reg = intel_tc_pll_enable_reg(display, pll); @@ -4346,19 +4346,19 @@ void intel_shared_dpll_init(struct intel_display *display) for (i = 0; dpll_info[i].name; i++) { if (drm_WARN_ON(display->drm, - i >= ARRAY_SIZE(display->dpll.shared_dplls))) + i >= ARRAY_SIZE(display->dpll.dplls))) break; /* must fit into unsigned long bitmask on 32bit */ if (drm_WARN_ON(display->drm, dpll_info[i].id >= 32)) break; - display->dpll.shared_dplls[i].info = &dpll_info[i]; - display->dpll.shared_dplls[i].index = i; + display->dpll.dplls[i].info = &dpll_info[i]; + display->dpll.dplls[i].index = i; } display->dpll.mgr = dpll_mgr; - display->dpll.num_shared_dpll = i; + display->dpll.num_dpll = i; } /** @@ -4482,7 +4482,7 @@ void intel_update_active_dpll(struct intel_atomic_state *state, * Return the output frequency corresponding to @pll's passed in @dpll_hw_state. */ int intel_dpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { if (drm_WARN_ON(display->drm, !pll->info->funcs->get_freq)) @@ -4500,14 +4500,14 @@ int intel_dpll_get_freq(struct intel_display *display, * Read out @pll's hardware state into @dpll_hw_state. */ bool intel_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return pll->info->funcs->get_hw_state(display, pll, dpll_hw_state); } static void readout_dpll_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_crtc *crtc; @@ -4521,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - if (crtc_state->hw.active && crtc_state->shared_dpll == pll) + if (crtc_state->hw.active && crtc_state->intel_dpll == pll) intel_reference_shared_dpll_crtc(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; @@ -4539,7 +4539,7 @@ void intel_dpll_update_ref_clks(struct intel_display *display) void intel_dpll_readout_hw_state(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) @@ -4547,7 +4547,7 @@ void intel_dpll_readout_hw_state(struct intel_display *display) } static void sanitize_dpll_state(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (!pll->on) return; @@ -4566,7 +4566,7 @@ static void sanitize_dpll_state(struct intel_display *display, void intel_dpll_sanitize_state(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; intel_cx0_pll_power_save_wa(display); @@ -4623,7 +4623,7 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, static void verify_single_dpll_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_crtc *crtc, const struct intel_crtc_state *new_crtc_state) { @@ -4676,8 +4676,8 @@ verify_single_dpll_state(struct intel_display *display, pll->info->name); } -static bool has_alt_port_dpll(const struct intel_shared_dpll *old_pll, - const struct intel_shared_dpll *new_pll) +static bool has_alt_port_dpll(const struct intel_dpll *old_pll, + const struct intel_dpll *new_pll) { return old_pll && new_pll && old_pll != new_pll && (old_pll->info->is_alt_port_dpll || new_pll->info->is_alt_port_dpll); @@ -4692,22 +4692,22 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - if (new_crtc_state->shared_dpll) - verify_single_dpll_state(display, new_crtc_state->shared_dpll, + if (new_crtc_state->intel_dpll) + verify_single_dpll_state(display, new_crtc_state->intel_dpll, crtc, new_crtc_state); - if (old_crtc_state->shared_dpll && - old_crtc_state->shared_dpll != new_crtc_state->shared_dpll) { + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll != new_crtc_state->intel_dpll) { u8 pipe_mask = BIT(crtc->pipe); - struct intel_shared_dpll *pll = old_crtc_state->shared_dpll; + struct intel_dpll *pll = old_crtc_state->intel_dpll; INTEL_DISPLAY_STATE_WARN(display, pll->active_mask & pipe_mask, "%s: pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n", pll->info->name, pipe_name(crtc->pipe), pll->active_mask); /* TC ports have both MG/TC and TBT PLL referenced simultaneously */ - INTEL_DISPLAY_STATE_WARN(display, !has_alt_port_dpll(old_crtc_state->shared_dpll, - new_crtc_state->shared_dpll) && + INTEL_DISPLAY_STATE_WARN(display, !has_alt_port_dpll(old_crtc_state->intel_dpll, + new_crtc_state->intel_dpll) && pll->state.pipe_mask & pipe_mask, "%s: pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n", pll->info->name, pipe_name(crtc->pipe), pll->state.pipe_mask); @@ -4717,7 +4717,7 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 28f464d504fb5..ea3fb7002e653 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -31,8 +31,8 @@ #include "intel_wakeref.h" #define for_each_dpll(__display, __pll, __i) \ - for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \ - ((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++) + for ((__i) = 0; (__i) < (__display)->dpll.num_dpll && \ + ((__pll) = &(__display)->dpll.dplls[(__i)]) ; (__i)++) enum tc_port; struct drm_printer; @@ -344,9 +344,9 @@ struct dpll_info { }; /** - * struct intel_shared_dpll - display PLL with tracked state and users + * struct intel_dpll - display PLL with tracked state and users */ -struct intel_shared_dpll { +struct intel_dpll { /** * @state: * @@ -388,11 +388,11 @@ struct intel_shared_dpll { #define SKL_DPLL3 3 /* shared dpll functions */ -struct intel_shared_dpll * +struct intel_dpll * intel_get_shared_dpll_by_id(struct intel_display *display, enum intel_dpll_id id); void assert_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, bool state); #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) @@ -405,7 +405,7 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state, void intel_release_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); @@ -413,10 +413,10 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); int intel_dpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); bool intel_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 169bbe154b5c5..b1d2ba9b7295f 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -910,7 +910,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder, intel_de_write(display, FDI_RX_CTL(PIPE_A), rx_ctl_val); /* Configure Port Clock Select */ - drm_WARN_ON(display->drm, crtc_state->shared_dpll->info->id != DPLL_ID_SPLL); + drm_WARN_ON(display->drm, crtc_state->intel_dpll->info->id != DPLL_ID_SPLL); intel_ddi_enable_clock(encoder, crtc_state); /* Start the training iterating through available voltages and emphasis, diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 8ce7c630da527..ec8f38fba1785 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -249,7 +249,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state, if (HAS_PCH_SPLIT(display)) { assert_fdi_rx_pll_disabled(display, pipe); - assert_shared_dpll_disabled(display, crtc_state->shared_dpll); + assert_shared_dpll_disabled(display, crtc_state->intel_dpll); } else { assert_pll_disabled(display, pipe); } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 0325b0c9506dd..46e0002a13586 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -92,10 +92,10 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->active = false; crtc->base.enabled = false; - if (crtc_state->shared_dpll) + if (crtc_state->intel_dpll) intel_unreference_shared_dpll_crtc(crtc, - crtc_state->shared_dpll, - &crtc_state->shared_dpll->state); + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, @@ -565,7 +565,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) */ return display->platform.sandybridge && crtc_state->hw.active && - crtc_state->shared_dpll && + crtc_state->intel_dpll && crtc_state->port_clock == 0; } diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 1743ebf551cbe..b38305c16e77c 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -251,7 +251,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) u32 val, pipeconf_val; /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(display, crtc_state->shared_dpll); + assert_shared_dpll_enabled(display, crtc_state->intel_dpll); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(display, pipe); @@ -381,7 +381,7 @@ void ilk_pch_enable(struct intel_atomic_state *state, temp = intel_de_read(display, PCH_DPLL_SEL); temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); - if (crtc_state->shared_dpll == + if (crtc_state->intel_dpll == intel_get_shared_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) temp |= sel; else @@ -496,7 +496,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum pipe pipe = crtc->pipe; enum intel_dpll_id pll_id; bool pll_active; @@ -528,8 +528,8 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) pll_id = DPLL_ID_PCH_PLL_A; } - crtc_state->shared_dpll = intel_get_shared_dpll_by_id(display, pll_id); - pll = crtc_state->shared_dpll; + crtc_state->intel_dpll = intel_get_shared_dpll_by_id(display, pll_id); + pll = crtc_state->intel_dpll; pll_active = intel_dpll_get_hw_state(display, pll, &crtc_state->dpll_hw_state); diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 8bec55deff9fe..9f6102d7c7be7 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -499,7 +499,7 @@ static void lpt_init_pch_refclk(struct intel_display *display) static void ilk_init_pch_refclk(struct intel_display *display) { struct intel_encoder *encoder; - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; u32 val, final; bool has_lvds = false; -- GitLab From 2b3b9a8faf56a61634e734afc01da9a9ea1265cf Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:54 +0530 Subject: [PATCH 098/902] drm/i915/dpll: Move away from using shared dpll Rename functions to move away from using shared dpll in the dpll framework as much as possible since dpll may not always be shared. --v2 -Use intel_dpll_global instead of global_dpll [Jani] --v3 -Just use intel_dpll [Jani] --v4 -Drop the global from comments [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-8-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 14 +- drivers/gpu/drm/i915/display/intel_display.c | 8 +- .../drm/i915/display/intel_display_driver.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 10 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 235 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 52 ++-- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- .../drm/i915/display/intel_modeset_setup.c | 6 +- .../drm/i915/display/intel_modeset_verify.c | 4 +- .../gpu/drm/i915/display/intel_pch_display.c | 14 +- 10 files changed, 173 insertions(+), 174 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 4d631cbc81d28..11ebcb40c91f6 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1569,7 +1569,7 @@ _icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg, id = (intel_de_read(display, reg) & clk_sel_mask) >> clk_sel_shift; - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void adls_ddi_enable_clock(struct intel_encoder *encoder, @@ -1723,7 +1723,7 @@ static struct intel_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) if (phy >= PHY_C) id += DPLL_ID_DG1_DPLL2; - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, @@ -1895,7 +1895,7 @@ static struct intel_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) @@ -1918,7 +1918,7 @@ static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void skl_ddi_enable_clock(struct intel_encoder *encoder, @@ -1986,7 +1986,7 @@ static struct intel_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >> DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port); - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } void hsw_ddi_enable_clock(struct intel_encoder *encoder, @@ -2053,7 +2053,7 @@ static struct intel_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } void intel_ddi_enable_clock(struct intel_encoder *encoder, @@ -2760,7 +2760,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, * 4. Enable the port PLL. * * The PLL enabling itself was already done before this function by - * hsw_crtc_enable()->intel_enable_shared_dpll(). We need only + * hsw_crtc_enable()->intel_enable_dpll(). We need only * configure the PLL to port mapping here. */ intel_ddi_enable_clock(encoder, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 20a940af0db12..858d9397b6708 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1664,7 +1664,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); if (new_crtc_state->intel_dpll) - intel_enable_shared_dpll(new_crtc_state); + intel_enable_dpll(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1793,7 +1793,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); - intel_disable_shared_dpll(old_crtc_state); + intel_disable_dpll(old_crtc_state); intel_encoders_post_pll_disable(state, crtc); @@ -6436,7 +6436,7 @@ int intel_atomic_check(struct drm_device *dev, any_ms = true; - intel_release_shared_dplls(state, crtc); + intel_release_dplls(state, crtc); } if (any_ms && !check_digital_port_conflicts(state)) { @@ -7533,7 +7533,7 @@ static int intel_atomic_swap_state(struct intel_atomic_state *state) intel_atomic_swap_global_state(state); - intel_shared_dpll_swap_state(state); + intel_dpll_swap_state(state); intel_atomic_track_fbs(state); diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 5c74ab5fd1aa5..16d91be02bb91 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -446,7 +446,7 @@ int intel_display_driver_probe_nogem(struct intel_display *display) } intel_plane_possible_crtcs_init(display); - intel_shared_dpll_init(display); + intel_dpll_init(display); intel_fdi_pll_freq_update(display); intel_update_czclk(display); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 9db46439592ea..80de897a761fb 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1162,7 +1162,7 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - ret = intel_compute_shared_dplls(state, crtc, encoder); + ret = intel_compute_dplls(state, crtc, encoder); if (ret) return ret; @@ -1190,7 +1190,7 @@ static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - return intel_reserve_shared_dplls(state, crtc, encoder); + return intel_reserve_dplls(state, crtc, encoder); } static int dg2_crtc_compute_clock(struct intel_atomic_state *state, @@ -1224,7 +1224,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, if (ret) return ret; - /* TODO: Do the readback via intel_compute_shared_dplls() */ + /* TODO: Do the readback via intel_compute_dplls() */ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); @@ -1395,7 +1395,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, ilk_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); - ret = intel_compute_shared_dplls(state, crtc, NULL); + ret = intel_compute_dplls(state, crtc, NULL); if (ret) return ret; @@ -1415,7 +1415,7 @@ static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, if (!crtc_state->has_pch_encoder) return 0; - return intel_reserve_shared_dplls(state, crtc, NULL); + return intel_reserve_dplls(state, crtc, NULL); } static u32 vlv_dpll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6fbbc5e89f3ce..69271892067a8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -52,21 +52,21 @@ * share a PLL if their configurations match. * * This file provides an abstraction over display PLLs. The function - * intel_shared_dpll_init() initializes the PLLs for the given platform. The + * intel_dpll_init() initializes the PLLs for the given platform. The * users of a PLL are tracked and that tracking is integrated with the atomic * modset interface. During an atomic operation, required PLLs can be reserved * for a given CRTC and encoder configuration by calling - * intel_reserve_shared_dplls() and previously reserved PLLs can be released - * with intel_release_shared_dplls(). + * intel_reserve_dplls() and previously reserved PLLs can be released + * with intel_release_dplls(). * Changes to the users are first staged in the atomic state, and then made - * effective by calling intel_shared_dpll_swap_state() during the atomic + * effective by calling intel_dpll_swap_state() during the atomic * commit phase. */ /* platform specific hooks for managing DPLLs */ struct intel_dpll_funcs { /* - * Hook for enabling the pll, called from intel_enable_shared_dpll() if + * Hook for enabling the pll, called from intel_enable_dpll() if * the pll is not already enabled. */ void (*enable)(struct intel_display *display, @@ -74,7 +74,7 @@ struct intel_dpll_funcs { const struct intel_dpll_hw_state *dpll_hw_state); /* - * Hook for disabling the pll, called from intel_disable_shared_dpll() + * Hook for disabling the pll, called from intel_disable_dpll() * only when it is safe to disable the pll, i.e., there are no more * tracked users for it. */ @@ -133,7 +133,7 @@ intel_atomic_duplicate_dpll_state(struct intel_display *display, } static struct intel_dpll_state * -intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) +intel_atomic_get_dpll_state(struct drm_atomic_state *s) { struct intel_atomic_state *state = to_intel_atomic_state(s); struct intel_display *display = to_intel_display(state); @@ -151,7 +151,7 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) } /** - * intel_get_shared_dpll_by_id - get a DPLL given its id + * intel_get_dpll_by_id - get a DPLL given its id * @display: intel_display device instance * @id: pll id * @@ -159,8 +159,8 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) * A pointer to the DPLL with @id */ struct intel_dpll * -intel_get_shared_dpll_by_id(struct intel_display *display, - enum intel_dpll_id id) +intel_get_dpll_by_id(struct intel_display *display, + enum intel_dpll_id id) { struct intel_dpll *pll; int i; @@ -175,9 +175,9 @@ intel_get_shared_dpll_by_id(struct intel_display *display, } /* For ILK+ */ -void assert_shared_dpll(struct intel_display *display, - struct intel_dpll *pll, - bool state) +void assert_dpll(struct intel_display *display, + struct intel_dpll *pll, + bool state) { bool cur_state; struct intel_dpll_hw_state hw_state; @@ -250,12 +250,12 @@ static void _intel_disable_shared_dpll(struct intel_display *display, } /** - * intel_enable_shared_dpll - enable a CRTC's shared DPLL - * @crtc_state: CRTC, and its state, which has a shared DPLL + * intel_enable_dpll - enable a CRTC's DPLL + * @crtc_state: CRTC, and its state, which has a DPLL * - * Enable the shared DPLL used by @crtc. + * Enable DPLL used by @crtc. */ -void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) +void intel_enable_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -282,7 +282,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) if (old_mask) { drm_WARN_ON(display->drm, !pll->on); - assert_shared_dpll_enabled(display, pll); + assert_dpll_enabled(display, pll); goto out; } drm_WARN_ON(display->drm, pll->on); @@ -296,12 +296,12 @@ out: } /** - * intel_disable_shared_dpll - disable a CRTC's shared DPLL + * intel_disable_dpll - disable a CRTC's shared DPLL * @crtc_state: CRTC, and its state, which has a shared DPLL * - * Disable the shared DPLL used by @crtc. + * Disable DPLL used by @crtc. */ -void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) +void intel_disable_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -326,7 +326,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) pll->info->name, pll->active_mask, pll->on, crtc->base.base.id, crtc->base.name); - assert_shared_dpll_enabled(display, pll); + assert_dpll_enabled(display, pll); drm_WARN_ON(display->drm, !pll->on); pll->active_mask &= ~pipe_mask; @@ -358,10 +358,10 @@ intel_dpll_mask_all(struct intel_display *display) } static struct intel_dpll * -intel_find_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll_hw_state *dpll_hw_state, - unsigned long dpll_mask) +intel_find_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll_hw_state *dpll_hw_state, + unsigned long dpll_mask) { struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); @@ -369,14 +369,14 @@ intel_find_shared_dpll(struct intel_atomic_state *state, struct intel_dpll *unused_pll = NULL; enum intel_dpll_id id; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); for_each_set_bit(id, &dpll_mask, fls(dpll_mask_all)) { struct intel_dpll *pll; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); if (!pll) continue; @@ -412,7 +412,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, } /** - * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC + * intel_reference_dpll_crtc - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -420,9 +420,9 @@ intel_find_shared_dpll(struct intel_atomic_state *state, * Take a reference for @pll tracking the use of it by @crtc. */ static void -intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_reference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -435,23 +435,23 @@ intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, } static void -intel_reference_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll *pll, - const struct intel_dpll_hw_state *dpll_hw_state) +intel_reference_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { struct intel_dpll_state *dpll_state; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); if (dpll_state[pll->index].pipe_mask == 0) dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_reference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } /** - * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC + * intel_unreference_dpll_crtc - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -459,9 +459,9 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, * Drop a reference for @pll tracking the end of use of it by @crtc. */ void -intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_unreference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -473,15 +473,15 @@ intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, crtc->base.base.id, crtc->base.name, pll->info->name); } -static void intel_unreference_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll *pll) +static void intel_unreference_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll *pll) { struct intel_dpll_state *dpll_state; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); - intel_unreference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_unreference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, @@ -497,11 +497,11 @@ static void intel_put_dpll(struct intel_atomic_state *state, if (!old_crtc_state->intel_dpll) return; - intel_unreference_shared_dpll(state, crtc, old_crtc_state->intel_dpll); + intel_unreference_dpll(state, crtc, old_crtc_state->intel_dpll); } /** - * intel_shared_dpll_swap_state - make atomic DPLL configuration effective + * intel_dpll_swap_state - make atomic DPLL configuration effective * @state: atomic state * * This is the dpll version of drm_atomic_helper_swap_state() since the @@ -511,7 +511,7 @@ static void intel_put_dpll(struct intel_atomic_state *state, * i.e. it also puts the current state into @state, even though there is no * need for that at this moment. */ -void intel_shared_dpll_swap_state(struct intel_atomic_state *state) +void intel_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll_state *dpll_state = state->dpll_state; @@ -620,25 +620,25 @@ static int ibx_get_dpll(struct intel_atomic_state *state, if (HAS_PCH_IBX(display)) { /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ id = (enum intel_dpll_id) crtc->pipe; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); drm_dbg_kms(display->drm, "[CRTC:%d:%s] using pre-allocated %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); } else { - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_PCH_PLL_B) | - BIT(DPLL_ID_PCH_PLL_A)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_PCH_PLL_B) | + BIT(DPLL_ID_PCH_PLL_A)); } if (!pll) return -EINVAL; /* reference the pll */ - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -1066,7 +1066,7 @@ hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - return intel_find_shared_dpll(state, crtc, + return intel_find_dpll(state, crtc, &crtc_state->dpll_hw_state, BIT(DPLL_ID_WRPLL2) | BIT(DPLL_ID_WRPLL1)); @@ -1113,7 +1113,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) return NULL; } - pll = intel_get_shared_dpll_by_id(display, pll_id); + pll = intel_get_dpll_by_id(display, pll_id); if (!pll) return NULL; @@ -1169,7 +1169,7 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - return intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, + return intel_find_dpll(state, crtc, &crtc_state->dpll_hw_state, BIT(DPLL_ID_SPLL)); } @@ -1233,8 +1233,8 @@ static int hsw_get_dpll(struct intel_atomic_state *state, if (!pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -1942,20 +1942,20 @@ static int skl_get_dpll(struct intel_atomic_state *state, struct intel_dpll *pll; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_SKL_DPLL0)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_SKL_DPLL0)); else - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_SKL_DPLL3) | - BIT(DPLL_ID_SKL_DPLL2) | - BIT(DPLL_ID_SKL_DPLL1)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_SKL_DPLL3) | + BIT(DPLL_ID_SKL_DPLL2) | + BIT(DPLL_ID_SKL_DPLL1)); if (!pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -2434,13 +2434,13 @@ static int bxt_get_dpll(struct intel_atomic_state *state, /* 1:1 mapping between ports and PLLs */ id = (enum intel_dpll_id) encoder->port; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); drm_dbg_kms(display->drm, "[CRTC:%d:%s] using pre-allocated %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -3388,14 +3388,14 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, /* Eliminate DPLLs from consideration if reserved by HTI */ dpll_mask &= ~intel_hti_dpll_mask(display); - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - dpll_mask); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + dpll_mask); if (!port_dpll->pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); icl_update_active_dpll(state, crtc, encoder); @@ -3452,26 +3452,25 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, int ret; port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - BIT(DPLL_ID_ICL_TBTPLL)); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(DPLL_ID_ICL_TBTPLL)); if (!port_dpll->pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); - + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; dpll_id = icl_tc_port_to_pll_id(intel_encoder_to_tc(encoder)); - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - BIT(dpll_id)); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(dpll_id)); if (!port_dpll->pll) { ret = -EINVAL; goto err_unreference_tbt_pll; } - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); icl_update_active_dpll(state, crtc, encoder); @@ -3479,7 +3478,7 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, err_unreference_tbt_pll: port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - intel_unreference_shared_dpll(state, crtc, port_dpll->pll); + intel_unreference_dpll(state, crtc, port_dpll->pll); return ret; } @@ -3534,7 +3533,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, if (!old_port_dpll->pll) continue; - intel_unreference_shared_dpll(state, crtc, old_port_dpll->pll); + intel_unreference_dpll(state, crtc, old_port_dpll->pll); } } @@ -4300,12 +4299,12 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { }; /** - * intel_shared_dpll_init - Initialize shared DPLLs + * intel_dpll_init - Initialize DPLLs * @display: intel_display device * - * Initialize shared DPLLs for @display. + * Initialize DPLLs for @display. */ -void intel_shared_dpll_init(struct intel_display *display) +void intel_dpll_init(struct intel_display *display) { const struct intel_dpll_mgr *dpll_mgr = NULL; const struct dpll_info *dpll_info; @@ -4362,7 +4361,7 @@ void intel_shared_dpll_init(struct intel_display *display) } /** - * intel_compute_shared_dplls - compute DPLL state CRTC and encoder combination + * intel_compute_dplls - compute DPLL state CRTC and encoder combination * @state: atomic state * @crtc: CRTC to compute DPLLs for * @encoder: encoder @@ -4370,14 +4369,14 @@ void intel_shared_dpll_init(struct intel_display *display) * This function computes the DPLL state for the given CRTC and encoder. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). * * Returns: * 0 on success, negative error code on failure. */ -int intel_compute_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4389,7 +4388,7 @@ int intel_compute_shared_dplls(struct intel_atomic_state *state, } /** - * intel_reserve_shared_dplls - reserve DPLLs for CRTC and encoder combination + * intel_reserve_dplls - reserve DPLLs for CRTC and encoder combination * @state: atomic state * @crtc: CRTC to reserve DPLLs for * @encoder: encoder @@ -4399,18 +4398,18 @@ int intel_compute_shared_dplls(struct intel_atomic_state *state, * state. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). * * The reserved DPLLs should be released by calling - * intel_release_shared_dplls(). + * intel_release_dplls(). * * Returns: * 0 if all required DPLLs were successfully reserved, * negative error code otherwise. */ -int intel_reserve_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_reserve_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4422,18 +4421,18 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state, } /** - * intel_release_shared_dplls - end use of DPLLs by CRTC in atomic state + * intel_release_dplls - end use of DPLLs by CRTC in atomic state * @state: atomic state * @crtc: crtc from which the DPLLs are to be released * - * This function releases all DPLLs reserved by intel_reserve_shared_dplls() + * This function releases all DPLLs reserved by intel_reserve_dplls() * from the current atomic commit @state and the old @crtc atomic state. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). */ -void intel_release_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_release_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4441,7 +4440,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, /* * FIXME: this function is called for every platform having a * compute_clock hook, even though the platform doesn't yet support - * the shared DPLL framework and intel_reserve_shared_dplls() is not + * the DPLL framework and intel_reserve_dplls() is not * called on those. */ if (!dpll_mgr) @@ -4457,7 +4456,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, * @encoder: encoder determining the type of port DPLL * * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, - * from the port DPLLs reserved previously by intel_reserve_shared_dplls(). The + * from the port DPLLs reserved previously by intel_reserve_dplls(). The * DPLL selected will be based on the current mode of the encoder's port. */ void intel_update_active_dpll(struct intel_atomic_state *state, @@ -4522,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, to_intel_crtc_state(crtc->base.state); if (crtc_state->hw.active && crtc_state->intel_dpll == pll) - intel_reference_shared_dpll_crtc(crtc, pll, &pll->state); + intel_reference_dpll_crtc(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; @@ -4683,8 +4682,8 @@ static bool has_alt_port_dpll(const struct intel_dpll *old_pll, (old_pll->info->is_alt_port_dpll || new_pll->info->is_alt_port_dpll); } -void intel_shared_dpll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_dpll_state_verify(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *old_crtc_state = @@ -4714,7 +4713,7 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, } } -void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) +void intel_dpll_verify_disabled(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll *pll; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index ea3fb7002e653..60391a5b52ff2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -387,26 +387,26 @@ struct intel_dpll { #define SKL_DPLL2 2 #define SKL_DPLL3 3 -/* shared dpll functions */ +/* dpll functions */ struct intel_dpll * -intel_get_shared_dpll_by_id(struct intel_display *display, - enum intel_dpll_id id); -void assert_shared_dpll(struct intel_display *display, - struct intel_dpll *pll, - bool state); -#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) -#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) -int intel_compute_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -int intel_reserve_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -void intel_release_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *shared_dpll_state); +intel_get_dpll_by_id(struct intel_display *display, + enum intel_dpll_id id); +void assert_dpll(struct intel_display *display, + struct intel_dpll *pll, + bool state); +#define assert_dpll_enabled(d, p) assert_dpll(d, p, true) +#define assert_dpll_disabled(d, p) assert_dpll(d, p, false) +int intel_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +int intel_reserve_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +void intel_release_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_unreference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, @@ -418,10 +418,10 @@ int intel_dpll_get_freq(struct intel_display *display, bool intel_dpll_get_hw_state(struct intel_display *display, struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); -void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); -void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); -void intel_shared_dpll_swap_state(struct intel_atomic_state *state); -void intel_shared_dpll_init(struct intel_display *display); +void intel_enable_dpll(const struct intel_crtc_state *crtc_state); +void intel_disable_dpll(const struct intel_crtc_state *crtc_state); +void intel_dpll_swap_state(struct intel_atomic_state *state); +void intel_dpll_init(struct intel_display *display); void intel_dpll_update_ref_clks(struct intel_display *display); void intel_dpll_readout_hw_state(struct intel_display *display); void intel_dpll_sanitize_state(struct intel_display *display); @@ -435,8 +435,8 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port); bool intel_dpll_is_combophy(enum intel_dpll_id id); -void intel_shared_dpll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state); +void intel_dpll_state_verify(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_dpll_verify_disabled(struct intel_atomic_state *state); #endif /* _INTEL_DPLL_MGR_H_ */ diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index ec8f38fba1785..f07c7ef561483 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -249,7 +249,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state, if (HAS_PCH_SPLIT(display)) { assert_fdi_rx_pll_disabled(display, pipe); - assert_shared_dpll_disabled(display, crtc_state->intel_dpll); + assert_dpll_disabled(display, crtc_state->intel_dpll); } else { assert_pll_disabled(display, pipe); } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 46e0002a13586..ed4f305e0d3ea 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -93,9 +93,9 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->base.enabled = false; if (crtc_state->intel_dpll) - intel_unreference_shared_dpll_crtc(crtc, - crtc_state->intel_dpll, - &crtc_state->intel_dpll->state); + intel_unreference_dpll_crtc(crtc, + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index 766a9983665a8..f2f6b9d9afa10 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -243,7 +243,7 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state, intel_wm_state_verify(state, crtc); verify_connector_state(state, crtc); verify_crtc_state(state, crtc); - intel_shared_dpll_state_verify(state, crtc); + intel_dpll_state_verify(state, crtc); intel_mpllb_state_verify(state, crtc); intel_cx0pll_state_verify(state, crtc); } @@ -252,5 +252,5 @@ void intel_modeset_verify_disabled(struct intel_atomic_state *state) { verify_encoder_state(state); verify_connector_state(state, NULL); - intel_shared_dpll_verify_disabled(state); + intel_dpll_verify_disabled(state); } diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index b38305c16e77c..b59b3c94f7113 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -251,7 +251,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) u32 val, pipeconf_val; /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(display, crtc_state->intel_dpll); + assert_dpll_enabled(display, crtc_state->intel_dpll); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(display, pipe); @@ -382,7 +382,7 @@ void ilk_pch_enable(struct intel_atomic_state *state, temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); if (crtc_state->intel_dpll == - intel_get_shared_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) + intel_get_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) temp |= sel; else temp &= ~sel; @@ -394,11 +394,11 @@ void ilk_pch_enable(struct intel_atomic_state *state, * transcoder, and we actually should do this to not upset any PCH * transcoder that already use the clock when we share it. * - * Note that enable_shared_dpll tries to do the right thing, but - * get_shared_dpll unconditionally resets the pll - we need that + * Note that enable_dpll tries to do the right thing, but + * get_dpll unconditionally resets the pll - we need that * to have the right LVDS enable sequence. */ - intel_enable_shared_dpll(crtc_state); + intel_enable_dpll(crtc_state); /* set transcoder timing, panel must allow it */ assert_pps_unlocked(display, pipe); @@ -472,7 +472,7 @@ void ilk_pch_post_disable(struct intel_atomic_state *state, ilk_fdi_pll_disable(crtc); - intel_disable_shared_dpll(old_crtc_state); + intel_disable_dpll(old_crtc_state); } static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) @@ -528,7 +528,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) pll_id = DPLL_ID_PCH_PLL_A; } - crtc_state->intel_dpll = intel_get_shared_dpll_by_id(display, pll_id); + crtc_state->intel_dpll = intel_get_dpll_by_id(display, pll_id); pll = crtc_state->intel_dpll; pll_active = intel_dpll_get_hw_state(display, pll, -- GitLab From 7e9a4cbbc5106a6bd7fc50ebc50bb8a8d68aca75 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:55 +0530 Subject: [PATCH 099/902] drm/i915/dpll: Rename crtc_get_shared_dpll Rename crtc_get_shared_dpll to take into the individual PLL framework which came in at DISPLAY_VER >= 14. Also having shared dpll stuff also in intel_dpll.c is just confusing. --v2 -Change naming to dpll_global to keep consistency with rest of the naming --v3 -Just use intel_dpll [Jani] --v4 -Modify commit message [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-9-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 24 ++++++++++---------- drivers/gpu/drm/i915/display/intel_dpll.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 858d9397b6708..bb57e6a980643 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4225,7 +4225,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, crtc_state->update_wm_post = true; if (intel_crtc_needs_modeset(crtc_state)) { - ret = intel_dpll_crtc_get_shared_dpll(state, crtc); + ret = intel_dpll_crtc_get_dpll(state, crtc); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 80de897a761fb..4f8be9ac9f8af 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -28,8 +28,8 @@ struct intel_dpll_global_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, struct intel_crtc *crtc); - int (*crtc_get_shared_dpll)(struct intel_atomic_state *state, - struct intel_crtc *crtc); + int (*crtc_get_dpll)(struct intel_atomic_state *state, + struct intel_crtc *crtc); }; struct intel_limit { @@ -1177,8 +1177,8 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int hsw_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = @@ -1405,8 +1405,8 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, return ret; } -static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int ilk_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1701,12 +1701,12 @@ static const struct intel_dpll_global_funcs dg2_dpll_funcs = { static const struct intel_dpll_global_funcs hsw_dpll_funcs = { .crtc_compute_clock = hsw_crtc_compute_clock, - .crtc_get_shared_dpll = hsw_crtc_get_shared_dpll, + .crtc_get_dpll = hsw_crtc_get_dpll, }; static const struct intel_dpll_global_funcs ilk_dpll_funcs = { .crtc_compute_clock = ilk_crtc_compute_clock, - .crtc_get_shared_dpll = ilk_crtc_get_shared_dpll, + .crtc_get_dpll = ilk_crtc_get_dpll, }; static const struct intel_dpll_global_funcs chv_dpll_funcs = { @@ -1759,8 +1759,8 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = @@ -1773,10 +1773,10 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, if (!crtc_state->hw.enable || crtc_state->intel_dpll) return 0; - if (!display->funcs.dpll->crtc_get_shared_dpll) + if (!display->funcs.dpll->crtc_get_dpll) return 0; - ret = display->funcs.dpll->crtc_get_shared_dpll(state, crtc); + ret = display->funcs.dpll->crtc_get_dpll(state, crtc); if (ret) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n", crtc->base.base.id, crtc->base.name); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.h b/drivers/gpu/drm/i915/display/intel_dpll.h index 280e90a57c875..3444a2dd3166e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.h +++ b/drivers/gpu/drm/i915/display/intel_dpll.h @@ -19,8 +19,8 @@ struct intel_dpll_hw_state; void intel_dpll_init_clock_hook(struct intel_display *display); int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc); -int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc); +int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc); int i9xx_calc_dpll_params(int refclk, struct dpll *clock); u32 i9xx_dpll_compute_fp(const struct dpll *dpll); void i9xx_dpll_get_hw_state(struct intel_crtc *crtc, -- GitLab From 38c5854a184cb681e0b25d675de27c1f0aa53917 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:56 +0530 Subject: [PATCH 100/902] drm/i915/dpll: Rename intel_[enable/disable]_dpll Rename intel_[enable/disable]_dpll to intel_dpll_[enable/disable] in an effort to make sure all functions that are exported start with the filename. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-10-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 4 ++-- drivers/gpu/drm/i915/display/intel_pch_display.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bb57e6a980643..27e1cce02faa8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1664,7 +1664,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); if (new_crtc_state->intel_dpll) - intel_enable_dpll(new_crtc_state); + intel_dpll_enable(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1793,7 +1793,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); - intel_disable_dpll(old_crtc_state); + intel_dpll_disable(old_crtc_state); intel_encoders_post_pll_disable(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 69271892067a8..2b592423e1d15 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -250,12 +250,12 @@ static void _intel_disable_shared_dpll(struct intel_display *display, } /** - * intel_enable_dpll - enable a CRTC's DPLL + * intel_dpll_enable - enable a CRTC's DPLL * @crtc_state: CRTC, and its state, which has a DPLL * * Enable DPLL used by @crtc. */ -void intel_enable_dpll(const struct intel_crtc_state *crtc_state) +void intel_dpll_enable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -296,12 +296,12 @@ out: } /** - * intel_disable_dpll - disable a CRTC's shared DPLL + * intel_dpll_disable - disable a CRTC's shared DPLL * @crtc_state: CRTC, and its state, which has a shared DPLL * * Disable DPLL used by @crtc. */ -void intel_disable_dpll(const struct intel_crtc_state *crtc_state) +void intel_dpll_disable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 60391a5b52ff2..88a81c850cf06 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -418,8 +418,8 @@ int intel_dpll_get_freq(struct intel_display *display, bool intel_dpll_get_hw_state(struct intel_display *display, struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); -void intel_enable_dpll(const struct intel_crtc_state *crtc_state); -void intel_disable_dpll(const struct intel_crtc_state *crtc_state); +void intel_dpll_enable(const struct intel_crtc_state *crtc_state); +void intel_dpll_disable(const struct intel_crtc_state *crtc_state); void intel_dpll_swap_state(struct intel_atomic_state *state); void intel_dpll_init(struct intel_display *display); void intel_dpll_update_ref_clks(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index b59b3c94f7113..ca85596dfc9e3 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -394,11 +394,11 @@ void ilk_pch_enable(struct intel_atomic_state *state, * transcoder, and we actually should do this to not upset any PCH * transcoder that already use the clock when we share it. * - * Note that enable_dpll tries to do the right thing, but + * Note that dpll_enable tries to do the right thing, but * get_dpll unconditionally resets the pll - we need that * to have the right LVDS enable sequence. */ - intel_enable_dpll(crtc_state); + intel_dpll_enable(crtc_state); /* set transcoder timing, panel must allow it */ assert_pps_unlocked(display, pipe); @@ -472,7 +472,7 @@ void ilk_pch_post_disable(struct intel_atomic_state *state, ilk_fdi_pll_disable(crtc); - intel_disable_dpll(old_crtc_state); + intel_dpll_disable(old_crtc_state); } static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) -- GitLab From 3b65a01ab590684e5b68c15940ef3ab2a6a72303 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:57 +0530 Subject: [PATCH 101/902] drm/i915/dpll: Rename intel_unreference_dpll_crtc Rename intel_unreference_dpll_crtc to intel_dpll_crtc_put in an effort to keep names of exported functions start with the filename. --v2 -Make the new name more sensible [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-11-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 6 +++--- drivers/gpu/drm/i915/display/intel_modeset_setup.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 2b592423e1d15..1265bc4b4307a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -451,7 +451,7 @@ intel_reference_dpll(struct intel_atomic_state *state, } /** - * intel_unreference_dpll_crtc - Drop a DPLL reference for a CRTC + * intel_dpll_crtc_put - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -459,9 +459,9 @@ intel_reference_dpll(struct intel_atomic_state *state, * Drop a reference for @pll tracking the end of use of it by @crtc. */ void -intel_unreference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_dpll_crtc_put(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -481,7 +481,7 @@ static void intel_unreference_dpll(struct intel_atomic_state *state, dpll_state = intel_atomic_get_dpll_state(&state->base); - intel_unreference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_dpll_crtc_put(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 88a81c850cf06..f8ba7b52a7adc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -404,9 +404,9 @@ int intel_reserve_dplls(struct intel_atomic_state *state, struct intel_encoder *encoder); void intel_release_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_unreference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *shared_dpll_state); +void intel_dpll_crtc_put(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index ed4f305e0d3ea..22c5302e37982 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -93,9 +93,9 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->base.enabled = false; if (crtc_state->intel_dpll) - intel_unreference_dpll_crtc(crtc, - crtc_state->intel_dpll, - &crtc_state->intel_dpll->state); + intel_dpll_crtc_put(crtc, + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, -- GitLab From c51686d8d3576bef6f842d0191214564613c4af6 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:58 +0530 Subject: [PATCH 102/902] drm/i915/dpll: Rename intel_reference_dpll_crtc Rename intel_reference_dpll_crtc to intel_dpll_crtc_get in an effort to have all the exported functions have the name start with file name. Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-12-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1265bc4b4307a..db15d4f0328c4 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -412,7 +412,7 @@ intel_find_dpll(struct intel_atomic_state *state, } /** - * intel_reference_dpll_crtc - Get a DPLL reference for a CRTC + * intel_dpll_crtc_get - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -420,9 +420,9 @@ intel_find_dpll(struct intel_atomic_state *state, * Take a reference for @pll tracking the use of it by @crtc. */ static void -intel_reference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_dpll_crtc_get(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -447,7 +447,7 @@ intel_reference_dpll(struct intel_atomic_state *state, if (dpll_state[pll->index].pipe_mask == 0) dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_dpll_crtc_get(crtc, pll, &dpll_state[pll->index]); } /** @@ -4521,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, to_intel_crtc_state(crtc->base.state); if (crtc_state->hw.active && crtc_state->intel_dpll == pll) - intel_reference_dpll_crtc(crtc, pll, &pll->state); + intel_dpll_crtc_get(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; -- GitLab From bb90401b847b3702ea2f9ba727be15e697d53528 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:59 +0530 Subject: [PATCH 103/902] drm/i915/dpll: Rename intel__dpll Rename intel__dpll to intel_dpll_ in an effort to keep names of exported functions start with the filename. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-13-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 4 +-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 26 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 10 +++---- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 27e1cce02faa8..c894e4d0d4881 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6436,7 +6436,7 @@ int intel_atomic_check(struct drm_device *dev, any_ms = true; - intel_release_dplls(state, crtc); + intel_dpll_release(state, crtc); } if (any_ms && !check_digital_port_conflicts(state)) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 4f8be9ac9f8af..83147a578c09f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1190,7 +1190,7 @@ static int hsw_crtc_get_dpll(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - return intel_reserve_dplls(state, crtc, encoder); + return intel_dpll_reserve(state, crtc, encoder); } static int dg2_crtc_compute_clock(struct intel_atomic_state *state, @@ -1415,7 +1415,7 @@ static int ilk_crtc_get_dpll(struct intel_atomic_state *state, if (!crtc_state->has_pch_encoder) return 0; - return intel_reserve_dplls(state, crtc, NULL); + return intel_dpll_reserve(state, crtc, NULL); } static u32 vlv_dpll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index db15d4f0328c4..6f56a80592424 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -56,8 +56,8 @@ * users of a PLL are tracked and that tracking is integrated with the atomic * modset interface. During an atomic operation, required PLLs can be reserved * for a given CRTC and encoder configuration by calling - * intel_reserve_dplls() and previously reserved PLLs can be released - * with intel_release_dplls(). + * intel_dpll_reserve() and previously reserved PLLs can be released + * with intel_dpll_release(). * Changes to the users are first staged in the atomic state, and then made * effective by calling intel_dpll_swap_state() during the atomic * commit phase. @@ -4388,7 +4388,7 @@ int intel_compute_dplls(struct intel_atomic_state *state, } /** - * intel_reserve_dplls - reserve DPLLs for CRTC and encoder combination + * intel_dpll_reserve - reserve DPLLs for CRTC and encoder combination * @state: atomic state * @crtc: CRTC to reserve DPLLs for * @encoder: encoder @@ -4401,15 +4401,15 @@ int intel_compute_dplls(struct intel_atomic_state *state, * calling intel_dpll_swap_state(). * * The reserved DPLLs should be released by calling - * intel_release_dplls(). + * intel_dpll_release(). * * Returns: * 0 if all required DPLLs were successfully reserved, * negative error code otherwise. */ -int intel_reserve_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_dpll_reserve(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4421,18 +4421,18 @@ int intel_reserve_dplls(struct intel_atomic_state *state, } /** - * intel_release_dplls - end use of DPLLs by CRTC in atomic state + * intel_dpll_release - end use of DPLLs by CRTC in atomic state * @state: atomic state * @crtc: crtc from which the DPLLs are to be released * - * This function releases all DPLLs reserved by intel_reserve_dplls() + * This function releases all DPLLs reserved by intel_dpll_reserve() * from the current atomic commit @state and the old @crtc atomic state. * * The new configuration in the atomic commit @state is made effective by * calling intel_dpll_swap_state(). */ -void intel_release_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_dpll_release(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4440,7 +4440,7 @@ void intel_release_dplls(struct intel_atomic_state *state, /* * FIXME: this function is called for every platform having a * compute_clock hook, even though the platform doesn't yet support - * the DPLL framework and intel_reserve_dplls() is not + * the DPLL framework and intel_dpll_reserve() is not * called on those. */ if (!dpll_mgr) @@ -4456,7 +4456,7 @@ void intel_release_dplls(struct intel_atomic_state *state, * @encoder: encoder determining the type of port DPLL * * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, - * from the port DPLLs reserved previously by intel_reserve_dplls(). The + * from the port DPLLs reserved previously by intel_dpll_reserve(). The * DPLL selected will be based on the current mode of the encoder's port. */ void intel_update_active_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index f8ba7b52a7adc..9c8a91b9639c0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -399,11 +399,11 @@ void assert_dpll(struct intel_display *display, int intel_compute_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); -int intel_reserve_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -void intel_release_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc); +int intel_dpll_reserve(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +void intel_dpll_release(struct intel_atomic_state *state, + struct intel_crtc *crtc); void intel_dpll_crtc_put(const struct intel_crtc *crtc, const struct intel_dpll *pll, struct intel_dpll_state *shared_dpll_state); -- GitLab From 71325aa5a0f18969f642fcc2a1cbb77624d357aa Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:48:00 +0530 Subject: [PATCH 104/902] drm/i915/dpll: Rename intel_compute_dpll Rename intel_compute_dpll to intel_dpll_compute in an effort to make sure all function names that are exported have the filename at start. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-14-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 83147a578c09f..db98e2758271e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1162,7 +1162,7 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - ret = intel_compute_dplls(state, crtc, encoder); + ret = intel_dpll_compute(state, crtc, encoder); if (ret) return ret; @@ -1224,7 +1224,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, if (ret) return ret; - /* TODO: Do the readback via intel_compute_dplls() */ + /* TODO: Do the readback via intel_dpll_compute() */ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); @@ -1395,7 +1395,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, ilk_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); - ret = intel_compute_dplls(state, crtc, NULL); + ret = intel_dpll_compute(state, crtc, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6f56a80592424..bf66cbe5a11cc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4361,7 +4361,7 @@ void intel_dpll_init(struct intel_display *display) } /** - * intel_compute_dplls - compute DPLL state CRTC and encoder combination + * intel_dpll_compute - compute DPLL state CRTC and encoder combination * @state: atomic state * @crtc: CRTC to compute DPLLs for * @encoder: encoder @@ -4374,9 +4374,9 @@ void intel_dpll_init(struct intel_display *display) * Returns: * 0 on success, negative error code on failure. */ -int intel_compute_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_dpll_compute(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 9c8a91b9639c0..b388310af9c3e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -396,9 +396,9 @@ void assert_dpll(struct intel_display *display, bool state); #define assert_dpll_enabled(d, p) assert_dpll(d, p, true) #define assert_dpll_disabled(d, p) assert_dpll(d, p, false) -int intel_compute_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); +int intel_dpll_compute(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); int intel_dpll_reserve(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); -- GitLab From 99354ec6409f716488887fc8094a1e63b7d35af3 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:48:01 +0530 Subject: [PATCH 105/902] drm/i915/dpll: Rename intel_update_active_dpll Rename intel_update_active_dpll to intel_dpll_update_active in an effort to have function names which are exported to start with filenames they are exported from. Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-15-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 11ebcb40c91f6..0e6d618b53565 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3650,7 +3650,7 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, intel_crtc_joined_pipe_mask(crtc_state)) - intel_update_active_dpll(state, pipe_crtc, encoder); + intel_dpll_update_active(state, pipe_crtc, encoder); } /* diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bf66cbe5a11cc..28b3f5ea4219a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4450,7 +4450,7 @@ void intel_dpll_release(struct intel_atomic_state *state, } /** - * intel_update_active_dpll - update the active DPLL for a CRTC/encoder + * intel_dpll_update_active - update the active DPLL for a CRTC/encoder * @state: atomic state * @crtc: the CRTC for which to update the active DPLL * @encoder: encoder determining the type of port DPLL @@ -4459,7 +4459,7 @@ void intel_dpll_release(struct intel_atomic_state *state, * from the port DPLLs reserved previously by intel_dpll_reserve(). The * DPLL selected will be based on the current mode of the encoder's port. */ -void intel_update_active_dpll(struct intel_atomic_state *state, +void intel_dpll_update_active(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index b388310af9c3e..f131bdd1c975d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -409,7 +409,7 @@ void intel_dpll_crtc_put(const struct intel_crtc *crtc, struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); -void intel_update_active_dpll(struct intel_atomic_state *state, +void intel_dpll_update_active(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); int intel_dpll_get_freq(struct intel_display *display, -- GitLab From c3a48363cf1f76147088b1adb518136ac5df86a0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 19 May 2025 16:34:17 +0300 Subject: [PATCH 106/902] drm/i915/dp_mst: Work around Thunderbolt sink disconnect after SINK_COUNT_ESI read Due to a problem in the iTBT DP-in adapter's firmware the sink on a TBT link may get disconnected inadvertently if the SINK_COUNT_ESI and the DP_LINK_SERVICE_IRQ_VECTOR_ESI0 registers are read in a single AUX transaction. Work around the issue by reading these registers in separate transactions. The issue affects MTL+ platforms and will be fixed in the DP-in adapter firmware, however releasing that firmware fix may take some time and is not guaranteed to be available for all systems. Based on this apply the workaround on affected platforms. See HSD #13013007775. v2: Cc'ing Mika Westerberg. Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13760 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14147 Cc: Mika Westerberg Cc: stable@vger.kernel.org Reviewed-by: Mika Westerberg Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250519133417.1469181-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 21297bc4cc00d..208a953b04a2f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4538,6 +4538,23 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp) static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) { + struct intel_display *display = to_intel_display(intel_dp); + + /* + * Display WA for HSD #13013007775: mtl/arl/lnl + * Read the sink count and link service IRQ registers in separate + * transactions to prevent disconnecting the sink on a TBT link + * inadvertently. + */ + if (IS_DISPLAY_VER(display, 14, 20) && !display->platform.battlemage) { + if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3) != 3) + return false; + + /* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */ + return drm_dp_dpcd_readb(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &esi[3]) == 1; + } + return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4; } -- GitLab From dcab7a228f4ea9cda3f5b0a1f0679e046d23d7f7 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 16 May 2025 15:16:54 +0300 Subject: [PATCH 107/902] drm/i915/display: Add check for alloc_ordered_workqueue() and alloc_workqueue() Add check for the return value of alloc_ordered_workqueue() and alloc_workqueue(). Furthermore, if some allocations fail, cleanup works are added to avoid potential memory leak problem. Fixes: 40053823baad ("drm/i915/display: move modeset probe/remove functions to intel_display_driver.c") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/20d3d096c6a4907636f8a1389b3b4dd753ca356e.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_display_driver.c | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 16d91be02bb91..581787d0452e6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -244,31 +244,45 @@ int intel_display_driver_probe_noirq(struct intel_display *display) intel_dmc_init(display); display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0); + if (!display->wq.modeset) { + ret = -ENOMEM; + goto cleanup_vga_client_pw_domain_dmc; + } + display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI | WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); + if (!display->wq.flip) { + ret = -ENOMEM; + goto cleanup_wq_modeset; + } + display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0); + if (!display->wq.cleanup) { + ret = -ENOMEM; + goto cleanup_wq_flip; + } intel_mode_config_init(display); ret = intel_cdclk_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_color_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_dbuf_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_bw_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_pmdemand_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; intel_init_quirks(display); @@ -276,6 +290,12 @@ int intel_display_driver_probe_noirq(struct intel_display *display) return 0; +cleanup_wq_cleanup: + destroy_workqueue(display->wq.cleanup); +cleanup_wq_flip: + destroy_workqueue(display->wq.flip); +cleanup_wq_modeset: + destroy_workqueue(display->wq.modeset); cleanup_vga_client_pw_domain_dmc: intel_dmc_fini(display); intel_power_domains_driver_remove(display); -- GitLab From 5b62d63395d5b7d4094e7cd380bccae4b25415cb Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 16 May 2025 15:16:55 +0300 Subject: [PATCH 108/902] drm/xe/display: Add check for alloc_ordered_workqueue() Add check for the return value of alloc_ordered_workqueue() in xe_display_create() to catch potential exception. Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/4ee1b0e5d1626ce1dde2e82af05c2edaed50c3aa.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 699f401eff101..df897d08255c7 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -112,6 +112,8 @@ int xe_display_create(struct xe_device *xe) spin_lock_init(&display->fb_tracking.lock); display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); + if (!display->hotplug.dp_wq) + return -ENOMEM; return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } -- GitLab From b617341e4801e2f0ea7aeb63fae0fa438f7cd601 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:56 +0300 Subject: [PATCH 109/902] drm/xe/display: drop duplicate display->fb_tracking.lock init The spinlock is initialized in intel_display_driver_early_probe(). Drop the extra init. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/f895a8a43c61a6e60db8e1eb698919ce0faab27c.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index df897d08255c7..9513b03847a82 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -109,8 +109,6 @@ int xe_display_create(struct xe_device *xe) xe->display = &xe->__display; - spin_lock_init(&display->fb_tracking.lock); - display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); if (!display->hotplug.dp_wq) return -ENOMEM; -- GitLab From ed23224b3f5e5e938e5c97d246678702df98eb93 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:57 +0300 Subject: [PATCH 110/902] drm/i915/display: move hotplug.dp_wq init from xe and i915 to display The workqueue init and destroy belongs in display. Move it. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/4730167548a40dc2abe38cd084809b74de988f1a.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_driver.c | 11 ++++++++++- drivers/gpu/drm/i915/i915_driver.c | 13 +------------ drivers/gpu/drm/xe/display/xe_display.c | 16 +--------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 581787d0452e6..2bdafab9b6d00 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -243,10 +243,16 @@ int intel_display_driver_probe_noirq(struct intel_display *display) intel_dmc_init(display); + display->hotplug.dp_wq = alloc_ordered_workqueue("intel-dp", 0); + if (!display->hotplug.dp_wq) { + ret = -ENOMEM; + goto cleanup_vga_client_pw_domain_dmc; + } + display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0); if (!display->wq.modeset) { ret = -ENOMEM; - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_dp; } display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI | @@ -296,6 +302,8 @@ cleanup_wq_flip: destroy_workqueue(display->wq.flip); cleanup_wq_modeset: destroy_workqueue(display->wq.modeset); +cleanup_wq_dp: + destroy_workqueue(display->hotplug.dp_wq); cleanup_vga_client_pw_domain_dmc: intel_dmc_fini(display); intel_power_domains_driver_remove(display); @@ -631,6 +639,7 @@ void intel_display_driver_remove_noirq(struct intel_display *display) intel_gmbus_teardown(display); + destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(display->wq.flip); destroy_workqueue(display->wq.modeset); destroy_workqueue(display->wq.cleanup); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 5c69d14a7673e..950b7ad8d675f 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,8 +115,6 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { - struct intel_display *display = dev_priv->display; - /* * The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -135,10 +133,6 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) if (dev_priv->wq == NULL) goto out_err; - display->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (!display->hotplug.dp_wq) - goto out_free_wq; - /* * The unordered i915 workqueue should be used for all work * scheduling that do not require running in order, which used @@ -147,12 +141,10 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) */ dev_priv->unordered_wq = alloc_workqueue("i915-unordered", 0, 0); if (dev_priv->unordered_wq == NULL) - goto out_free_dp_wq; + goto out_free_wq; return 0; -out_free_dp_wq: - destroy_workqueue(display->hotplug.dp_wq); out_free_wq: destroy_workqueue(dev_priv->wq); out_err: @@ -163,10 +155,7 @@ out_err: static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { - struct intel_display *display = dev_priv->display; - destroy_workqueue(dev_priv->unordered_wq); - destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(dev_priv->wq); } diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 9513b03847a82..b0f5624177bdb 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -83,14 +83,6 @@ static void unset_display_features(struct xe_device *xe) xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); } -static void display_destroy(struct drm_device *dev, void *dummy) -{ - struct xe_device *xe = to_xe_device(dev); - struct intel_display *display = xe->display; - - destroy_workqueue(display->hotplug.dp_wq); -} - /** * xe_display_create - create display struct * @xe: XE device instance @@ -105,15 +97,9 @@ static void display_destroy(struct drm_device *dev, void *dummy) int xe_display_create(struct xe_device *xe) { /* TODO: Allocate display dynamically. */ - struct intel_display *display = &xe->__display; - xe->display = &xe->__display; - display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); - if (!display->hotplug.dp_wq) - return -ENOMEM; - - return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); + return 0; } static void xe_display_fini_early(void *arg) -- GitLab From 1e2803e565af3b7463c7615347510f7093945633 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:58 +0300 Subject: [PATCH 111/902] drm/xe/display: move xe->display initialization to xe_display_probe() The future goal is to have intel_display_device_probe() create struct intel_display. As the first step, postpone xe->display initialization right before that call. This is the same location as in i915. There's a subtle functional change here: xe->display will now be initialized only if xe->info.probe_display. The xe_display_create() function becomes empty, and can be removed. Move its documentation to xe_display_probe() Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/6c3075739d84cecea258d686c3ef38455a61191c.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 33 +++++++++++-------------- drivers/gpu/drm/xe/display/xe_display.h | 4 --- drivers/gpu/drm/xe/xe_device.c | 4 --- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b0f5624177bdb..c35444637620f 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -83,25 +83,6 @@ static void unset_display_features(struct xe_device *xe) xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); } -/** - * xe_display_create - create display struct - * @xe: XE device instance - * - * Initialize all fields used by the display part. - * - * TODO: once everything can be inside a single struct, make the struct opaque - * to the rest of xe and return it to be xe->display. - * - * Returns: 0 on success - */ -int xe_display_create(struct xe_device *xe) -{ - /* TODO: Allocate display dynamically. */ - xe->display = &xe->__display; - - return 0; -} - static void xe_display_fini_early(void *arg) { struct xe_device *xe = arg; @@ -524,6 +505,17 @@ static void display_device_remove(struct drm_device *dev, void *arg) intel_display_device_remove(display); } +/** + * xe_display_probe - probe display and create display struct + * @xe: XE device instance + * + * Initialize all fields used by the display part. + * + * TODO: once everything can be inside a single struct, make the struct opaque + * to the rest of xe and return it to be xe->display. + * + * Returns: 0 on success + */ int xe_display_probe(struct xe_device *xe) { struct pci_dev *pdev = to_pci_dev(xe->drm.dev); @@ -533,6 +525,9 @@ int xe_display_probe(struct xe_device *xe) if (!xe->info.probe_display) goto no_display; + /* TODO: Allocate display dynamically. */ + xe->display = &xe->__display; + display = intel_display_device_probe(pdev); err = drmm_add_action_or_reset(&xe->drm, display_device_remove, display); diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 46e14f8dee28a..e533aa4750bc1 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -15,8 +15,6 @@ struct drm_driver; bool xe_display_driver_probe_defer(struct pci_dev *pdev); void xe_display_driver_set_hooks(struct drm_driver *driver); -int xe_display_create(struct xe_device *xe); - int xe_display_probe(struct xe_device *xe); int xe_display_init_early(struct xe_device *xe); @@ -46,8 +44,6 @@ static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0 static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { } static inline void xe_display_driver_remove(struct xe_device *xe) {} -static inline int xe_display_create(struct xe_device *xe) { return 0; } - static inline int xe_display_probe(struct xe_device *xe) { return 0; } static inline int xe_display_init_early(struct xe_device *xe) { return 0; } diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index c02c4c4e94128..b615d8ed38a21 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -493,10 +493,6 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, if (err) goto err; - err = xe_display_create(xe); - if (WARN_ON(err)) - goto err; - return xe; err: -- GitLab From 7e49ab36e6f3fb6edc250609ece1548bf80c50cc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:59 +0300 Subject: [PATCH 112/902] drm/xe/display: add notes about how early a few functions can be called xe_display_driver_probe_defer() and xe_display_driver_set_hooks() get called before either struct xe_device or struct intel_display exist. Make a note of that. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/937ea1e16e970a6f6944b94c6a9c216d36e728d1.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index c35444637620f..8b2aa7dc6e076 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -48,6 +48,8 @@ static bool has_display(struct xe_device *xe) * early on * @pdev: PCI device * + * Note: This is called before xe or display device creation. + * * Returns: true if probe needs to be deferred, false otherwise */ bool xe_display_driver_probe_defer(struct pci_dev *pdev) @@ -65,6 +67,8 @@ bool xe_display_driver_probe_defer(struct pci_dev *pdev) * Set features and function hooks in @driver that are needed for driving the * display IP. This sets the driver's capability of driving display, regardless * if the device has it enabled + * + * Note: This is called before xe or display device creation. */ void xe_display_driver_set_hooks(struct drm_driver *driver) { -- GitLab From 5a9f299f956ef9764f56044cfca7aafa23cea1d1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:17:00 +0300 Subject: [PATCH 113/902] drm/xe/display: use xe->display to decide whether to do anything Since we only initialize xe->display when xe->info.probe_display, we can use !xe->display to bail out early. This seems cleaner and more accurate than relying on xe->info.probe_display, since xe->display may indeed be NULL. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/945d2a987214044a81f4816684972961b772b45a.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 8b2aa7dc6e076..1e59b6dd2c3bd 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -92,7 +92,7 @@ static void xe_display_fini_early(void *arg) struct xe_device *xe = arg; struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_driver_remove_nogem(display); @@ -106,7 +106,7 @@ int xe_display_init_early(struct xe_device *xe) struct intel_display *display = xe->display; int err; - if (!xe->info.probe_display) + if (!display) return 0; /* Fake uncore lock */ @@ -160,7 +160,7 @@ int xe_display_init(struct xe_device *xe) struct intel_display *display = xe->display; int err; - if (!xe->info.probe_display) + if (!display) return 0; err = intel_display_driver_probe(display); @@ -174,7 +174,7 @@ void xe_display_register(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_driver_register(display); @@ -185,7 +185,7 @@ void xe_display_unregister(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_power_domains_disable(display); @@ -198,7 +198,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (master_ctl & DISPLAY_IRQ) @@ -209,7 +209,7 @@ void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (gu_misc_iir & GU_MISC_GSE) @@ -220,7 +220,7 @@ void xe_display_irq_reset(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; gen11_display_irq_reset(display); @@ -230,7 +230,7 @@ void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (gt->info.id == XE_GT0) @@ -271,7 +271,7 @@ static void xe_display_enable_d3cold(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; /* @@ -294,7 +294,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_dmc_resume(display); @@ -319,7 +319,7 @@ void xe_display_pm_suspend(struct xe_device *xe) struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); - if (!xe->info.probe_display) + if (!display) return; /* @@ -353,7 +353,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_power_domains_disable(display); @@ -384,7 +384,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) { @@ -400,7 +400,7 @@ void xe_display_pm_suspend_late(struct xe_device *xe) struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); - if (!xe->info.probe_display) + if (!display) return; intel_display_power_suspend_late(display, s2idle); @@ -410,7 +410,7 @@ void xe_display_pm_runtime_suspend_late(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) @@ -428,7 +428,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; /* @@ -443,7 +443,7 @@ void xe_display_pm_resume_early(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_power_resume_early(display); @@ -453,7 +453,7 @@ void xe_display_pm_resume(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_dmc_resume(display); @@ -488,7 +488,7 @@ void xe_display_pm_runtime_resume(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) { -- GitLab From 56764c845aa5be14cd53702fc9f2da23e25857de Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 20 May 2025 17:22:19 +0300 Subject: [PATCH 114/902] drm/i915/dp: Fix the enabling/disabling of audio SDP splitting Adjust the enabling/disabling steps of the DP audio SDP splitting according to a recent Bspec update. This moves the enabling to the audio codec enable sequence after the transcoder is enabled and disables SDP splitting explicitly during the audio disable sequence. Bspec requires waiting for a vblank event after the transcoder is enabled and before SDP splitting is enabled. There is no need for an explicit wait for this, since after the transcoder is enabled this vblank event is guaranteed to have happened via a flip done wait (see intel_atomic_commit_tail() -> drm_atomic_helper_wait_for_flip_done()). The bspec update is for LNL+ only, but the HW team clarified that this has been always the intended sequence on all platforms and bspec will be updated everywhere accordingly. The way SDP splitting was originally enabled matched the version of bspec at that time. Adding here the Fixes: line still, since this change fixes a FIFO underrun on PTL during output enabling when DSC is enabled. Bspec: 49283, 68943 Fixes: 8853750dbad8 ("drm/i915: Enable SDP split for DP2.0") Cc: Vinod Govindapillai Acked-by: Jani Nikula Reviewed-by: Vinod Govindapillai Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250520142219.1688401-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 27 +++++++++++++-------- drivers/gpu/drm/i915/display/intel_audio.h | 1 - drivers/gpu/drm/i915/display/intel_ddi.c | 3 --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 -- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 40d8bbd8107d6..55af3a553c58a 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -397,6 +397,19 @@ hsw_audio_config_update(struct intel_encoder *encoder, hsw_hdmi_audio_config_update(encoder, crtc_state); } +static void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state, + bool enable) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder trans = crtc_state->cpu_transcoder; + + if (!HAS_DP20(display)) + return; + + intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, + enable && crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); +} + static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -430,6 +443,8 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, if (needs_wa_14020863754(display)) intel_de_rmw(display, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); + intel_audio_sdp_split_update(old_crtc_state, false); + mutex_unlock(&display->audio.mutex); } @@ -555,6 +570,8 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) enable_audio_dsc_wa(encoder, crtc_state); + intel_audio_sdp_split_update(crtc_state, true); + if (needs_wa_14020863754(display)) intel_de_rmw(display, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); @@ -681,16 +698,6 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&display->audio.mutex); } -void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - enum transcoder trans = crtc_state->cpu_transcoder; - - if (HAS_DP20(display)) - intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, - crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); -} - bool intel_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index ad49eefa7182c..42cf886f3d24f 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -31,6 +31,5 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state); void intel_audio_init(struct intel_display *display); void intel_audio_register(struct intel_display *display); void intel_audio_deinit(struct intel_display *display); -void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0e6d618b53565..3d47d0ed3c37b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3507,9 +3507,6 @@ static void intel_ddi_enable(struct intel_atomic_state *state, intel_vrr_transcoder_enable(crtc_state); - /* Enable/Disable DP2.0 SDP split config before transcoder */ - intel_audio_sdp_split_update(crtc_state); - /* 128b/132b SST */ if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 57602606acd5a..cc00a73898f14 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1336,8 +1336,6 @@ static void mst_stream_enable(struct intel_atomic_state *state, FECSTALL_DIS_DPTSTREAM_DPTTG, pipe_config->fec_enable ? FECSTALL_DIS_DPTSTREAM_DPTTG : 0); - intel_audio_sdp_split_update(pipe_config); - intel_enable_transcoder(pipe_config); for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) { -- GitLab From 49c6dc74b5968885f421f9f1b45eb4890b955870 Mon Sep 17 00:00:00 2001 From: Matt Atwood Date: Tue, 20 May 2025 12:57:49 -0700 Subject: [PATCH 115/902] drm/xe/ptl: Update the PTL pci id table Update to current bspec table. Bspec: 72574 Signed-off-by: Matt Atwood Reviewed-by: Tejas Upadhyay Reviewed-by: Clint Taylor Link: https://lore.kernel.org/r/20250520195749.371748-1-matthew.s.atwood@intel.com Signed-off-by: Matt Roper --- include/drm/intel/pciids.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/drm/intel/pciids.h b/include/drm/intel/pciids.h index d212848d07f3f..a7ce9523c50d3 100644 --- a/include/drm/intel/pciids.h +++ b/include/drm/intel/pciids.h @@ -861,6 +861,10 @@ MACRO__(0xB081, ## __VA_ARGS__), \ MACRO__(0xB082, ## __VA_ARGS__), \ MACRO__(0xB083, ## __VA_ARGS__), \ + MACRO__(0xB084, ## __VA_ARGS__), \ + MACRO__(0xB085, ## __VA_ARGS__), \ + MACRO__(0xB086, ## __VA_ARGS__), \ + MACRO__(0xB087, ## __VA_ARGS__), \ MACRO__(0xB08F, ## __VA_ARGS__), \ MACRO__(0xB090, ## __VA_ARGS__), \ MACRO__(0xB0A0, ## __VA_ARGS__), \ -- GitLab From 20a07782dacf7348a259efcc4a2ab56ecbe7aeb1 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Tue, 20 May 2025 01:00:35 +0200 Subject: [PATCH 116/902] drm/xe/vf: Fail migration recovery if fixups needed but platform not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The post-migration recovery needs to be fully implemented for a specific platform in order to make continuation of workloads possible. New platforms introduce changes which affect the recovery procedure, and without a clear verification of support this leads to errors with no straight forward error message explaining the cause. This patch fixes that issue - it introduces a message to be logged when the current driver is known to not support the current platform. Wedging the driver immediately also decreases the amount of additional errors which would come afterwards if the driver continued operation. v2: Show the message during probe as well as during recovery; do not perform any recovery steps if the recovery is bound to fail v3: Use SRIOV-specific logging, fix typos v4: XE_DEBUG_SRIOV to XE_DEBUG check switch, to make testing more straightforward Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Cc: Michał Winiarski Reviewed-by: Michal Wajdeczko Acked-by: Michał Winiarski Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250519230035.3143966-1-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_sriov_vf.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index 2674fa948fda3..46466932375c2 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -123,6 +123,15 @@ * | | | */ +static bool vf_migration_supported(struct xe_device *xe) +{ + /* + * TODO: Add conditions to allow specific platforms, when they're + * supported at production quality. + */ + return IS_ENABLED(CONFIG_DRM_XE_DEBUG); +} + static void migration_worker_func(struct work_struct *w); /** @@ -132,6 +141,9 @@ static void migration_worker_func(struct work_struct *w); void xe_sriov_vf_init_early(struct xe_device *xe) { INIT_WORK(&xe->sriov.vf.migration.worker, migration_worker_func); + + if (!vf_migration_supported(xe)) + xe_sriov_info(xe, "migration not supported by this module version\n"); } /** @@ -236,6 +248,11 @@ static void vf_post_migration_recovery(struct xe_device *xe) goto defer; if (unlikely(err)) goto fail; + if (!vf_migration_supported(xe)) { + xe_sriov_err(xe, "migration not supported by this module version\n"); + err = -ENOTRECOVERABLE; + goto fail; + } need_fixups = vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ -- GitLab From 42e5fc672fee07da071a37e06a2454aba85d8efe Mon Sep 17 00:00:00 2001 From: Yumeng Fang Date: Fri, 23 May 2025 14:14:22 +0800 Subject: [PATCH 117/902] drm/i915/display: Use str_true_false() helper Remove hard-coded strings by using the str_true_false() helper. Signed-off-by: Yumeng Fang Signed-off-by: Yunjian Long Link: https://lore.kernel.org/r/20250523141422844GEA-yzba-OvN0lZirDsS-@zte.com.cn Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3c323f694e694..b671b4ea1a24d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -972,7 +973,7 @@ static ssize_t i915_dsc_fec_support_write(struct file *file, return ret; drm_dbg(display->drm, "Got %s for DSC Enable\n", - (dsc_enable) ? "true" : "false"); + str_true_false(dsc_enable)); intel_dp->force_dsc_en = dsc_enable; *offp += len; @@ -1183,7 +1184,7 @@ static ssize_t i915_dsc_fractional_bpp_write(struct file *file, return ret; drm_dbg(display->drm, "Got %s for DSC Fractional BPP Enable\n", - (dsc_fractional_bpp_enable) ? "true" : "false"); + str_true_false(dsc_fractional_bpp_enable)); intel_dp->force_dsc_fractional_bpp_en = dsc_fractional_bpp_enable; *offp += len; -- GitLab From 55f233aaadabfad883aa442c202d91617008dff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 23 May 2025 11:50:31 +0530 Subject: [PATCH 118/902] drm/i915/dsb: Extract intel_dsb_ins_align() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the code that alings the next instruction to the next QW boundary into a small helper. I'll have some more uses for this later. Also explain why we don't have to zero out the extra DW. Signed-off-by: Ville Syrjälä Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Animesh Manna Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-2-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 393ea07947b41..d6641cfe80617 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -228,13 +228,25 @@ static bool is_dsb_busy(struct intel_display *display, enum pipe pipe, return intel_de_read_fw(display, DSB_CTRL(pipe, dsb_id)) & DSB_STATUS_BUSY; } +static void intel_dsb_ins_align(struct intel_dsb *dsb) +{ + /* + * Every instruction should be 8 byte aligned. + * + * The only way to get unaligned free_pos is via + * intel_dsb_reg_write_indexed() which already + * makes sure the next dword is zeroed, so no need + * to clear it here. + */ + dsb->free_pos = ALIGN(dsb->free_pos, 2); +} + static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) { if (!assert_dsb_has_room(dsb)) return; - /* Every instruction should be 8 byte aligned. */ - dsb->free_pos = ALIGN(dsb->free_pos, 2); + intel_dsb_ins_align(dsb); dsb->ins_start_offset = dsb->free_pos; dsb->ins[0] = ldw; -- GitLab From d535ae997ddd6b5c0c591c7d4440d3e389618da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 23 May 2025 11:50:32 +0530 Subject: [PATCH 119/902] drm/i915/dsb: Extract assert_dsb_tail_is_aligned() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the DSB tail alignment checks into helper. We already have two uses of this, and soon we'll get a third. v2: s/soo/soon in commit message (Animesh) Signed-off-by: Ville Syrjälä Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Animesh Manna Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-3-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index d6641cfe80617..f2574e6812d18 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -204,6 +204,15 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb) crtc->base.base.id, crtc->base.name, dsb->id); } +static bool assert_dsb_tail_is_aligned(struct intel_dsb *dsb) +{ + struct intel_crtc *crtc = dsb->crtc; + struct intel_display *display = to_intel_display(crtc->base.dev); + + return !drm_WARN_ON(display->drm, + !IS_ALIGNED(dsb->free_pos * 4, CACHELINE_BYTES)); +} + static void intel_dsb_dump(struct intel_dsb *dsb) { struct intel_crtc *crtc = dsb->crtc; @@ -621,10 +630,11 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, if (drm_WARN_ON(display->drm, dsb->id == chained_dsb->id)) return; - tail = chained_dsb->free_pos * 4; - if (drm_WARN_ON(display->drm, !IS_ALIGNED(tail, CACHELINE_BYTES))) + if (!assert_dsb_tail_is_aligned(chained_dsb)) return; + tail = chained_dsb->free_pos * 4; + intel_dsb_reg_write(dsb, DSB_CTRL(pipe, chained_dsb->id), ctrl | DSB_ENABLE); @@ -695,10 +705,11 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, enum pipe pipe = crtc->pipe; u32 tail; - tail = dsb->free_pos * 4; - if (drm_WARN_ON(display->drm, !IS_ALIGNED(tail, CACHELINE_BYTES))) + if (!assert_dsb_tail_is_aligned(dsb)) return; + tail = dsb->free_pos * 4; + if (is_dsb_busy(display, pipe, dsb->id)) { drm_err(display->drm, "[CRTC:%d:%s] DSB %d is busy\n", crtc->base.base.id, crtc->base.name, dsb->id); -- GitLab From bb3de17e2b5eb3cdc26e71b257e6c7989fce71ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 23 May 2025 11:50:33 +0530 Subject: [PATCH 120/902] drm/i915/dsb: Extract intel_dsb_{head,tail}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the code that calculates the DSB_HEAD/TAIL register values into small helpers. We already have two copies of this, and soon there will be a third. Signed-off-by: Ville Syrjälä Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Animesh Manna Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-4-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index f2574e6812d18..9b2de4e7e681e 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -237,6 +237,16 @@ static bool is_dsb_busy(struct intel_display *display, enum pipe pipe, return intel_de_read_fw(display, DSB_CTRL(pipe, dsb_id)) & DSB_STATUS_BUSY; } +static unsigned int intel_dsb_head(struct intel_dsb *dsb) +{ + return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf); +} + +static unsigned int intel_dsb_tail(struct intel_dsb *dsb) +{ + return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + dsb->free_pos * 4; +} + static void intel_dsb_ins_align(struct intel_dsb *dsb) { /* @@ -625,7 +635,6 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state->base.dev); struct intel_crtc *crtc = dsb->crtc; enum pipe pipe = crtc->pipe; - u32 tail; if (drm_WARN_ON(display->drm, dsb->id == chained_dsb->id)) return; @@ -633,8 +642,6 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, if (!assert_dsb_tail_is_aligned(chained_dsb)) return; - tail = chained_dsb->free_pos * 4; - intel_dsb_reg_write(dsb, DSB_CTRL(pipe, chained_dsb->id), ctrl | DSB_ENABLE); @@ -655,10 +662,10 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, } intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id), - intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf)); + intel_dsb_head(chained_dsb)); intel_dsb_reg_write(dsb, DSB_TAIL(pipe, chained_dsb->id), - intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf) + tail); + intel_dsb_tail(chained_dsb)); if (ctrl & DSB_WAIT_FOR_VBLANK) { /* @@ -703,13 +710,10 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, struct intel_crtc *crtc = dsb->crtc; struct intel_display *display = to_intel_display(crtc->base.dev); enum pipe pipe = crtc->pipe; - u32 tail; if (!assert_dsb_tail_is_aligned(dsb)) return; - tail = dsb->free_pos * 4; - if (is_dsb_busy(display, pipe, dsb->id)) { drm_err(display->drm, "[CRTC:%d:%s] DSB %d is busy\n", crtc->base.base.id, crtc->base.name, dsb->id); @@ -727,7 +731,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, dsb_error_int_en(display) | DSB_PROG_INT_EN); intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id), - intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf)); + intel_dsb_head(dsb)); if (hw_dewake_scanline >= 0) { int diff, position; @@ -749,7 +753,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, } intel_de_write_fw(display, DSB_TAIL(pipe, dsb->id), - intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + tail); + intel_dsb_tail(dsb)); } /** -- GitLab From 2c41d62f6fb16d591df17b29edaa81ea56569bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 23 May 2025 11:50:34 +0530 Subject: [PATCH 121/902] drm/i915/dsb: Implement intel_dsb_gosub() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the new GOSUB DSB instruction (available on ptl+), which instructs the DSB to jump to a different buffer, execute the commands there, and then return execution to the next instruction in the original buffer. There are a few alignment related workarounds that need to be dealt with when emitting GOSUB instruction. v2: Right shift head and tail pointer passed to gosub command (chaitanya) v3: Add macro for right shifting head/tail pointers (Animesh) v4: Fix typo in commit message (Uma) Add comments explaining why right shifting htp is needed (Animesh) Signed-off-by: Ville Syrjälä Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Reviewed-by: Animesh Manna Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-5-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 73 ++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dsb.h | 2 + 2 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 9b2de4e7e681e..cd32b59adf187 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -93,6 +93,10 @@ struct intel_dsb { /* see DSB_REG_VALUE_MASK */ #define DSB_OPCODE_POLL 0xA /* see DSB_REG_VALUE_MASK */ +#define DSB_OPCODE_GOSUB 0xC /* ptl+ */ +#define DSB_GOSUB_HEAD_SHIFT 26 +#define DSB_GOSUB_TAIL_SHIFT 0 +#define DSB_GOSUB_CONVERT_ADDR(x) ((x) >> 6) static bool pre_commit_is_vrr_active(struct intel_atomic_state *state, struct intel_crtc *crtc) @@ -533,6 +537,75 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb) dsb->free_pos = aligned_tail / 4; } +static void intel_dsb_gosub_align(struct intel_dsb *dsb) +{ + u32 aligned_tail, tail; + + intel_dsb_ins_align(dsb); + + tail = dsb->free_pos * 4; + aligned_tail = ALIGN(tail, CACHELINE_BYTES); + + /* + * "The GOSUB instruction cannot be placed in + * cacheline QW slot 6 or 7 (numbered 0-7)" + */ + if (aligned_tail - tail <= 2 * 8) + intel_dsb_buffer_memset(&dsb->dsb_buf, dsb->free_pos, 0, + aligned_tail - tail); + + dsb->free_pos = aligned_tail / 4; +} + +void intel_dsb_gosub(struct intel_dsb *dsb, + struct intel_dsb *sub_dsb) +{ + struct intel_crtc *crtc = dsb->crtc; + struct intel_display *display = to_intel_display(crtc->base.dev); + unsigned int head, tail; + u64 head_tail; + + if (drm_WARN_ON(display->drm, dsb->id != sub_dsb->id)) + return; + + if (!assert_dsb_tail_is_aligned(sub_dsb)) + return; + + intel_dsb_gosub_align(dsb); + + head = intel_dsb_head(sub_dsb); + tail = intel_dsb_tail(sub_dsb); + + /* + * The GOSUB instruction has the following memory layout. + * + * +------------------------------------------------------------+ + * | Opcode | Rsvd | Head Ptr | Tail Ptr | + * | 0x0c | | | | + * +------------------------------------------------------------+ + * |<- 8bits->|<- 4bits ->|<-- 26bits -->|<-- 26bits -->| + * + * We have only 26 bits each to represent the head and tail + * pointers even though the addresses itself are of 32 bit. However, this + * is not a problem because the addresses are 64 bit aligned and therefore + * the last 6 bits are always Zero's. Therefore, we right shift the address + * by 6 before embedding it into the GOSUB instruction. + */ + + head_tail = ((u64)(DSB_GOSUB_CONVERT_ADDR(head)) << DSB_GOSUB_HEAD_SHIFT) | + ((u64)(DSB_GOSUB_CONVERT_ADDR(tail)) << DSB_GOSUB_TAIL_SHIFT); + + intel_dsb_emit(dsb, lower_32_bits(head_tail), + (DSB_OPCODE_GOSUB << DSB_OPCODE_SHIFT) | + upper_32_bits(head_tail)); + + /* + * "NOTE: the instructions within the cacheline + * FOLLOWING the GOSUB instruction must be NOPs." + */ + intel_dsb_align_tail(dsb); +} + void intel_dsb_finish(struct intel_dsb *dsb) { struct intel_crtc *crtc = dsb->crtc; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index e843c52bf97c2..8b2cf0a7b7e68 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -57,6 +57,8 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state, void intel_dsb_poll(struct intel_dsb *dsb, i915_reg_t reg, u32 mask, u32 val, int wait_us, int count); +void intel_dsb_gosub(struct intel_dsb *dsb, + struct intel_dsb *sub_dsb); void intel_dsb_chain(struct intel_atomic_state *state, struct intel_dsb *dsb, struct intel_dsb *chained_dsb, -- GitLab From 796b6df0f8f57c40e95bd49294cf5f869eab3e9b Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:35 +0530 Subject: [PATCH 122/902] drm/i915/dsb: add intel_dsb_gosub_finish() A DSB buffer which will be used for GOSUB execution does not need the DEWAKE mechanism but still need to be 64 bit aligned. Add helper to finish preparation of a dsb buffer to be executed with GOSUB instruction. v2: Add a cacheline of noops at the end of GOSUB buffer (Ville) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-6-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 13 +++++++++++++ drivers/gpu/drm/i915/display/intel_dsb.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index cd32b59adf187..04c2096df2dc8 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -606,6 +606,19 @@ void intel_dsb_gosub(struct intel_dsb *dsb, intel_dsb_align_tail(dsb); } +void intel_dsb_gosub_finish(struct intel_dsb *dsb) +{ + intel_dsb_align_tail(dsb); + + /* + * "All subroutines called by the GOSUB instruction + * must end with a cacheline of NOPs" + */ + intel_dsb_noop(dsb, 8); + + intel_dsb_buffer_flush_map(&dsb->dsb_buf); +} + void intel_dsb_finish(struct intel_dsb *dsb) { struct intel_crtc *crtc = dsb->crtc; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 8b2cf0a7b7e68..6900acd603b86 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -31,6 +31,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, enum intel_dsb_id dsb_id, unsigned int max_cmds); void intel_dsb_finish(struct intel_dsb *dsb); +void intel_dsb_gosub_finish(struct intel_dsb *dsb); void intel_dsb_cleanup(struct intel_dsb *dsb); void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -- GitLab From 78f237a6a61b102e0b4cd0ea842861e82ec323dd Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:36 +0530 Subject: [PATCH 123/902] drm/i915/dsb: Add support for GOSUB interrupt DSB raises an interrupt when there is a nested GOSUB command or illegal Head/Tail. Add support to log such errors in the DSB interrupt handler. v2: Enable support only in platforms that support this (Ville) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-7-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 9 +++++++++ drivers/gpu/drm/i915/display/intel_dsb_regs.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 04c2096df2dc8..a4a996018a826 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -655,6 +655,9 @@ static u32 dsb_error_int_status(struct intel_display *display) if (DISPLAY_VER(display) >= 14) errors |= DSB_ATS_FAULT_INT_STATUS; + if (DISPLAY_VER(display) >= 30) + errors |= DSB_GOSUB_INT_STATUS; + return errors; } @@ -669,6 +672,9 @@ static u32 dsb_error_int_en(struct intel_display *display) if (DISPLAY_VER(display) >= 14) errors |= DSB_ATS_FAULT_INT_EN; + if (DISPLAY_VER(display) >= 30) + errors |= DSB_GOSUB_INT_EN; + return errors; } @@ -1007,4 +1013,7 @@ void intel_dsb_irq_handler(struct intel_display *display, if (errors & DSB_POLL_ERR_INT_STATUS) drm_err(display->drm, "[CRTC:%d:%s] DSB %d poll error\n", crtc->base.base.id, crtc->base.name, dsb_id); + if (errors & DSB_GOSUB_INT_STATUS) + drm_err(display->drm, "[CRTC:%d:%s] DSB %d GOSUB programming error\n", + crtc->base.base.id, crtc->base.name, dsb_id); } diff --git a/drivers/gpu/drm/i915/display/intel_dsb_regs.h b/drivers/gpu/drm/i915/display/intel_dsb_regs.h index cb6e0e5624a6a..230104f361458 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dsb_regs.h @@ -51,11 +51,13 @@ #define DSB_RESET_SM_STATE_MASK REG_GENMASK(5, 4) #define DSB_RUN_SM_STATE_MASK REG_GENMASK(2, 0) #define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28) +#define DSB_GOSUB_INT_EN REG_BIT(21) /* ptl+ */ #define DSB_ATS_FAULT_INT_EN REG_BIT(20) /* mtl+ */ #define DSB_GTT_FAULT_INT_EN REG_BIT(19) #define DSB_RSPTIMEOUT_INT_EN REG_BIT(18) #define DSB_POLL_ERR_INT_EN REG_BIT(17) #define DSB_PROG_INT_EN REG_BIT(16) +#define DSB_GOSUB_INT_STATUS REG_BIT(5) /* ptl+ */ #define DSB_ATS_FAULT_INT_STATUS REG_BIT(4) /* mtl+ */ #define DSB_GTT_FAULT_INT_STATUS REG_BIT(3) #define DSB_RSPTIMEOUT_INT_STATUS REG_BIT(2) -- GitLab From 9dae0b6e9c8c05931c1708fa9e0f4d69166a61c0 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:37 +0530 Subject: [PATCH 124/902] drm/i915: s/dsb_color_vblank/dsb_color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With double buffer gamma registers in the mix, we need not wait for vblank to execute gamma writes through dsb. Before we implement that s/dsb_color_vblank/dsb_color. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Ville Syrjälä Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-8-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_color.c | 38 +++++++++---------- drivers/gpu/drm/i915/display/intel_display.c | 10 ++--- .../drm/i915/display/intel_display_types.h | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index e83feca5c9c9b..f85edb374c975 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -274,7 +274,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->do_async_flip = false; crtc_state->fb_bits = 0; crtc_state->update_planes = 0; - crtc_state->dsb_color_vblank = NULL; + crtc_state->dsb_color = NULL; crtc_state->dsb_commit = NULL; crtc_state->use_dsb = false; @@ -310,7 +310,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, { struct intel_crtc_state *crtc_state = to_intel_crtc_state(state); - drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank); + drm_WARN_ON(crtc->dev, crtc_state->dsb_color); drm_WARN_ON(crtc->dev, crtc_state->dsb_commit); __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 98dddf72c0eb9..bb2da3a53e9ca 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1339,8 +1339,8 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state, { struct intel_display *display = to_intel_display(crtc_state); - if (crtc_state->dsb_color_vblank) - intel_dsb_reg_write(crtc_state->dsb_color_vblank, reg, val); + if (crtc_state->dsb_color) + intel_dsb_reg_write(crtc_state->dsb_color, reg, val); else intel_de_write_fw(display, reg, val); } @@ -1350,8 +1350,8 @@ static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, { struct intel_display *display = to_intel_display(crtc_state); - if (crtc_state->dsb_color_vblank) - intel_dsb_reg_write_indexed(crtc_state->dsb_color_vblank, reg, val); + if (crtc_state->dsb_color) + intel_dsb_reg_write_indexed(crtc_state->dsb_color, reg, val); else intel_de_write_fw(display, reg, val); } @@ -1389,7 +1389,7 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, for (i = 0; i < 256; i++) { ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i), i9xx_lut_8(&lut[i])); - if (crtc_state->dsb_color_vblank) + if (crtc_state->dsb_color) ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i), i9xx_lut_8(&lut[i])); } @@ -1917,7 +1917,7 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - if (crtc_state->dsb_color_vblank) + if (crtc_state->dsb_color) return; display->funcs.color->load_luts(crtc_state); @@ -1982,39 +1982,39 @@ void intel_color_prepare_commit(struct intel_atomic_state *state, if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut) return; - crtc_state->dsb_color_vblank = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024); - if (!crtc_state->dsb_color_vblank) + crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024); + if (!crtc_state->dsb_color) return; display->funcs.color->load_luts(crtc_state); if (crtc_state->use_dsb) { - intel_vrr_send_push(crtc_state->dsb_color_vblank, crtc_state); - intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank); - intel_vrr_check_push_sent(crtc_state->dsb_color_vblank, crtc_state); - intel_dsb_interrupt(crtc_state->dsb_color_vblank); + intel_vrr_send_push(crtc_state->dsb_color, crtc_state); + intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color); + intel_vrr_check_push_sent(crtc_state->dsb_color, crtc_state); + intel_dsb_interrupt(crtc_state->dsb_color); } - intel_dsb_finish(crtc_state->dsb_color_vblank); + intel_dsb_finish(crtc_state->dsb_color); } void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) { - if (crtc_state->dsb_color_vblank) { - intel_dsb_cleanup(crtc_state->dsb_color_vblank); - crtc_state->dsb_color_vblank = NULL; + if (crtc_state->dsb_color) { + intel_dsb_cleanup(crtc_state->dsb_color); + crtc_state->dsb_color = NULL; } } void intel_color_wait_commit(const struct intel_crtc_state *crtc_state) { - if (crtc_state->dsb_color_vblank) - intel_dsb_wait(crtc_state->dsb_color_vblank); + if (crtc_state->dsb_color) + intel_dsb_wait(crtc_state->dsb_color); } bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state) { - return crtc_state->dsb_color_vblank; + return crtc_state->dsb_color; } static bool intel_can_preload_luts(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c894e4d0d4881..f261ceca5a3a5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7192,7 +7192,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color_vblank) + if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color) return; /* @@ -7239,7 +7239,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, skl_detach_scalers(new_crtc_state->dsb_commit, new_crtc_state); - if (!new_crtc_state->dsb_color_vblank) { + if (!new_crtc_state->dsb_color) { intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1); intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state); @@ -7249,9 +7249,9 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, } } - if (new_crtc_state->dsb_color_vblank) + if (new_crtc_state->dsb_color) intel_dsb_chain(state, new_crtc_state->dsb_commit, - new_crtc_state->dsb_color_vblank, true); + new_crtc_state->dsb_color, true); intel_dsb_finish(new_crtc_state->dsb_commit); } @@ -7440,7 +7440,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * * FIXME get rid of this funny new->old swapping */ - old_crtc_state->dsb_color_vblank = fetch_and_zero(&new_crtc_state->dsb_color_vblank); + old_crtc_state->dsb_color = fetch_and_zero(&new_crtc_state->dsb_color); old_crtc_state->dsb_commit = fetch_and_zero(&new_crtc_state->dsb_commit); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b8836d29a7214..fc1eda590da85 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1297,7 +1297,7 @@ struct intel_crtc_state { enum transcoder mst_master_transcoder; /* For DSB based pipe updates */ - struct intel_dsb *dsb_color_vblank, *dsb_commit; + struct intel_dsb *dsb_color, *dsb_commit; bool use_dsb; u32 psr2_man_track_ctl; -- GitLab From b0e0369bca338bb6a07466838cef6c6e5a1a55b9 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:38 +0530 Subject: [PATCH 125/902] drm/i915/display: use GOSUB to program double buffered LUT registers With addition of double buffered GAMMA registers in PTL, we can now program them in the active region. Use GOSUB instruction of DSB to program them. It is done in the following steps: 1. intel_color_prepare_commit() - If the platform supports, prepare a dsb instance (dsb_color) hooked to DSB0. - Add all the register write instructions to dsb_color through the load_lut() hook - Do not add the vrr_send_push() logic to the buffer as it should be taken care by dsb_commit instance of DSB0 - Finish preparation of the buffer by aligning it to 64 bit 2. intel_atomic_dsb_finish() - Add the gosub instruction into the dsb_commit instance of DSB0 using intel_dsb_gosub() - If needed, add the vrr_send_push() logic to dsb_commit after it v2: Refactor code to simplify commit completion flow. Add some helpers along the way (Ville) v3: s/doubled/double and add display to commit message prefix (Uma) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-9-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 39 ++++++++++++++----- drivers/gpu/drm/i915/display/intel_color.h | 2 + drivers/gpu/drm/i915/display/intel_display.c | 24 +++++++----- .../drm/i915/display/intel_display_device.h | 1 + 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index bb2da3a53e9ca..ac00b86798fb5 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1965,6 +1965,25 @@ void intel_color_modeset(const struct intel_crtc_state *crtc_state) } } +bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->dsb_color; +} + +bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + return crtc_state->dsb_color && !HAS_DOUBLE_BUFFERED_LUT(display); +} + +bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + return crtc_state->dsb_color && HAS_DOUBLE_BUFFERED_LUT(display); +} + void intel_color_prepare_commit(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1982,20 +2001,27 @@ void intel_color_prepare_commit(struct intel_atomic_state *state, if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut) return; - crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024); - if (!crtc_state->dsb_color) + if (HAS_DOUBLE_BUFFERED_LUT(display)) + crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 1024); + else + crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024); + + if (!intel_color_uses_dsb(crtc_state)) return; display->funcs.color->load_luts(crtc_state); - if (crtc_state->use_dsb) { + if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) { intel_vrr_send_push(crtc_state->dsb_color, crtc_state); intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color); intel_vrr_check_push_sent(crtc_state->dsb_color, crtc_state); intel_dsb_interrupt(crtc_state->dsb_color); } - intel_dsb_finish(crtc_state->dsb_color); + if (intel_color_uses_gosub_dsb(crtc_state)) + intel_dsb_gosub_finish(crtc_state->dsb_color); + else + intel_dsb_finish(crtc_state->dsb_color); } void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) @@ -2012,11 +2038,6 @@ void intel_color_wait_commit(const struct intel_crtc_state *crtc_state) intel_dsb_wait(crtc_state->dsb_color); } -bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state) -{ - return crtc_state->dsb_color; -} - static bool intel_can_preload_luts(struct intel_atomic_state *state, struct intel_crtc *crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 9d66457c1e893..bf7a12ce9df0f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -24,6 +24,8 @@ void intel_color_prepare_commit(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state); bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state); +bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state); +bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state); void intel_color_wait_commit(const struct intel_crtc_state *crtc_state); void intel_color_commit_noarm(struct intel_dsb *dsb, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f261ceca5a3a5..128b2d865ac37 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7238,20 +7238,24 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, if (DISPLAY_VER(display) >= 9) skl_detach_scalers(new_crtc_state->dsb_commit, new_crtc_state); - - if (!new_crtc_state->dsb_color) { - intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1); - - intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state); - intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit); - intel_vrr_check_push_sent(new_crtc_state->dsb_commit, new_crtc_state); - intel_dsb_interrupt(new_crtc_state->dsb_commit); - } } - if (new_crtc_state->dsb_color) + if (intel_color_uses_chained_dsb(new_crtc_state)) intel_dsb_chain(state, new_crtc_state->dsb_commit, new_crtc_state->dsb_color, true); + else if (intel_color_uses_gosub_dsb(new_crtc_state)) + intel_dsb_gosub(new_crtc_state->dsb_commit, + new_crtc_state->dsb_color); + + if (new_crtc_state->use_dsb && !intel_color_uses_chained_dsb(new_crtc_state)) { + intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1); + + intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state); + intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit); + intel_vrr_check_push_sent(new_crtc_state->dsb_commit, + new_crtc_state); + intel_dsb_interrupt(new_crtc_state->dsb_commit); + } intel_dsb_finish(new_crtc_state->dsb_commit); } diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index f0ea56cc5def5..0ac5484c00438 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -157,6 +157,7 @@ struct intel_display_platforms { #define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc) #define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20) #define HAS_DOUBLE_BUFFERED_M_N(__display) (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell) +#define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30) #define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4) #define HAS_DP20(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14) #define HAS_DPT(__display) (DISPLAY_VER(__display) >= 13) -- GitLab From d94a92b7d0a4424936b6a5aa25038a769cdd4ba8 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:39 +0530 Subject: [PATCH 126/902] drm/i915: Program DB LUT registers before vblank Double Buffered LUT registers can be programmed in the active region. This patch implements the MMIO path for it. Program the registers after evading vblank. The HW latches on to the registers after delayed vblank. It takes around 1024 cdclk cycles(~one scanline) for this. Following assumptions have been made while making this change - Current vblank evasion time is sufficient for programming the LUT registers. - Current guardband calculation would be sufficient for the HW to latch on to the new values v2: move loading LUTs to commit_pipe_post_planes() since a vblank evasion failure for this is probably less drastic than for plane programming. (Ville) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-10-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 128b2d865ac37..06f58c062b296 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6638,6 +6638,7 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + bool modeset = intel_crtc_needs_modeset(new_crtc_state); drm_WARN_ON(display->drm, new_crtc_state->use_dsb); @@ -6646,10 +6647,15 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state, * get a catastrophic underrun even if the two operations * end up happening in two different frames. */ - if (DISPLAY_VER(display) >= 9 && - !intel_crtc_needs_modeset(new_crtc_state)) + if (DISPLAY_VER(display) >= 9 && !modeset) skl_detach_scalers(NULL, new_crtc_state); + if (!modeset && + intel_crtc_needs_color_update(new_crtc_state) && + !intel_color_uses_dsb(new_crtc_state) && + HAS_DOUBLE_BUFFERED_LUT(display)) + intel_color_load_luts(new_crtc_state); + if (intel_crtc_vrr_enabling(state, crtc)) intel_vrr_enable(new_crtc_state); } -- GitLab From 88d7e284b24ee3e16b97630536c6aa06e58941db Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:40 +0530 Subject: [PATCH 127/902] drm/i915/color: Do not pre-load LUTs with DB registers Since Double Buffered LUT registers can be written in active region no need to preload them. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-11-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index ac00b86798fb5..671db6926e4c8 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2041,9 +2041,13 @@ void intel_color_wait_commit(const struct intel_crtc_state *crtc_state) static bool intel_can_preload_luts(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + if (HAS_DOUBLE_BUFFERED_LUT(display)) + return false; + return !old_crtc_state->post_csc_lut && !old_crtc_state->pre_csc_lut; } -- GitLab From dc0698d1b30c053d48dbe49cedb037633fa8a391 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Fri, 23 May 2025 11:50:41 +0530 Subject: [PATCH 128/902] drm/i915: Disable updating of LUT values during vblank Do not schedule vblank worker for LUT update if the registers are double buffered v2: Do not schedule the worker at all (Ville) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Signed-off-by: Animesh Manna Link: https://lore.kernel.org/r/20250523062041.166468-12-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_crtc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 29cfc38f12e04..a88317ea4e9c0 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -417,10 +417,13 @@ int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); + return crtc_state->hw.active && !crtc_state->preload_luts && !intel_crtc_needs_modeset(crtc_state) && - intel_crtc_needs_color_update(crtc_state) && + (intel_crtc_needs_color_update(crtc_state) && + !HAS_DOUBLE_BUFFERED_LUT(display)) && !intel_color_uses_dsb(crtc_state) && !crtc_state->use_dsb; } -- GitLab From 6f142c52d3ce6eca626b1444a0694d27de6be993 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 22 May 2025 12:48:42 +0300 Subject: [PATCH 129/902] drm/i915/display: allocate struct intel_display dynamically Allocate struct intel_display dynamically in intel_display_device_probe() and free in intel_display_device_remove(). v2: Remove duplicate intel_display_device_remove() on error path (Lucas) Reviewed-by: Rodrigo Vivi Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/8cd526a177061cddf71db59bd0901bd1a24e77be.1747907216.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_device.c | 10 +++++++++- drivers/gpu/drm/i915/i915_driver.c | 13 +++++++------ drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/selftests/mock_gem_device.c | 11 ++++++++--- drivers/gpu/drm/xe/display/xe_display.c | 7 ++++--- drivers/gpu/drm/xe/xe_device_types.h | 1 - 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index 90d7145986643..1d8c2036d967f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -1621,13 +1621,17 @@ static void display_platforms_or(struct intel_display_platforms *dst, struct intel_display *intel_display_device_probe(struct pci_dev *pdev) { - struct intel_display *display = to_intel_display(pdev); + struct intel_display *display; const struct intel_display_device_info *info; struct intel_display_ip_ver ip_ver = {}; const struct platform_desc *desc; const struct subplatform_desc *subdesc; enum intel_step step; + display = kzalloc(sizeof(*display), GFP_KERNEL); + if (!display) + return ERR_PTR(-ENOMEM); + /* Add drm device backpointer as early as possible. */ display->drm = pci_get_drvdata(pdev); @@ -1708,7 +1712,11 @@ no_display: void intel_display_device_remove(struct intel_display *display) { + if (!display) + return; + intel_display_params_free(&display->params); + kfree(display); } static void __intel_display_device_info_runtime_init(struct intel_display *display) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 950b7ad8d675f..d33b0eb83a4f3 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -293,6 +293,8 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) intel_sbi_fini(dev_priv); i915_params_free(&dev_priv->params); + + intel_display_device_remove(display); } /** @@ -735,6 +737,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) const struct intel_device_info *match_info = (struct intel_device_info *)ent->driver_data; struct drm_i915_private *i915; + struct intel_display *display; i915 = devm_drm_dev_alloc(&pdev->dev, &i915_drm_driver, struct drm_i915_private, drm); @@ -749,10 +752,11 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, match_info); - /* TODO: Allocate display dynamically. */ - i915->display = &i915->__display; + display = intel_display_device_probe(pdev); + if (IS_ERR(display)) + return ERR_CAST(display); - intel_display_device_probe(pdev); + i915->display = display; return i915; } @@ -911,7 +915,6 @@ void i915_driver_remove(struct drm_i915_private *i915) static void i915_driver_release(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; intel_wakeref_t wakeref; @@ -934,8 +937,6 @@ static void i915_driver_release(struct drm_device *dev) intel_runtime_pm_driver_release(rpm); i915_driver_late_release(dev_priv); - - intel_display_device_remove(display); } static int i915_driver_open(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0841988c4a671..fd0274ec9c2c7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -178,7 +178,6 @@ struct drm_i915_private { struct drm_device drm; struct intel_display *display; - struct intel_display __display; /* Transitional. Do not use directly. */ /* FIXME: Device release actions should all be moved to drmm_ */ bool do_release; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 0ea12c68cedb2..dab2b71a2a8fc 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -141,6 +141,7 @@ struct drm_i915_private *mock_gem_device(void) static struct dev_iommu fake_iommu = { .priv = (void *)-1 }; #endif struct drm_i915_private *i915; + struct intel_display *display; struct pci_dev *pdev; int ret; @@ -180,10 +181,11 @@ struct drm_i915_private *mock_gem_device(void) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, &mock_info); - /* TODO: Allocate display dynamically. */ - i915->display = &i915->__display; + display = intel_display_device_probe(pdev); + if (IS_ERR(display)) + goto err_device; - intel_display_device_probe(pdev); + i915->display = display; dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); @@ -260,6 +262,7 @@ err_ttm: intel_gt_driver_late_release_all(i915); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); +err_device: mock_destroy_device(i915); return NULL; @@ -269,6 +272,8 @@ void mock_destroy_device(struct drm_i915_private *i915) { struct device *dev = i915->drm.dev; + intel_display_device_remove(i915->display); + devres_release_group(dev, NULL); put_device(dev); } diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 1e59b6dd2c3bd..db7ef8737e1d5 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -529,15 +529,16 @@ int xe_display_probe(struct xe_device *xe) if (!xe->info.probe_display) goto no_display; - /* TODO: Allocate display dynamically. */ - xe->display = &xe->__display; - display = intel_display_device_probe(pdev); + if (IS_ERR(display)) + return PTR_ERR(display); err = drmm_add_action_or_reset(&xe->drm, display_device_remove, display); if (err) return err; + xe->display = display; + if (has_display(xe)) return 0; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 634ac4aa7674b..ae9243e409a67 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -588,7 +588,6 @@ struct xe_device { * migrating to the right sub-structs */ struct intel_display *display; - struct intel_display __display; /* Transitional. Do not use directly. */ struct dram_info { bool wm_lv_0_adjust_needed; -- GitLab From 62384da2a04d7a61d840ad099fc9d0d065b31208 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 22 May 2025 12:48:43 +0300 Subject: [PATCH 130/902] drm/i915: stop including display/intel_display_{core, limits}.h from i915_drv.h Make i915->display pointer opaque to most of core i915 driver. Lots of places now need explicit include of intel_display_core.h, or a more specific header. With this dependency broken, changes in display should cause radically less recompilation of i915. Reviewed-by: Chaitanya Kumar Borah Link: https://lore.kernel.org/r/b381b59acb7e4f600e0282935a68aedf77768109.1747907216.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 1 + drivers/gpu/drm/i915/display/intel_display_conversion.c | 1 + drivers/gpu/drm/i915/display/intel_display_driver.c | 1 + drivers/gpu/drm/i915/display/intel_display_reset.c | 1 + drivers/gpu/drm/i915/display/intel_display_rpm.c | 1 + drivers/gpu/drm/i915/display/intel_display_rps.c | 1 + drivers/gpu/drm/i915/display/intel_dpt.c | 1 + drivers/gpu/drm/i915/display/intel_encoder.c | 2 +- drivers/gpu/drm/i915/display/intel_fb.c | 1 + drivers/gpu/drm/i915/display/intel_fb_bo.c | 1 + drivers/gpu/drm/i915/display/intel_fb_pin.c | 1 + drivers/gpu/drm/i915/display/intel_fbdev_fb.c | 1 + drivers/gpu/drm/i915/display/intel_hotplug.c | 1 + drivers/gpu/drm/i915/display/intel_opregion.c | 1 + drivers/gpu/drm/i915/display/intel_plane_initial.c | 1 + drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c | 1 + drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 ++ drivers/gpu/drm/i915/gvt/cmd_parser.c | 1 + drivers/gpu/drm/i915/gvt/display.c | 1 + drivers/gpu/drm/i915/gvt/edid.c | 1 + drivers/gpu/drm/i915/gvt/fb_decoder.c | 1 + drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/i915_driver.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 7 +++---- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_switcheroo.c | 2 ++ drivers/gpu/drm/i915/intel_clock_gating.c | 1 + drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 1 + drivers/gpu/drm/i915/intel_uncore.c | 2 ++ drivers/gpu/drm/i915/selftests/mock_gem_device.c | 2 ++ drivers/gpu/drm/i915/soc/intel_dram.c | 2 ++ drivers/gpu/drm/i915/soc/intel_gmch.c | 2 ++ 32 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index ba7b8938b17c3..9ce41e689d501 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -37,6 +37,7 @@ #include "i915_drv.h" #include "intel_display.h" +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_gmbus.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_conversion.c b/drivers/gpu/drm/i915/display/intel_display_conversion.c index 151d83fdbe379..4d565935e2cc7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_conversion.c +++ b/drivers/gpu/drm/i915/display/intel_display_conversion.c @@ -2,6 +2,7 @@ /* Copyright © 2024 Intel Corporation */ #include "i915_drv.h" +#include "intel_display_conversion.h" struct intel_display *__i915_to_display(struct drm_i915_private *i915) { diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 2bdafab9b6d00..ec799a1773e47 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -27,6 +27,7 @@ #include "intel_cdclk.h" #include "intel_color.h" #include "intel_crtc.h" +#include "intel_display_core.h" #include "intel_display_debugfs.h" #include "intel_display_driver.h" #include "intel_display_irq.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c index 1dbd3e841df33..f5f38dca14d7f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.c +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c @@ -8,6 +8,7 @@ #include "i915_drv.h" #include "intel_clock_gating.h" #include "intel_cx0_phy.h" +#include "intel_display_core.h" #include "intel_display_driver.h" #include "intel_display_reset.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.c b/drivers/gpu/drm/i915/display/intel_display_rpm.c index 48da67dd01361..56c4024201c16 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rpm.c +++ b/drivers/gpu/drm/i915/display/intel_display_rpm.c @@ -2,6 +2,7 @@ /* Copyright © 2025 Intel Corporation */ #include "i915_drv.h" +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_runtime_pm.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index 0f1c95d70843b..82ea1ec482e41 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -9,6 +9,7 @@ #include "gt/intel_rps.h" #include "i915_drv.h" #include "i915_reg.h" +#include "intel_display_core.h" #include "intel_display_irq.h" #include "intel_display_rps.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 8684cf8e4b7f0..aea249e2699f3 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -9,6 +9,7 @@ #include "gt/gen8_ppgtt.h" #include "i915_drv.h" +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dpt.h" diff --git a/drivers/gpu/drm/i915/display/intel_encoder.c b/drivers/gpu/drm/i915/display/intel_encoder.c index 21d6385354972..bad452ad979a8 100644 --- a/drivers/gpu/drm/i915/display/intel_encoder.c +++ b/drivers/gpu/drm/i915/display/intel_encoder.c @@ -6,7 +6,7 @@ #include #include "i915_drv.h" - +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_encoder.h" diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 05393bd60c989..a5906cb4900c0 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -14,6 +14,7 @@ #include "intel_atomic_plane.h" #include "intel_bo.h" #include "intel_display.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" diff --git a/drivers/gpu/drm/i915/display/intel_fb_bo.c b/drivers/gpu/drm/i915/display/intel_fb_bo.c index 3d338a7283546..b0e8b89f7ce8f 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_bo.c +++ b/drivers/gpu/drm/i915/display/intel_fb_bo.c @@ -8,6 +8,7 @@ #include "gem/i915_gem_object.h" #include "i915_drv.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_bo.h" diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index c648ab8a93d76..98a61a7b0b932 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -12,6 +12,7 @@ #include "i915_drv.h" #include "intel_atomic_plane.h" +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dpt.h" diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c index 5f4cb3328265f..8db3af36b2f2d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c @@ -8,6 +8,7 @@ #include "gem/i915_gem_lmem.h" #include "i915_drv.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fbdev_fb.h" diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index fc5d8928c37ef..74fe398663d63 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -30,6 +30,7 @@ #include "i915_irq.h" #include "intel_connector.h" #include "intel_display_power.h" +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_hdcp.h" diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index 0eaa6cd6fe809..5535cb7994317 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -35,6 +35,7 @@ #include "i915_drv.h" #include "intel_acpi.h" #include "intel_backlight.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_opregion.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index c00d9184c5866..8800a657cd21f 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -9,6 +9,7 @@ #include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_display.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_frontbuffer.h" diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index bac15196b4d24..86d9d2fcb6a6b 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -5,6 +5,7 @@ #include "i915_selftest.h" +#include "display/intel_display_core.h" #include "gt/intel_context.h" #include "gt/intel_engine_regs.h" #include "gt/intel_engine_user.h" diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 3b77b4bb88e33..c7f59d60fac64 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -6,6 +6,8 @@ #include #include +#include "display/intel_display_power.h" + #include "i915_drv.h" #include "i915_irq.h" #include "i915_params.h" diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 2b5094e8de5e3..62d744363598f 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -50,6 +50,7 @@ #include "trace.h" #include "display/i9xx_plane_regs.h" +#include "display/intel_display_core.h" #include "display/intel_sprite_regs.h" #include "gem/i915_gem_context.h" #include "gem/i915_gem_pm.h" diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index b77e8f3ff75c8..6fed71f8198fa 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -43,6 +43,7 @@ #include "display/intel_crt_regs.h" #include "display/intel_cursor_regs.h" #include "display/intel_display.h" +#include "display/intel_display_core.h" #include "display/intel_dpio_phy.h" #include "display/intel_sprite_regs.h" diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index 89147d33168c0..2031b97de2b76 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -35,6 +35,7 @@ #include #include "display/intel_dp_aux_regs.h" +#include "display/intel_gmbus.h" #include "display/intel_gmbus_regs.h" #include "gvt.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c index 4cfe8d7f368d2..112f6723c4277 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.c +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -42,6 +42,7 @@ #include "display/i9xx_plane_regs.h" #include "display/intel_cursor_regs.h" +#include "display/intel_display_core.h" #include "display/intel_sprite_regs.h" #include "display/skl_universal_plane_regs.h" diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 11cb8bf1fa4aa..9b001776a9608 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -47,6 +47,7 @@ #include "display/i9xx_plane_regs.h" #include "display/intel_crt_regs.h" #include "display/intel_cursor_regs.h" +#include "display/intel_display_core.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dp_aux_regs.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index d33b0eb83a4f3..3b0bda74697d7 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -51,6 +51,7 @@ #include "display/intel_bw.h" #include "display/intel_cdclk.h" #include "display/intel_crtc.h" +#include "display/intel_display_core.h" #include "display/intel_display_driver.h" #include "display/intel_dmc.h" #include "display/intel_dp.h" @@ -58,6 +59,7 @@ #include "display/intel_encoder.h" #include "display/intel_fbdev.h" #include "display/intel_hotplug.h" +#include "display/intel_opregion.h" #include "display/intel_overlay.h" #include "display/intel_pch_refclk.h" #include "display/intel_pps.h" diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fd0274ec9c2c7..b6c632bd522cd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -32,13 +32,11 @@ #include +#include #include #include -#include "display/intel_display_limits.h" -#include "display/intel_display_core.h" - #include "gem/i915_gem_context_types.h" #include "gem/i915_gem_shrinker.h" #include "gem/i915_gem_stolen.h" @@ -63,8 +61,9 @@ #include "intel_uncore.h" struct drm_i915_clock_gating_funcs; -struct vlv_s0ix_state; +struct intel_display; struct intel_pxp; +struct vlv_s0ix_state; #define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 351928481cd9e..191ed8bb1d9c4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,6 +33,7 @@ #include +#include "display/intel_display_core.h" #include "display/intel_display_irq.h" #include "display/intel_hotplug.h" #include "display/intel_hotplug_irq.h" diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c index f45bd6b6cede4..4c02a04be6817 100644 --- a/drivers/gpu/drm/i915/i915_switcheroo.c +++ b/drivers/gpu/drm/i915/i915_switcheroo.c @@ -5,6 +5,8 @@ #include +#include "display/intel_display_core.h" + #include "i915_driver.h" #include "i915_drv.h" #include "i915_switcheroo.h" diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 5bbf891ccc32c..f86a3629ae9ea 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -27,6 +27,7 @@ #include "display/i9xx_plane_regs.h" #include "display/intel_display.h" +#include "display/intel_display_core.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index d581a9d2c063d..e83dc30e658d6 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -11,6 +11,7 @@ #include "display/intel_color_regs.h" #include "display/intel_crt_regs.h" #include "display/intel_cursor_regs.h" +#include "display/intel_display_core.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dp_aux_regs.h" diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 48a10ff801486..9b2254d864917 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -24,6 +24,8 @@ #include #include +#include "display/intel_display_core.h" + #include "gt/intel_gt.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index dab2b71a2a8fc..fb8751bd5df0a 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -28,6 +28,8 @@ #include +#include "display/intel_display_device.h" + #include "gt/intel_gt.h" #include "gt/intel_gt_requests.h" #include "gt/mock_engine.h" diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index efee955ae8a3d..9f806ce0eb9ef 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -5,6 +5,8 @@ #include +#include "../display/intel_display_core.h" /* FIXME */ + #include "i915_drv.h" #include "i915_reg.h" #include "intel_dram.h" diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 734e9f2801eab..5346b8dda79a4 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -10,6 +10,8 @@ #include #include +#include "../display/intel_display_core.h" /* FIXME */ + #include "i915_drv.h" #include "intel_gmch.h" #include "intel_pci_config.h" -- GitLab From e6ba431676d522ddc5f4301c0b5fb9f4741433c2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 22 May 2025 12:48:44 +0300 Subject: [PATCH 131/902] drm/xe: stop including intel_display_{core, device}.h from xe_device_types.h Make xe->display pointer opaque to most of core xe driver. A few places now need explicit include of intel_display_core.h. With this dependency broken, changes in display should cause radically less recompilation of xe. Acked-by: Lucas De Marchi Reviewed-by: Chaitanya Kumar Borah Link: https://lore.kernel.org/r/a12918f4d404e2d6d4e963126ce96df01d5064f3.1747907216.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 1 + drivers/gpu/drm/xe/display/xe_display.c | 1 + drivers/gpu/drm/xe/display/xe_display_rpm.c | 1 + drivers/gpu/drm/xe/display/xe_display_wa.c | 2 +- drivers/gpu/drm/xe/display/xe_fb_pin.c | 1 + drivers/gpu/drm/xe/display/xe_plane_initial.c | 1 + drivers/gpu/drm/xe/display/xe_tdf.c | 4 ++-- drivers/gpu/drm/xe/xe_device_types.h | 6 +----- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c index e8191562d122e..b28a94df824fb 100644 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c @@ -5,6 +5,7 @@ #include +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fbdev_fb.h" diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index db7ef8737e1d5..3f92bf51813e5 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -20,6 +20,7 @@ #include "intel_audio.h" #include "intel_bw.h" #include "intel_display.h" +#include "intel_display_core.h" #include "intel_display_driver.h" #include "intel_display_irq.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c index ef76efe42e9f8..3825376e98ccd 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rpm.c +++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT /* Copyright © 2025 Intel Corporation */ +#include "intel_display_core.h" #include "intel_display_rpm.h" #include "xe_device.h" #include "xe_device_types.h" diff --git a/drivers/gpu/drm/xe/display/xe_display_wa.c b/drivers/gpu/drm/xe/display/xe_display_wa.c index 2933ca97d673b..68d1387d81a06 100644 --- a/drivers/gpu/drm/xe/display/xe_display_wa.c +++ b/drivers/gpu/drm/xe/display/xe_display_wa.c @@ -3,8 +3,8 @@ * Copyright © 2024 Intel Corporation */ +#include "intel_display_core.h" #include "intel_display_wa.h" - #include "xe_device.h" #include "xe_wa.h" diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index c2b4be72f7a00..461ecdfdb7422 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -6,6 +6,7 @@ #include #include "i915_vma.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 6502b82741732..fada6f877bca5 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -14,6 +14,7 @@ #include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_display.h" +#include "intel_display_core.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_pin.h" diff --git a/drivers/gpu/drm/xe/display/xe_tdf.c b/drivers/gpu/drm/xe/display/xe_tdf.c index 2a7fccbeb1d55..78bda4c47874a 100644 --- a/drivers/gpu/drm/xe/display/xe_tdf.c +++ b/drivers/gpu/drm/xe/display/xe_tdf.c @@ -3,9 +3,9 @@ * Copyright © 2024 Intel Corporation */ -#include "xe_device.h" -#include "intel_display_types.h" +#include "intel_display_core.h" #include "intel_tdf.h" +#include "xe_device.h" void intel_td_flush(struct intel_display *display) { diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index ae9243e409a67..5c56f0d96e32e 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -30,11 +30,7 @@ #define TEST_VM_OPS_ERROR #endif -#if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) -#include "intel_display_core.h" -#include "intel_display_device.h" -#endif - +struct intel_display; struct xe_ggtt; struct xe_pat_ops; struct xe_pxp; -- GitLab From d2dc30e0aa252830f908c8e793d3139d51321370 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Thu, 22 May 2025 09:41:27 +0300 Subject: [PATCH 132/902] Revert "drm/i915/gem: Allow EXEC_CAPTURE on recoverable contexts on DG1" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d6e020819612a4a06207af858e0978be4d3e3140. The IS_DGFX check was put in place because error capture of buffer objects is expected to be broken on devices with VRAM. Userspace fix[1] to the impacted media driver has been submitted, merged and a new driver release is out as 25.2.3 where the capture flag is dropped on DG1 thus unblocking the usage of media driver on DG1. [1] https://github.com/intel/media-driver/commit/93c07d9b4b96a78bab21f6acd4eb863f4313ea4a Cc: stable@vger.kernel.org # v6.0+ Cc: Ville Syrjälä Cc: Andi Shyti Cc: Matthew Auld Cc: Thomas Hellström Cc: Tvrtko Ursulin Acked-by: Tvrtko Ursulin Reviewed-by: Andi Shyti Link: https://lore.kernel.org/r/20250522064127.24293-1-joonas.lahtinen@linux.intel.com [Joonas: Update message to point out the merged userspace fix] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 7d44aadcd5a5c..02c59808cbe48 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2013,7 +2013,7 @@ static int eb_capture_stage(struct i915_execbuffer *eb) continue; if (i915_gem_context_is_recoverable(eb->gem_context) && - GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 10)) + (IS_DGFX(eb->i915) || GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 0))) return -EINVAL; for_each_batch_create_order(eb, j) { -- GitLab From af53f0fd99c3bbb3afd29f1612c9e88c5a92cc01 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 21 May 2025 12:51:47 -0400 Subject: [PATCH 133/902] drm/xe: Make xe_gt_freq part of the Documentation The documentation was created with the creation of the component, however it has never been actually shown in the actual Documentation. While doing this, fixes the identation style, to avoid new warnings while building htmldocs. Fixes: bef52b5c7a19 ("drm/xe: Create a xe_gt_freq component for raw management and sysfs") Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250521165146.39616-3-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- Documentation/gpu/xe/index.rst | 1 + Documentation/gpu/xe/xe_gt_freq.rst | 14 ++++++++++++++ drivers/gpu/drm/xe/xe_gt_freq.c | 2 ++ 3 files changed, 17 insertions(+) create mode 100644 Documentation/gpu/xe/xe_gt_freq.rst diff --git a/Documentation/gpu/xe/index.rst b/Documentation/gpu/xe/index.rst index b2369561f24e1..42ba6c263cd0d 100644 --- a/Documentation/gpu/xe/index.rst +++ b/Documentation/gpu/xe/index.rst @@ -16,6 +16,7 @@ DG2, etc is provided to prototype the driver. xe_migrate xe_cs xe_pm + xe_gt_freq xe_pcode xe_gt_mcr xe_wa diff --git a/Documentation/gpu/xe/xe_gt_freq.rst b/Documentation/gpu/xe/xe_gt_freq.rst new file mode 100644 index 0000000000000..c0811200e3275 --- /dev/null +++ b/Documentation/gpu/xe/xe_gt_freq.rst @@ -0,0 +1,14 @@ +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +========================== +Xe GT Frequency Management +========================== + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_freq.c + :doc: Xe GT Frequency Management + +Internal API +============ + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_freq.c + :internal: diff --git a/drivers/gpu/drm/xe/xe_gt_freq.c b/drivers/gpu/drm/xe/xe_gt_freq.c index 868a5d2c1a52f..3293d89f1386e 100644 --- a/drivers/gpu/drm/xe/xe_gt_freq.c +++ b/drivers/gpu/drm/xe/xe_gt_freq.c @@ -32,6 +32,7 @@ * Xe's Freq provides a sysfs API for frequency management: * * device/tile#/gt#/freq0/_freq *read-only* files: + * * - act_freq: The actual resolved frequency decided by PCODE. * - cur_freq: The current one requested by GuC PC to the PCODE. * - rpn_freq: The Render Performance (RP) N level, which is the minimal one. @@ -39,6 +40,7 @@ * - rp0_freq: The Render Performance (RP) 0 level, which is the maximum one. * * device/tile#/gt#/freq0/_freq *read-write* files: + * * - min_freq: Min frequency request. * - max_freq: Max frequency request. * If max <= min, then freq_min becomes a fixed frequency request. -- GitLab From 39578fa40420fb11dbe4f42225a347e945d8fd0e Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 21 May 2025 12:51:48 -0400 Subject: [PATCH 134/902] drm/xe: Add missing documentation of rpa_freq While at it, already adjust the rpe_freq frequency, to highlight that both are calculated by PCODE at runtime. Fixes: c6aac2fa77a3 ("drm/xe: Introduce the RPa information") Cc: Vinay Belgaumkar Cc: Lucas De Marchi Reviewed-by: Lucas De Marchi Reviewed-by: Vinay Belgaumkar Link: https://lore.kernel.org/r/20250521165146.39616-4-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_gt_freq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_freq.c b/drivers/gpu/drm/xe/xe_gt_freq.c index 3293d89f1386e..60d9354e7dbf4 100644 --- a/drivers/gpu/drm/xe/xe_gt_freq.c +++ b/drivers/gpu/drm/xe/xe_gt_freq.c @@ -36,7 +36,10 @@ * - act_freq: The actual resolved frequency decided by PCODE. * - cur_freq: The current one requested by GuC PC to the PCODE. * - rpn_freq: The Render Performance (RP) N level, which is the minimal one. + * - rpa_freq: The Render Performance (RP) A level, which is the achiveable one. + * Calculated by PCODE at runtime based on multiple running conditions * - rpe_freq: The Render Performance (RP) E level, which is the efficient one. + * Calculated by PCODE at runtime based on multiple running conditions * - rp0_freq: The Render Performance (RP) 0 level, which is the maximum one. * * device/tile#/gt#/freq0/_freq *read-write* files: -- GitLab From 22eba3be8e1dc27de4aec3374bc9018dc8713670 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Mon, 26 May 2025 22:09:07 +0530 Subject: [PATCH 135/902] drm/xe/svm: Avoid duplicate eviction on get_pages() failure xe_svm_range_get_pages() already calls drm_gpusvm_range_evict() internally when it fails with -EOPNOTSUPP. Remove the eviction call in the caller to prevent duplicate handling. Fixes: e0ff0d7cf928 ("drm/xe/svm: Refactor usage of drm_gpusvm* function in xe_svm") Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250526163907.1011529-1-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 4432685936ed4..871ac81bb04aa 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -914,11 +914,6 @@ retry: if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (migrate_try_count > 0 || !ctx.devmem_only) { - if (err == -EOPNOTSUPP) { - range_debug(range, "PAGE FAULT - EVICT PAGES"); - drm_gpusvm_range_evict(&vm->svm.gpusvm, - &range->base); - } drm_dbg(&vm->xe->drm, "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); -- GitLab From 7ce53db1ff02062ba2b5808f41fa61ef2706f83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 13 May 2025 12:28:20 +0300 Subject: [PATCH 136/902] drm/i915: Indicate which pipe lied about its interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indicate which pipe signalled the spurious DE PIPE interrupt. Might help with debugging a bit if we know where the interrupt is supposedly coming from. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250513092820.18715-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index c24841f57aac4..0c9fff26653ba 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -1427,7 +1427,8 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) iir = intel_de_read(display, GEN8_DE_PIPE_IIR(pipe)); if (!iir) { drm_err_ratelimited(display->drm, - "The master control interrupt lied (DE PIPE)!\n"); + "The master control interrupt lied (DE PIPE %c)!\n", + pipe_name(pipe)); continue; } -- GitLab From 2cb38bb0add9b81f89ccdb2db88af89e99925880 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 19 May 2025 22:09:14 +0200 Subject: [PATCH 137/902] drm/xe: Allow to trigger GT resets using debugfs writes Today we allow to trigger GT resest by reading dedicated debugfs files "force_reset" and "force_reset_sync" that we are exposing using drm_info_list[] and drm_debugfs_create_files(). To avoid triggering potentially disruptive actions during otherwise "safe" read operations, expose those two attributes using debugfs function where we can specify file permissions and provide custom "write" handler to trigger the GT resets also from there. This step would allow us to drop triggering GT resets during read operations, which we leave just to give users more time to switch. Signed-off-by: Michal Wajdeczko Cc: Lucas De Marchi Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250519200914.216-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_debugfs.c | 96 +++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c index 119a55bb75800..848618acdca8d 100644 --- a/drivers/gpu/drm/xe/xe_gt_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c @@ -122,24 +122,6 @@ static int powergate_info(struct xe_gt *gt, struct drm_printer *p) return ret; } -static int force_reset(struct xe_gt *gt, struct drm_printer *p) -{ - xe_pm_runtime_get(gt_to_xe(gt)); - xe_gt_reset_async(gt); - xe_pm_runtime_put(gt_to_xe(gt)); - - return 0; -} - -static int force_reset_sync(struct xe_gt *gt, struct drm_printer *p) -{ - xe_pm_runtime_get(gt_to_xe(gt)); - xe_gt_reset(gt); - xe_pm_runtime_put(gt_to_xe(gt)); - - return 0; -} - static int sa_info(struct xe_gt *gt, struct drm_printer *p) { struct xe_tile *tile = gt_to_tile(gt); @@ -306,8 +288,6 @@ static int hwconfig(struct xe_gt *gt, struct drm_printer *p) * - without access to the PF specific data */ static const struct drm_info_list vf_safe_debugfs_list[] = { - {"force_reset", .show = xe_gt_debugfs_simple_show, .data = force_reset}, - {"force_reset_sync", .show = xe_gt_debugfs_simple_show, .data = force_reset_sync}, {"sa_info", .show = xe_gt_debugfs_simple_show, .data = sa_info}, {"topology", .show = xe_gt_debugfs_simple_show, .data = topology}, {"ggtt", .show = xe_gt_debugfs_simple_show, .data = ggtt}, @@ -332,6 +312,78 @@ static const struct drm_info_list pf_only_debugfs_list[] = { {"steering", .show = xe_gt_debugfs_simple_show, .data = steering}, }; +static ssize_t write_to_gt_call(const char __user *userbuf, size_t count, loff_t *ppos, + void (*call)(struct xe_gt *), struct xe_gt *gt) +{ + bool yes; + int ret; + + if (*ppos) + return -EINVAL; + ret = kstrtobool_from_user(userbuf, count, &yes); + if (ret < 0) + return ret; + if (yes) + call(gt); + return count; +} + +static void force_reset(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + + xe_pm_runtime_get(xe); + xe_gt_reset_async(gt); + xe_pm_runtime_put(xe); +} + +static ssize_t force_reset_write(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct xe_gt *gt = s->private; + + return write_to_gt_call(userbuf, count, ppos, force_reset, gt); +} + +static int force_reset_show(struct seq_file *s, void *unused) +{ + struct xe_gt *gt = s->private; + + force_reset(gt); /* to be deprecated! */ + return 0; +} +DEFINE_SHOW_STORE_ATTRIBUTE(force_reset); + +static void force_reset_sync(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + + xe_pm_runtime_get(xe); + xe_gt_reset(gt); + xe_pm_runtime_put(xe); +} + +static ssize_t force_reset_sync_write(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct xe_gt *gt = s->private; + + return write_to_gt_call(userbuf, count, ppos, force_reset_sync, gt); +} + +static int force_reset_sync_show(struct seq_file *s, void *unused) +{ + struct xe_gt *gt = s->private; + + force_reset_sync(gt); /* to be deprecated! */ + return 0; +} +DEFINE_SHOW_STORE_ATTRIBUTE(force_reset_sync); + void xe_gt_debugfs_register(struct xe_gt *gt) { struct xe_device *xe = gt_to_xe(gt); @@ -355,6 +407,10 @@ void xe_gt_debugfs_register(struct xe_gt *gt) */ root->d_inode->i_private = gt; + /* VF safe */ + debugfs_create_file("force_reset", 0600, root, gt, &force_reset_fops); + debugfs_create_file("force_reset_sync", 0600, root, gt, &force_reset_sync_fops); + drm_debugfs_create_files(vf_safe_debugfs_list, ARRAY_SIZE(vf_safe_debugfs_list), root, minor); -- GitLab From a6a26786f22a4ab0227bcf610510c4c9c2df0808 Mon Sep 17 00:00:00 2001 From: Jesus Narvaez Date: Wed, 14 May 2025 15:52:24 -0700 Subject: [PATCH 138/902] drm/i915/guc: Check if expecting reply before decrementing outstanding_submission_g2h When sending a H2G message where a reply is expected in guc_submission_send_busy_loop(), outstanding_submission_g2h is incremented before the send. However, if there is an error sending the message, outstanding_submission_g2h is decremented without checking if a reply is expected. Therefore, check if reply is expected when there is a failure before decrementing outstanding_submission_g2h. Fixes: 2f2cc53b5fe7 ("drm/i915/guc: Close deregister-context race against CT-loss") Signed-off-by: Jesus Narvaez Cc: Daniele Ceraolo Spurio Cc: Alan Previn Cc: Anshuman Gupta Cc: Mousumi Jana Cc: Rodrigo Vivi Cc: Matt Roper Reviewed-by: Daniele Ceraolo Spurio Signed-off-by: John Harrison Link: https://lore.kernel.org/r/20250514225224.4142684-1-jesus.narvaez@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index f8cb7c630d5b8..108331a699958 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -633,7 +633,7 @@ static int guc_submission_send_busy_loop(struct intel_guc *guc, atomic_inc(&guc->outstanding_submission_g2h); ret = intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); - if (ret) + if (ret && g2h_len_dw) atomic_dec(&guc->outstanding_submission_g2h); return ret; -- GitLab From 07cc32ecc6f393f416589f90f30542bfa7a9891d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:01 +0300 Subject: [PATCH 139/902] drm/panelreplay: Panel Replay capability DPCD register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new definition for size of Panel Replay DPCD capability registers area. Rename existing definitions to group capability registers together. Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Acked-by: Maarten Lankhorst Link: https://lore.kernel.org/r/20250526120512.1702815-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 8 ++++---- include/drm/display/drm_dp.h | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index cd833b63ea6b7..0cfdeff268f97 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -516,7 +516,7 @@ static u8 intel_dp_get_su_capability(struct intel_dp *intel_dp) if (intel_dp->psr.sink_panel_replay_su_support) drm_dp_dpcd_readb(&intel_dp->aux, - DP_PANEL_PANEL_REPLAY_CAPABILITY, + DP_PANEL_REPLAY_CAP_CAPABILITY, &su_capability); else su_capability = intel_dp->psr_dpcd[1]; @@ -528,7 +528,7 @@ static unsigned int intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp) { return intel_dp->psr.sink_panel_replay_su_support ? - DP_PANEL_PANEL_REPLAY_X_GRANULARITY : + DP_PANEL_REPLAY_CAP_X_GRANULARITY : DP_PSR2_SU_X_GRANULARITY; } @@ -536,7 +536,7 @@ static unsigned int intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp) { return intel_dp->psr.sink_panel_replay_su_support ? - DP_PANEL_PANEL_REPLAY_Y_GRANULARITY : + DP_PANEL_REPLAY_CAP_Y_GRANULARITY : DP_PSR2_SU_Y_GRANULARITY; } @@ -676,7 +676,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) { drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); - drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP, + drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT, &intel_dp->pr_dpcd); if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SUPPORT) diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 3001c0b6e7bb3..3371e2edd9e9e 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -547,16 +547,18 @@ /* DFP Capability Extension */ #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0a3 /* 2.0 */ -#define DP_PANEL_REPLAY_CAP 0x0b0 /* DP 2.0 */ +#define DP_PANEL_REPLAY_CAP_SUPPORT 0x0b0 /* DP 2.0 */ # define DP_PANEL_REPLAY_SUPPORT (1 << 0) # define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1) # define DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT (1 << 2) /* eDP 1.5 */ -#define DP_PANEL_PANEL_REPLAY_CAPABILITY 0xb1 -# define DP_PANEL_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +#define DP_PANEL_REPLAY_CAP_SIZE 7 -#define DP_PANEL_PANEL_REPLAY_X_GRANULARITY 0xb2 -#define DP_PANEL_PANEL_REPLAY_Y_GRANULARITY 0xb4 +#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 +# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) + +#define DP_PANEL_REPLAY_CAP_X_GRANULARITY 0xb2 +#define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4 /* Link Configuration */ #define DP_LINK_BW_SET 0x100 -- GitLab From 3e61b092e61d8f7f0b882f07ede9a0a553197e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:02 +0300 Subject: [PATCH 140/902] drm/dp: Add Panel Replay capability bits from DP2.1 specification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PANEL REPLAY CAPABILITY register (0xb1) bits. v3: - added DP_DSC_DECODE_CAPABILITY definitions - use defined shift instead of hardcoded value v2: comment about DP2.1 changed as DP2.1a Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Acked-by: Maarten Lankhorst Link: https://lore.kernel.org/r/20250526120512.1702815-3-jouni.hogander@intel.com --- include/drm/display/drm_dp.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 3371e2edd9e9e..811e9238a77cc 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -554,8 +554,18 @@ #define DP_PANEL_REPLAY_CAP_SIZE 7 -#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 -# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 +# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT 1 /* DP 2.1a */ +# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK (3 << DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT) +# define DP_DSC_DECODE_CAPABILITY_IN_PR_SUPPORTED 0x00 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_FULL_FRAME_ONLY 0x01 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_NOT_SUPPORTED 0x02 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_RESERVED 0x03 +# define DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR (1 << 3) +# define DP_PANEL_REPLAY_DSC_CRC_OF_MULTIPLE_SUS_SUPPORTED (1 << 4) +# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +# define DP_PANEL_REPLAY_SU_Y_GRANULARITY_EXTENDED_CAPABILITY_SUPPORTED (1 << 6) +# define DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP (1 << 7) #define DP_PANEL_REPLAY_CAP_X_GRANULARITY 0xb2 #define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4 -- GitLab From deb8d0fe88a71c53b2f3db3a17bd459ff436bbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:03 +0300 Subject: [PATCH 141/902] drm/i915/psr: Read all Panel Replay capability registers from DPCD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are several Panel Replay capability register in DPCD. Read them all for later use. v2: - avoid using hardcoded indices - read all Panel Replay capability registers Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-4-jouni.hogander@intel.com --- .../drm/i915/display/intel_display_types.h | 4 +++- drivers/gpu/drm/i915/display/intel_psr.c | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index fc1eda590da85..ed4d743fc7c54 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1669,7 +1669,9 @@ struct intel_dp { bool use_max_params; u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; - u8 pr_dpcd; + u8 pr_dpcd[DP_PANEL_REPLAY_CAP_SIZE]; +#define INTEL_PR_DPCD_INDEX(pr_dpcd_register) ((pr_dpcd_register) - DP_PANEL_REPLAY_CAP_SUPPORT) + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE]; u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 0cfdeff268f97..1072549649cdd 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -608,7 +608,8 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp) return; } - if (!(intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)) { + if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & + DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)) { drm_dbg_kms(display->drm, "Panel doesn't support early transport, eDP Panel Replay not possible\n"); return; @@ -617,7 +618,8 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp) intel_dp->psr.sink_panel_replay_support = true; - if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SU_SUPPORT) + if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & + DP_PANEL_REPLAY_SU_SUPPORT) intel_dp->psr.sink_panel_replay_su_support = true; drm_dbg_kms(display->drm, @@ -676,10 +678,12 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) { drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); - drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT, - &intel_dp->pr_dpcd); - if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SUPPORT) + drm_dp_dpcd_read(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT, + &intel_dp->pr_dpcd, sizeof(intel_dp->pr_dpcd)); + + if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & + DP_PANEL_REPLAY_SUPPORT) _panel_replay_init_dpcd(intel_dp); if (intel_dp->psr_dpcd[0]) @@ -736,7 +740,8 @@ static bool psr2_su_region_et_valid(struct intel_dp *intel_dp, bool panel_replay return false; return panel_replay ? - intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT : + intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & + DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT : intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED && psr2_su_region_et_global_enabled(intel_dp); } @@ -3916,7 +3921,8 @@ static void intel_psr_sink_capability(struct intel_dp *intel_dp, seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support)); seq_printf(m, ", Panel Replay Selective Update = %s", str_yes_no(psr->sink_panel_replay_su_support)); - if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT) + if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & + DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT) seq_printf(m, " (Early Transport)"); seq_printf(m, "\n"); } -- GitLab From 91a2cd6236f394a1abf566db6fdee2e6884b2182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:04 +0300 Subject: [PATCH 142/902] drm/i915/alpm: Add PR_ALPM_CTL register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PR_ALPM_CTL register definition and bits for it. Bspec: 71014 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-5-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr_regs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 795e6b9cc575c..aad3ac5f502ed 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -266,6 +266,16 @@ #define _PIPE_SRCSZ_ERLY_TPT_B 0x71074 #define PIPE_SRCSZ_ERLY_TPT(pipe) _MMIO_PIPE((pipe), _PIPE_SRCSZ_ERLY_TPT_A, _PIPE_SRCSZ_ERLY_TPT_B) +#define _PR_ALPM_CTL_A 0x60948 +#define PR_ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PR_ALPM_CTL_A) +#define PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU BIT(6) +#define PR_ALPM_CTL_RFB_UPDATE_CONTROL BIT(5) +#define PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE BIT(4) +#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK REG_GENMASK(1, 0) +#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 0) +#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 1) +#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 2) + #define _ALPM_CTL_A 0x60950 #define ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A) #define ALPM_CTL_ALPM_ENABLE REG_BIT(31) -- GitLab From d6a8336c5f06b4fc065963cfcf1ff4fe52640979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:05 +0300 Subject: [PATCH 143/902] drm/i915/alpm: Write PR_ALPM_CTL register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR_ALPM_CTL register contains configurations related to Adaptive sync sdp. Configure these if Adaptive Sync SDP is supported. v2: avoid using hardcoded indices Bspec: 71014 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-6-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index c176bdbc19a34..0890247085a7a 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -348,6 +348,20 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines); + if (intel_dp->as_sdp_supported) { + u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; + + if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] & + DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP) + pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; + if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] & + DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR)) + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + + intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), + pr_alpm_ctl); + } + intel_de_write(display, PORT_ALPM_CTL(port), PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | -- GitLab From e6503d10cab72ffc4419af76ad96aa10fbea08cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:06 +0300 Subject: [PATCH 144/902] drm/i915/psr: Add interface to check if AUXLess ALPM is needed by PSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we spread ugly PSR details into ALPM code to check if AUXLess ALPM is needed. Prepare to hide these details to PSR code by adding new interface for checking if AUXLess ALPM is needed. v2: remove kerneldoc comment Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-7-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_psr.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 1072549649cdd..38535e0d24965 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -4246,3 +4246,9 @@ bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_sta return intel_dp_is_edp(intel_dp) && (crtc_state->has_sel_update || crtc_state->has_panel_replay); } + +bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + return intel_dp_is_edp(intel_dp) && crtc_state->has_panel_replay; +} diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 73c3fa40844bc..0cf53184f13f9 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -77,5 +77,7 @@ int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state); void intel_psr_connector_debugfs_add(struct intel_connector *connector); void intel_psr_debugfs_register(struct intel_display *display); bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); #endif /* __INTEL_PSR_H__ */ -- GitLab From 5d9d4feb33b7d509f8e6f5558381e1e8a3304134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:07 +0300 Subject: [PATCH 145/902] drm/i915/alpm: Add new interface to check if AUXLess ALPM is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we need to know if AUXLess ALPM is used when preparing for link training. Add new interface for this and use it in existing code where possible. v2: remove kerneldoc comment Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-8-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 10 ++++++++-- drivers/gpu/drm/i915/display/intel_alpm.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 0890247085a7a..bbcf510b0c254 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -26,6 +26,13 @@ bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp) return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP; } +bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + return intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) || + (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp)); +} + void intel_alpm_init(struct intel_dp *intel_dp) { u8 dpcd; @@ -341,8 +348,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, * Panel Replay on eDP is always using ALPM aux less. I.e. no need to * check panel support at this point. */ - if ((crtc_state->has_panel_replay && intel_dp_is_edp(intel_dp)) || - (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp))) { + if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) { alpm_ctl = ALPM_CTL_ALPM_ENABLE | ALPM_CTL_ALPM_AUX_LESS_ENABLE | ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index c9fe21e3e72ce..86f4d5ab1981b 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -32,6 +32,8 @@ void intel_alpm_post_plane_update(struct intel_atomic_state *state, void intel_alpm_lobf_debugfs_add(struct intel_connector *connector); bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp); +bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_alpm_disable(struct intel_dp *intel_dp); bool intel_alpm_get_error(struct intel_dp *intel_dp); #endif -- GitLab From 6ecb8e586f8339657211e12fcba7f77bae297fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:08 +0300 Subject: [PATCH 146/902] drm/i915/alpm: Move port alpm configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is specified in Bspec where port alpm configuration is supposed to be performed. Change accordingly. v2: - drop HAS reference - ensure PORT_ALPM registers are not writen on older platform Bspec: 68849 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-9-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 48 ++++++++++++-------- drivers/gpu/drm/i915/display/intel_alpm.h | 2 + drivers/gpu/drm/i915/display/intel_cx0_phy.c | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 6 +++ 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index bbcf510b0c254..dfdde8e4eabe4 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -336,7 +336,6 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - enum port port = dp_to_dig_port(intel_dp)->base.port; u32 alpm_ctl; if (DISPLAY_VER(display) < 20 || (!intel_psr_needs_alpm(intel_dp, crtc_state) && @@ -368,23 +367,6 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, pr_alpm_ctl); } - intel_de_write(display, - PORT_ALPM_CTL(port), - PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | - PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | - PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | - PORT_ALPM_CTL_SILENCE_PERIOD( - intel_dp->alpm_parameters.silence_period_sym_clocks)); - - intel_de_write(display, - PORT_ALPM_LFPS_CTL(port), - PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) | - PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | - PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | - PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms)); } else { alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines); @@ -408,6 +390,36 @@ void intel_alpm_configure(struct intel_dp *intel_dp, intel_dp->alpm_parameters.transcoder = crtc_state->cpu_transcoder; } +void intel_alpm_port_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + enum port port = dp_to_dig_port(intel_dp)->base.port; + u32 alpm_ctl_val = 0, lfps_ctl_val = 0; + + if (DISPLAY_VER(display) < 20) + return; + + if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) { + alpm_ctl_val = PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | + PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | + PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | + PORT_ALPM_CTL_SILENCE_PERIOD( + intel_dp->alpm_parameters.silence_period_sym_clocks); + lfps_ctl_val = PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) | + PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms); + } + + intel_de_write(display, PORT_ALPM_CTL(port), alpm_ctl_val); + + intel_de_write(display, PORT_ALPM_LFPS_CTL(port), lfps_ctl_val); +} + void intel_alpm_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index 86f4d5ab1981b..a861c20b5d79f 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -27,6 +27,8 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); void intel_alpm_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); +void intel_alpm_port_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_alpm_post_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_alpm_lobf_debugfs_add(struct intel_connector *connector); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index a82b93cbc81d2..91118d115fd35 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -10,6 +10,7 @@ #include "i915_reg.h" #include "i915_utils.h" +#include "intel_alpm.h" #include "intel_cx0_phy.h" #include "intel_cx0_phy_regs.h" #include "intel_ddi.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3d47d0ed3c37b..f9653fa667b74 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3740,6 +3740,12 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp, intel_ddi_buf_enable(encoder, intel_dp->DP); intel_dp->DP |= DDI_BUF_CTL_ENABLE; + + /* + * 6.k If AUX-Less ALPM is going to be enabled + * i. Configure PORT_ALPM_CTL and PORT_ALPM_LFPS_CTL here + */ + intel_alpm_port_configure(intel_dp, crtc_state); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, -- GitLab From 7acc76a37e5d5743102784be82e6ae6dd784043c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:09 +0300 Subject: [PATCH 147/902] drm/i915/display: Add PHY_CMN1_CONTROL register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PHY_CMN1_CONTROL register and its definitions to configure port LFPS sending. Bspec: 68962 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-10-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index 59c22beaf1de5..580a43be195e6 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -285,6 +285,9 @@ #define PHY_CX0_TX_CONTROL(tx, control) (0x400 + ((tx) - 1) * 0x200 + (control)) #define CONTROL2_DISABLE_SINGLE_TX REG_BIT(6) +#define PHY_CMN1_CONTROL(tx, control) (0x800 + ((tx) - 1) * 0x200 + (control)) +#define CONTROL0_MAC_TRANSMIT_LFPS REG_BIT(1) + /* C20 Registers */ #define PHY_C20_WR_ADDRESS_L 0xC02 #define PHY_C20_WR_ADDRESS_H 0xC03 -- GitLab From 9dc619680de4ae04930e8a0df8b5c37d280a1b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:10 +0300 Subject: [PATCH 148/902] drm/i915/display: Add function to configure LFPS sending MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add function to configre LFPS sending for Panel Replay according to link training sequence in HAS document. This assumes we are using AUX Less always if it's supported by the sink and the source. v2: - drop HAS reference - replay kerneldoc comment with a generic comment - check display version in intel_lnl_mac_transmit_lfps Bspec: 68849 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-11-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 31 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_cx0_phy.h | 2 ++ drivers/gpu/drm/i915/display/intel_ddi.c | 8 ++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 91118d115fd35..75caccb65513e 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3225,6 +3225,37 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, intel_cx0pll_enable(encoder, crtc_state); } +/* + * According to HAS we need to enable MAC Transmitting LFPS in the "PHY Common + * Control 0" PIPE register in case of AUX Less ALPM is going to be used. This + * function is doing that and is called by link retrain sequence. + */ +void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); + u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); + bool enable = intel_alpm_is_alpm_aux_less(enc_to_intel_dp(encoder), + crtc_state); + int i; + + if (DISPLAY_VER(display) < 20) + return; + + for (i = 0; i < 4; i++) { + int tx = i % 2 + 1; + u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1; + + if (!(owned_lane_mask & lane_mask)) + continue; + + intel_cx0_rmw(encoder, lane_mask, PHY_CMN1_CONTROL(tx, 0), + CONTROL0_MAC_TRANSMIT_LFPS, + enable ? CONTROL0_MAC_TRANSMIT_LFPS : 0, + MB_WRITE_COMMITTED); + } +} + static u8 cx0_power_control_disable_val(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index a8f811ca5e7bc..c5a7b529955b0 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -43,5 +43,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); void intel_cx0_pll_power_save_wa(struct intel_display *display); +void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); #endif /* __INTEL_CX0_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index f9653fa667b74..4c845dd410a2a 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3742,10 +3742,16 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp, intel_dp->DP |= DDI_BUF_CTL_ENABLE; /* - * 6.k If AUX-Less ALPM is going to be enabled + * 6.k If AUX-Less ALPM is going to be enabled: * i. Configure PORT_ALPM_CTL and PORT_ALPM_LFPS_CTL here */ intel_alpm_port_configure(intel_dp, crtc_state); + + /* + * ii. Enable MAC Transmits LFPS in the "PHY Common Control 0" PIPE + * register + */ + intel_lnl_mac_transmit_lfps(encoder, crtc_state); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, -- GitLab From 8097128a40ff378761034ec72cdbf6f46e466dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:11 +0300 Subject: [PATCH 149/902] drm/i915/psr: Fix using wrong mask in REG_FIELD_PREP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrong mask is used in PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION and PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION. Fixes: 295099580f04 ("drm/i915/psr: Add missing ALPM AUX-Less register definitions") Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-12-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index aad3ac5f502ed..8afbf5a383353 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -335,8 +335,8 @@ #define PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(20, 16) #define PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) #define PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(12, 8) -#define PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) +#define PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION_MASK, val) #define PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(4, 0) -#define PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) +#define PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK, val) #endif /* __INTEL_PSR_REGS_H__ */ -- GitLab From 9856a688e4bcb753f89479642a5ea57ccc64a8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 26 May 2025 15:05:12 +0300 Subject: [PATCH 150/902] drm/i915/psr: Do not disable Panel Replay in case VRR is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow Panel Replay with VRR. All VRR modes are supposed to work with Panel Replay. Bspec: 68920, 68925 Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250526120512.1702815-13-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 38535e0d24965..db7111374293c 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1579,6 +1579,12 @@ static bool _psr_compute_config(struct intel_dp *intel_dp, if (!CAN_PSR(intel_dp)) return false; + /* + * Currently PSR doesn't work reliably with VRR enabled. + */ + if (crtc_state->vrr.enable) + return false; + entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, adjusted_mode); if (entry_setup_frames >= 0) { @@ -1696,12 +1702,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, return; } - /* - * Currently PSR/PR doesn't work reliably with VRR enabled. - */ - if (crtc_state->vrr.enable) - return; - crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp, crtc_state, conn_state); -- GitLab From 338ec84deefdaf8e479455ee7d55434571799cf0 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 16 May 2025 16:38:11 +0100 Subject: [PATCH 151/902] drm/xe/bo: optimise CCS case for WB pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dealing with CCS state is significant on LNL+, where we end up clearing the compression state on every page alloc using the blitter for user buffers, including also saving and restoring it when moving between domains, plus we need to alloc extra pages to hold the raw CCS state for the save step. However all compression PAT modes, on platforms like LNL, also require coh_none, meaning that only WC memory can use compression in the first place. With this we can be sneaky and completely ignore CCS for WB buffers, which is likely the common case anyway. This would then skip all blitter moves/clears between sys <-> tt and then also means we can drop the extra CCS pages. This should be safe since there is no way to interact with the compression state (potentially uncleared) without using a PAT enabled index (which is rejected at bind), including if trying to be malicious and copy the raw CCS state from userpace, which should give back all zeroes if the src surface (indirect) is lacking compressed PAT index. Signed-off-by: Matthew Auld Cc: Satyanarayana K V P Cc: Thomas Hellström Cc: Matthew Brost Reviewed-by: José Roberto de Souza Reviewed-by: Satyanarayana K V P Link: https://lore.kernel.org/r/20250516153810.223530-2-matthew.auld@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 8 ++++++++ drivers/gpu/drm/xe/xe_pat.c | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index d99d91fe8aa98..3fafdcb8d95be 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2982,6 +2982,14 @@ bool xe_bo_needs_ccs_pages(struct xe_bo *bo) if (IS_DGFX(xe) && (bo->flags & XE_BO_FLAG_SYSTEM)) return false; + /* + * Compression implies coh_none, therefore we know for sure that WB + * memory can't currently use compression, which is likely one of the + * common cases. + */ + if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB) + return false; + return true; } diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 30fdbdb9341e8..38a6a49c1b2a7 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -103,7 +103,8 @@ static const struct xe_pat_table_entry xelpg_pat_table[] = { * * Note: There is an implicit assumption in the driver that compression and * coh_1way+ are mutually exclusive. If this is ever not true then userptr - * and imported dma-buf from external device will have uncleared ccs state. + * and imported dma-buf from external device will have uncleared ccs state. See + * also xe_bo_needs_ccs_pages(). */ #define XE2_PAT(no_promote, comp_en, l3clos, l3_policy, l4_policy, __coh_mode) \ { \ -- GitLab From 96af397aa1a2d1032a6e28ff3f4bc0ab4be40e1d Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 14 May 2025 16:24:25 +0100 Subject: [PATCH 152/902] drm/xe/vm: move rebind_work init earlier In xe_vm_close_and_put() we need to be able to call flush_work(rebind_work), however during vm creation we can call this on the error path, before having actually set up the worker, leading to a splat from flush_work(). It looks like we can simply move the worker init step earlier to fix this. Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Signed-off-by: Matthew Auld Cc: Matthew Brost Cc: # v6.8+ Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250514152424.149591-3-matthew.auld@intel.com --- drivers/gpu/drm/xe/xe_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 5a978da411b03..168756fb140b2 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1704,8 +1704,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) * scheduler drops all the references of it, hence protecting the VM * for this case is necessary. */ - if (flags & XE_VM_FLAG_LR_MODE) + if (flags & XE_VM_FLAG_LR_MODE) { + INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); xe_pm_runtime_get_noresume(xe); + } vm_resv_obj = drm_gpuvm_resv_object_alloc(&xe->drm); if (!vm_resv_obj) { @@ -1750,10 +1752,8 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) vm->batch_invalidate_tlb = true; } - if (vm->flags & XE_VM_FLAG_LR_MODE) { - INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); + if (vm->flags & XE_VM_FLAG_LR_MODE) vm->batch_invalidate_tlb = false; - } /* Fill pt_root after allocating scratch tables */ for_each_tile(tile, xe, id) { -- GitLab From 4f296d77cf49fcb5f90b4674123ad7f3a0676165 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 14 May 2025 16:24:26 +0100 Subject: [PATCH 153/902] drm/xe/vm: move xe_svm_init() earlier In xe_vm_close_and_put() we need to be able to call xe_svm_fini(), however during vm creation we can call this on the error path, before having actually initialised the svm state, leading to various splats followed by a fatal NPD. Fixes: 6fd979c2f331 ("drm/xe: Add SVM init / close / fini to faulting VMs") Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4967 Signed-off-by: Matthew Auld Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250514152424.149591-4-matthew.auld@intel.com --- drivers/gpu/drm/xe/xe_vm.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 168756fb140b2..7140d8856bad0 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1709,10 +1709,16 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) xe_pm_runtime_get_noresume(xe); } + if (flags & XE_VM_FLAG_FAULT_MODE) { + err = xe_svm_init(vm); + if (err) + goto err_no_resv; + } + vm_resv_obj = drm_gpuvm_resv_object_alloc(&xe->drm); if (!vm_resv_obj) { err = -ENOMEM; - goto err_no_resv; + goto err_svm_fini; } drm_gpuvm_init(&vm->gpuvm, "Xe VM", DRM_GPUVM_RESV_PROTECTED, &xe->drm, @@ -1783,12 +1789,6 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) } } - if (flags & XE_VM_FLAG_FAULT_MODE) { - err = xe_svm_init(vm); - if (err) - goto err_close; - } - if (number_tiles > 1) vm->composite_fence_ctx = dma_fence_context_alloc(1); @@ -1802,6 +1802,11 @@ err_close: xe_vm_close_and_put(vm); return ERR_PTR(err); +err_svm_fini: + if (flags & XE_VM_FLAG_FAULT_MODE) { + vm->size = 0; /* close the vm */ + xe_svm_fini(vm); + } err_no_resv: mutex_destroy(&vm->snap_mutex); for_each_tile(tile, xe, id) -- GitLab From fbeaad071a98fef87deccee81d564de1c8e8e16d Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Wed, 28 May 2025 22:20:32 -0700 Subject: [PATCH 154/902] drm/xe: Create LRC BO without VM Specifying VM during lrc->bo creation requires VM's reference to be held for the lifetime of lrc->bo as it will use VM's dma reservation object. Using VM's dma reservation object for lrc->bo doesn't provide any advantage. Hence do not pass VM while creating lrc->bo. v2: Use xe_bo_unpin_map_no_vm (Matthew Brost) Fixes: 264eecdba211 ("drm/xe: Decouple xe_exec_queue and xe_lrc") Signed-off-by: Niranjana Vishwanathapura Reviewed-by: Matthew Brost Reviewed-by: Maarten Lankhorst Signed-off-by: Matthew Brost Link: https://lore.kernel.org/r/20250529052031.2429120-2-niranjana.vishwanathapura@intel.com --- drivers/gpu/drm/xe/xe_exec_queue.c | 9 --------- drivers/gpu/drm/xe/xe_lrc.c | 23 ++++------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index ce78cee5dec68..32c6923df7c37 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -132,12 +132,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) flags |= XE_LRC_CREATE_RUNALONE; } - if (vm) { - err = xe_vm_lock(vm, true); - if (err) - return err; - } - for (i = 0; i < q->width; ++i) { q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags); if (IS_ERR(q->lrc[i])) { @@ -146,9 +140,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) } } - if (vm) - xe_vm_unlock(vm); - err = q->ops->init(q); if (err) goto err_lrc; diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 61a2e87990a9d..63d74e27f54cf 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -909,10 +909,7 @@ static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) static void xe_lrc_finish(struct xe_lrc *lrc) { xe_hw_fence_ctx_finish(&lrc->fence_ctx); - xe_bo_lock(lrc->bo, false); - xe_bo_unpin(lrc->bo); - xe_bo_unlock(lrc->bo); - xe_bo_put(lrc->bo); + xe_bo_unpin_map_no_vm(lrc->bo); xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo); } @@ -1007,7 +1004,7 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, * FIXME: Perma-pinning LRC as we don't yet support moving GGTT address * via VM bind calls. */ - lrc->bo = xe_bo_create_pin_map(xe, tile, vm, lrc_size, + lrc->bo = xe_bo_create_pin_map(xe, tile, NULL, lrc_size, ttm_bo_type_kernel, bo_flags); if (IS_ERR(lrc->bo)) @@ -1795,9 +1792,6 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) if (!snapshot) return NULL; - if (lrc->bo->vm) - xe_vm_get(lrc->bo->vm); - snapshot->context_desc = xe_lrc_ggtt_addr(lrc); snapshot->ring_addr = __xe_lrc_ring_ggtt_addr(lrc); snapshot->indirect_context_desc = xe_lrc_indirect_ring_ggtt_addr(lrc); @@ -1819,14 +1813,12 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot) { struct xe_bo *bo; - struct xe_vm *vm; struct iosys_map src; if (!snapshot) return; bo = snapshot->lrc_bo; - vm = bo->vm; snapshot->lrc_bo = NULL; snapshot->lrc_snapshot = kvmalloc(snapshot->lrc_size, GFP_KERNEL); @@ -1846,8 +1838,6 @@ void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot) xe_bo_unlock(bo); put_bo: xe_bo_put(bo); - if (vm) - xe_vm_put(vm); } void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p) @@ -1900,14 +1890,9 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) return; kvfree(snapshot->lrc_snapshot); - if (snapshot->lrc_bo) { - struct xe_vm *vm; - - vm = snapshot->lrc_bo->vm; + if (snapshot->lrc_bo) xe_bo_put(snapshot->lrc_bo); - if (vm) - xe_vm_put(vm); - } + kfree(snapshot); } -- GitLab From 241cc827c0987d7173714fc5a95a7c8fc9bf15c0 Mon Sep 17 00:00:00 2001 From: Balasubramani Vivekanandan Date: Tue, 20 May 2025 19:54:45 +0530 Subject: [PATCH 155/902] drm/xe/mocs: Initialize MOCS index early MOCS uc_index is used even before it is initialized in the following callstack guc_prepare_xfer() __xe_guc_upload() xe_guc_min_load_for_hwconfig() xe_uc_init_hwconfig() xe_gt_init_hwconfig() Do MOCS index initialization earlier in the device probe. Signed-off-by: Balasubramani Vivekanandan Reviewed-by: Ravi Kumar Vodapalli Link: https://lore.kernel.org/r/20250520142445.2792824-1-balasubramani.vivekanandan@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 0e5d243c94517..858b5398c01b7 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -417,6 +417,8 @@ int xe_gt_init_early(struct xe_gt *gt) if (err) return err; + xe_mocs_init_early(gt); + return 0; } @@ -634,8 +636,6 @@ int xe_gt_init(struct xe_gt *gt) if (err) return err; - xe_mocs_init_early(gt); - err = xe_gt_sysfs_init(gt); if (err) return err; -- GitLab From f36a75aba1c3176d177964bca76f86a075d2943a Mon Sep 17 00:00:00 2001 From: Jesus Narvaez Date: Wed, 28 May 2025 16:05:51 -0700 Subject: [PATCH 156/902] drm/i915/guc: Handle race condition where wakeref count drops below 0 There is a rare race condition when preparing for a reset where guc_lrc_desc_unpin() could be in the process of deregistering a context while a different thread is scrubbing outstanding contexts and it alters the context state and does a wakeref put. Then, if there is a failure with deregister_context(), a second wakeref put could occur. As a result the wakeref count could drop below 0 and fail an INTEL_WAKEREF_BUG_ON() check. Therefore if there is a failure with deregister_context(), undo the context state changes and do a wakeref put only if the context was set to be destroyed earlier. v2: Expand comment to better explain change. (Daniele) v3: Removed addition to the original comment. (Daniele) Fixes: 2f2cc53b5fe7 ("drm/i915/guc: Close deregister-context race against CT-loss") Signed-off-by: Jesus Narvaez Cc: Daniele Ceraolo Spurio Cc: Alan Previn Cc: Anshuman Gupta Cc: Mousumi Jana Cc: Rodrigo Vivi Cc: Matt Roper Reviewed-by: Daniele Ceraolo Spurio Signed-off-by: John Harrison Link: https://lore.kernel.org/r/20250528230551.1855177-1-jesus.narvaez@intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 108331a699958..127316d2c8aa9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3443,18 +3443,29 @@ static inline int guc_lrc_desc_unpin(struct intel_context *ce) * GuC is active, lets destroy this context, but at this point we can still be racing * with suspend, so we undo everything if the H2G fails in deregister_context so * that GuC reset will find this context during clean up. + * + * There is a race condition where the reset code could have altered + * this context's state and done a wakeref put before we try to + * deregister it here. So check if the context is still set to be + * destroyed before undoing earlier changes, to avoid two wakeref puts + * on the same context. */ ret = deregister_context(ce, ce->guc_id.id); if (ret) { + bool pending_destroyed; spin_lock_irqsave(&ce->guc_state.lock, flags); - set_context_registered(ce); - clr_context_destroyed(ce); + pending_destroyed = context_destroyed(ce); + if (pending_destroyed) { + set_context_registered(ce); + clr_context_destroyed(ce); + } spin_unlock_irqrestore(&ce->guc_state.lock, flags); /* * As gt-pm is awake at function entry, intel_wakeref_put_async merely decrements * the wakeref immediately but per function spec usage call this after unlock. */ - intel_wakeref_put_async(>->wakeref); + if (pending_destroyed) + intel_wakeref_put_async(>->wakeref); } return ret; -- GitLab From 1a524e8b488eabd3cb3f32bc0e124f702c3a57ef Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Thu, 29 May 2025 09:43:38 -0700 Subject: [PATCH 157/902] drm/xe: Do not warn on SVM migration failing because of 64k requirements On platforms which only support 64k VRAM pages, it is expected that 4k faults will not migrate. Do not warn on this, rather print a debug message. Signed-off-by: Matthew Brost Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250529164338.1745515-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 871ac81bb04aa..f27fb9b588de1 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -821,7 +821,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm } if (preferred_region_is_vram && range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { - drm_warn(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); + drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); return false; } -- GitLab From d201a9797b39e580842613238c620a2a1694ceef Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 14:48:54 +0300 Subject: [PATCH 158/902] drm/i915: drop intel_dpio_phy.h include from VLV IOSF SB vlv_iosf_sb.c no longer depends on enum dpio_phy from intel_dpio_phy.h. Drop the include. Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250527114854.3687469-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index f4b435555f3bd..f4b3869331414 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -8,8 +8,6 @@ #include "i915_reg.h" #include "vlv_iosf_sb.h" -#include "display/intel_dpio_phy.h" - /* * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and * VLV_VLV2_PUNIT_HAS_0.8.docx -- GitLab From 7596d839f6228757fe17a810da2d1c5f3305078c Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:53 +0530 Subject: [PATCH 159/902] drm/xe/hwmon: Add support to manage power limits though mailbox Add support to manage power limits using pcode mailbox commands for supported platforms. v2: - Address review comments. (Badal) - Use mailbox commands instead of registers to manage power limits for BMG. - Clamp the maximum power limit to GPU firmware default value. v3: - Clamp power limit in write also for platforms with mailbox support. v4: - Remove unnecessary debug prints. (Badal) v5: - Update description of variable pl1_on_boot to fix kernel-doc error. v6: - Improve commit message, refer to BIOS as GPU firmware. - Change macro READ_PL_FROM_BIOS to READ_PL_FROM_FW. - Rectify drm_warn to drm_info. Signed-off-by: Karthik Poosa Fixes: e90f7a58e659 ("drm/xe/hwmon: Add HWMON support for BMG") Reviewed-by: Badal Nilawar Link: https://lore.kernel.org/r/20250529163458.2354509-2-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/regs/xe_mchbar_regs.h | 10 +- drivers/gpu/drm/xe/regs/xe_pcode_regs.h | 4 - drivers/gpu/drm/xe/xe_device_types.h | 4 + drivers/gpu/drm/xe/xe_hwmon.c | 380 +++++++++++++++++------ drivers/gpu/drm/xe/xe_pci.c | 5 + drivers/gpu/drm/xe/xe_pcode.c | 11 + drivers/gpu/drm/xe/xe_pcode.h | 3 + drivers/gpu/drm/xe/xe_pcode_api.h | 7 + 8 files changed, 318 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h b/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h index f5e5234857c19..5394a1373a6bb 100644 --- a/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h @@ -38,10 +38,10 @@ #define TEMP_MASK REG_GENMASK(7, 0) #define PCU_CR_PACKAGE_RAPL_LIMIT XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x59a0) -#define PKG_PWR_LIM_1 REG_GENMASK(14, 0) -#define PKG_PWR_LIM_1_EN REG_BIT(15) -#define PKG_PWR_LIM_1_TIME REG_GENMASK(23, 17) -#define PKG_PWR_LIM_1_TIME_X REG_GENMASK(23, 22) -#define PKG_PWR_LIM_1_TIME_Y REG_GENMASK(21, 17) +#define PWR_LIM_VAL REG_GENMASK(14, 0) +#define PWR_LIM_EN REG_BIT(15) +#define PWR_LIM_TIME REG_GENMASK(23, 17) +#define PWR_LIM_TIME_X REG_GENMASK(23, 22) +#define PWR_LIM_TIME_Y REG_GENMASK(21, 17) #endif /* _XE_MCHBAR_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index c7d5d782e3f95..c556a04670eef 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -18,16 +18,12 @@ #define PVC_GT0_PLATFORM_ENERGY_STATUS XE_REG(0x28106c) #define PVC_GT0_PACKAGE_POWER_SKU XE_REG(0x281080) -#define BMG_PACKAGE_POWER_SKU XE_REG(0x138098) -#define BMG_PACKAGE_POWER_SKU_UNIT XE_REG(0x1380dc) #define BMG_PACKAGE_ENERGY_STATUS XE_REG(0x138120) #define BMG_FAN_1_SPEED XE_REG(0x138140) #define BMG_FAN_2_SPEED XE_REG(0x138170) #define BMG_FAN_3_SPEED XE_REG(0x1381a0) #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) -#define BMG_PACKAGE_RAPL_LIMIT XE_REG(0x138440) #define BMG_PLATFORM_ENERGY_STATUS XE_REG(0x138458) -#define BMG_PLATFORM_POWER_LIMIT XE_REG(0x138460) #endif /* _XE_PCODE_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index f81be293b260e..043515f8c068b 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -326,6 +326,10 @@ struct xe_device { u8 has_heci_gscfi:1; /** @info.has_llc: Device has a shared CPU+GPU last level cache */ u8 has_llc:1; + /** @info.has_mbx_power_limits: Device has support to manage power limits using + * pcode mailbox commands. + */ + u8 has_mbx_power_limits:1; /** @info.has_pxp: Device has PXP support */ u8 has_pxp:1; /** @info.has_range_tlb_invalidation: Has range based TLB invalidations */ diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index eb293aec36a0f..e272128f51451 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -51,6 +51,14 @@ enum xe_fan_channel { FAN_MAX, }; +/* + * For platforms that support mailbox commands for power limits, REG_PKG_POWER_SKU_UNIT is + * not supported and below are SKU units to be used. + */ +#define PWR_UNIT 0x3 +#define ENERGY_UNIT 0xe +#define TIME_UNIT 0xa + /* * SF_* - scale factors for particular quantities according to hwmon spec. */ @@ -60,6 +68,18 @@ enum xe_fan_channel { #define SF_ENERGY 1000000 /* microjoules */ #define SF_TIME 1000 /* milliseconds */ +/* + * PL*_HWMON_ATTR - mapping of hardware power limits to corresponding hwmon power attribute. + */ +#define PL1_HWMON_ATTR hwmon_power_max + +#define PWR_ATTR_TO_STR(attr) (((attr) == hwmon_power_max) ? "PL1" : "Invalid") + +/* + * Timeout for power limit write mailbox command. + */ +#define PL_WRITE_MBX_TIMEOUT_MS (1) + /** * struct xe_hwmon_energy_info - to accumulate energy */ @@ -100,8 +120,80 @@ struct xe_hwmon { struct xe_hwmon_energy_info ei[CHANNEL_MAX]; /** @fi: Fan info for fanN_input */ struct xe_hwmon_fan_info fi[FAN_MAX]; + /** @boot_power_limit_read: is boot power limits read */ + bool boot_power_limit_read; + /** @pl1_on_boot: power limit PL1 on boot */ + u32 pl1_on_boot[CHANNEL_MAX]; }; +static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, + u32 *uval) +{ + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); + u32 val0 = 0, val1 = 0; + int ret = 0; + + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_POWER_SETUP, + (channel == CHANNEL_CARD) ? + READ_PSYSGPU_POWER_LIMIT : + READ_PACKAGE_POWER_LIMIT, + hwmon->boot_power_limit_read ? + READ_PL_FROM_PCODE : READ_PL_FROM_FW), + &val0, &val1); + + if (ret) { + drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", + channel, val0, val1, ret); + *uval = 0; + return ret; + } + + /* return the value only if limit is enabled */ + if (attr == PL1_HWMON_ATTR) + *uval = (val0 & PWR_LIM_EN) ? val0 : 0; + else if (attr == hwmon_power_label) + *uval = (val0 & PWR_LIM_EN) ? 1 : 0; + else + *uval = 0; + + return ret; +} + +static int xe_hwmon_pcode_write_power_limit(const struct xe_hwmon *hwmon, u32 attr, u8 channel, + u32 uval) +{ + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); + u32 val0, val1; + int ret = 0; + + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_POWER_SETUP, + (channel == CHANNEL_CARD) ? + READ_PSYSGPU_POWER_LIMIT : + READ_PACKAGE_POWER_LIMIT, + hwmon->boot_power_limit_read ? + READ_PL_FROM_PCODE : READ_PL_FROM_FW), + &val0, &val1); + + if (ret) + drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", + channel, val0, val1, ret); + + if (attr == PL1_HWMON_ATTR) + val0 = uval; + else + return -EIO; + + ret = xe_pcode_write64_timeout(root_tile, PCODE_MBOX(PCODE_POWER_SETUP, + (channel == CHANNEL_CARD) ? + WRITE_PSYSGPU_POWER_LIMIT : + WRITE_PACKAGE_POWER_LIMIT, 0), + val0, val1, PL_WRITE_MBX_TIMEOUT_MS); + if (ret) + drm_dbg(&hwmon->xe->drm, "write failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", + channel, val0, val1, ret); + return ret; +} + static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon_reg, int channel) { @@ -122,29 +214,19 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg } break; case REG_PKG_RAPL_LIMIT: - if (xe->info.platform == XE_BATTLEMAGE) { - if (channel == CHANNEL_PKG) - return BMG_PACKAGE_RAPL_LIMIT; - else - return BMG_PLATFORM_POWER_LIMIT; - } else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { + if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) return PVC_GT0_PACKAGE_RAPL_LIMIT; - } else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) { + else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) return PCU_CR_PACKAGE_RAPL_LIMIT; - } break; case REG_PKG_POWER_SKU: - if (xe->info.platform == XE_BATTLEMAGE) - return BMG_PACKAGE_POWER_SKU; - else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) + if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) return PVC_GT0_PACKAGE_POWER_SKU; else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) return PCU_CR_PACKAGE_POWER_SKU; break; case REG_PKG_POWER_SKU_UNIT: - if (xe->info.platform == XE_BATTLEMAGE) - return BMG_PACKAGE_POWER_SKU_UNIT; - else if (xe->info.platform == XE_PVC) + if (xe->info.platform == XE_PVC) return PVC_GT0_PACKAGE_POWER_SKU_UNIT; else if (xe->info.platform == XE_DG2) return PCU_CR_PACKAGE_POWER_SKU_UNIT; @@ -181,7 +263,7 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return XE_REG(0); } -#define PL1_DISABLE 0 +#define PL_DISABLE 0 /* * HW allows arbitrary PL1 limits to be set but silently clamps these values to @@ -189,67 +271,83 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg * same pattern for sysfs, allow arbitrary PL1 limits to be set but display * clamped values when read. */ -static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *value) +static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *value) { u64 reg_val, min, max; struct xe_device *xe = hwmon->xe; struct xe_reg rapl_limit, pkg_power_sku; struct xe_mmio *mmio = xe_root_tile_mmio(xe); - rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); - pkg_power_sku = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + mutex_lock(&hwmon->hwmon_lock); - /* - * Valid check of REG_PKG_RAPL_LIMIT is already done in xe_hwmon_power_is_visible. - * So not checking it again here. - */ - if (!xe_reg_is_valid(pkg_power_sku)) { - drm_warn(&xe->drm, "pkg_power_sku invalid\n"); - *value = 0; - return; + if (hwmon->xe->info.has_mbx_power_limits) { + xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, (u32 *)®_val); + } else { + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + pkg_power_sku = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + + /* + * Valid check of REG_PKG_RAPL_LIMIT is already done in xe_hwmon_power_is_visible. + * So not checking it again here. + */ + if (!xe_reg_is_valid(pkg_power_sku)) { + drm_warn(&xe->drm, "pkg_power_sku invalid\n"); + *value = 0; + goto unlock; + } + reg_val = xe_mmio_read32(mmio, rapl_limit); } - mutex_lock(&hwmon->hwmon_lock); - - reg_val = xe_mmio_read32(mmio, rapl_limit); - /* Check if PL1 limit is disabled */ - if (!(reg_val & PKG_PWR_LIM_1_EN)) { - *value = PL1_DISABLE; + /* Check if PL limits are disabled. */ + if (!(reg_val & PWR_LIM_EN)) { + *value = PL_DISABLE; + drm_info(&hwmon->xe->drm, "%s disabled for channel %d, val 0x%016llx\n", + PWR_ATTR_TO_STR(attr), channel, reg_val); goto unlock; } - reg_val = REG_FIELD_GET(PKG_PWR_LIM_1, reg_val); + reg_val = REG_FIELD_GET(PWR_LIM_VAL, reg_val); *value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); - reg_val = xe_mmio_read64_2x32(mmio, pkg_power_sku); - min = REG_FIELD_GET(PKG_MIN_PWR, reg_val); - min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power); - max = REG_FIELD_GET(PKG_MAX_PWR, reg_val); - max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power); - - if (min && max) - *value = clamp_t(u64, *value, min, max); + /* For platforms with mailbox power limit support clamping would be done by pcode. */ + if (!hwmon->xe->info.has_mbx_power_limits) { + reg_val = xe_mmio_read64_2x32(mmio, pkg_power_sku); + min = REG_FIELD_GET(PKG_MIN_PWR, reg_val); + max = REG_FIELD_GET(PKG_MAX_PWR, reg_val); + min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power); + max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power); + if (min && max) + *value = clamp_t(u64, *value, min, max); + } unlock: mutex_unlock(&hwmon->hwmon_lock); } -static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long value) +static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channel, long value) { struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); int ret = 0; - u64 reg_val; + u32 reg_val; struct xe_reg rapl_limit; + mutex_lock(&hwmon->hwmon_lock); + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); - mutex_lock(&hwmon->hwmon_lock); + /* Disable Power Limit and verify, as limit cannot be disabled on all platforms. */ + if (value == PL_DISABLE) { + if (hwmon->xe->info.has_mbx_power_limits) { + drm_dbg(&hwmon->xe->drm, "disabling %s on channel %d\n", + PWR_ATTR_TO_STR(attr), channel); + xe_hwmon_pcode_write_power_limit(hwmon, attr, channel, 0); + xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, ®_val); + } else { + reg_val = xe_mmio_rmw32(mmio, rapl_limit, PWR_LIM_EN, 0); + reg_val = xe_mmio_read32(mmio, rapl_limit); + } - /* Disable PL1 limit and verify, as limit cannot be disabled on all platforms */ - if (value == PL1_DISABLE) { - reg_val = xe_mmio_rmw32(mmio, rapl_limit, PKG_PWR_LIM_1_EN, 0); - reg_val = xe_mmio_read32(mmio, rapl_limit); - if (reg_val & PKG_PWR_LIM_1_EN) { - drm_warn(&hwmon->xe->drm, "PL1 disable is not supported!\n"); + if (reg_val & PWR_LIM_EN) { + drm_warn(&hwmon->xe->drm, "Power limit disable is not supported!\n"); ret = -EOPNOTSUPP; } goto unlock; @@ -257,26 +355,50 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va /* Computation in 64-bits to avoid overflow. Round to nearest. */ reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER); - reg_val = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, reg_val); - reg_val = xe_mmio_rmw32(mmio, rapl_limit, PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val); + reg_val = PWR_LIM_EN | REG_FIELD_PREP(PWR_LIM_VAL, reg_val); + /* + * Clamp power limit to card-firmware default as maximum, as an additional protection to + * pcode clamp. + */ + if (hwmon->xe->info.has_mbx_power_limits) { + if (reg_val > REG_FIELD_GET(PWR_LIM_VAL, hwmon->pl1_on_boot[channel])) { + reg_val = REG_FIELD_GET(PWR_LIM_VAL, hwmon->pl1_on_boot[channel]); + drm_dbg(&hwmon->xe->drm, "Clamping power limit to firmware default 0x%x\n", + reg_val); + } + } + + if (hwmon->xe->info.has_mbx_power_limits) + ret = xe_hwmon_pcode_write_power_limit(hwmon, attr, channel, reg_val); + else + reg_val = xe_mmio_rmw32(mmio, rapl_limit, PWR_LIM_EN | PWR_LIM_VAL, + reg_val); unlock: mutex_unlock(&hwmon->hwmon_lock); return ret; } -static void xe_hwmon_power_rated_max_read(struct xe_hwmon *hwmon, int channel, long *value) +static void xe_hwmon_power_rated_max_read(struct xe_hwmon *hwmon, u32 attr, int channel, + long *value) { struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); - struct xe_reg reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); - u64 reg_val; + u32 reg_val; + + if (hwmon->xe->info.has_mbx_power_limits) { + /* PL1 is rated max if supported. */ + xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, channel, ®_val); + } else { + /* + * This sysfs file won't be visible if REG_PKG_POWER_SKU is invalid, so valid check + * for this register can be skipped. + * See xe_hwmon_power_is_visible. + */ + struct xe_reg reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + + reg_val = xe_mmio_read32(mmio, reg); + } - /* - * This sysfs file won't be visible if REG_PKG_POWER_SKU is invalid, so valid check - * for this register can be skipped. - * See xe_hwmon_power_is_visible. - */ - reg_val = xe_mmio_read32(mmio, reg); reg_val = REG_FIELD_GET(PKG_TDP, reg_val); *value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); } @@ -330,23 +452,35 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); u32 x, y, x_w = 2; /* 2 bits */ u64 r, tau4, out; - int sensor_index = to_sensor_dev_attr(attr)->index; + int channel = to_sensor_dev_attr(attr)->index; + u32 power_attr = PL1_HWMON_ATTR; + int ret = 0; xe_pm_runtime_get(hwmon->xe); mutex_lock(&hwmon->hwmon_lock); - r = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index)); + if (hwmon->xe->info.has_mbx_power_limits) { + ret = xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, (u32 *)&r); + if (ret) { + drm_err(&hwmon->xe->drm, + "power interval read fail, ch %d, attr %d, r 0%llx, ret %d\n", + channel, power_attr, r, ret); + r = 0; + } + } else { + r = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel)); + } mutex_unlock(&hwmon->hwmon_lock); xe_pm_runtime_put(hwmon->xe); - x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r); - y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r); + x = REG_FIELD_GET(PWR_LIM_TIME_X, r); + y = REG_FIELD_GET(PWR_LIM_TIME_Y, r); /* - * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17) + * tau = (1 + (x / 4)) * power(2,y), x = bits(23:22), y = bits(21:17) * = (4 | x) << (y - 2) * * Here (y - 2) ensures a 1.x fixed point representation of 1.x @@ -373,14 +507,15 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a u64 tau4, r, max_win; unsigned long val; int ret; - int sensor_index = to_sensor_dev_attr(attr)->index; + int channel = to_sensor_dev_attr(attr)->index; + u32 power_attr = PL1_HWMON_ATTR; ret = kstrtoul(buf, 0, &val); if (ret) return ret; /* - * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12. + * Max HW supported tau in '(1 + (x / 4)) * power(2,y)' format, x = 0, y = 0x12. * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds. * * The ideal scenario is for PKG_MAX_WIN to be read from the PKG_PWR_SKU register. @@ -400,11 +535,13 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a tau4 = (u64)((1 << x_w) | x) << y; max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); - if (val > max_win) + if (val > max_win) { + drm_warn(&hwmon->xe->drm, "power_interval invalid val 0x%lx\n", val); return -EINVAL; + } /* val in hw units */ - val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME); + val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME) + 1; /* * Convert val to 1.x * power(2,y) @@ -419,14 +556,21 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a x = (val - (1ul << y)) << x_w >> y; } - rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y); + rxy = REG_FIELD_PREP(PWR_LIM_TIME_X, x) | + REG_FIELD_PREP(PWR_LIM_TIME_Y, y); xe_pm_runtime_get(hwmon->xe); mutex_lock(&hwmon->hwmon_lock); - r = xe_mmio_rmw32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index), - PKG_PWR_LIM_1_TIME, rxy); + if (hwmon->xe->info.has_mbx_power_limits) { + ret = xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, (u32 *)&r); + r = (r & ~PWR_LIM_TIME) | rxy; + xe_hwmon_pcode_write_power_limit(hwmon, power_attr, channel, r); + } else { + r = xe_mmio_rmw32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel), + PWR_LIM_TIME, rxy); + } mutex_unlock(&hwmon->hwmon_lock); @@ -435,6 +579,7 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a return count; } +/* PSYS PL1 */ static SENSOR_DEVICE_ATTR(power1_max_interval, 0664, xe_hwmon_power_max_interval_show, xe_hwmon_power_max_interval_store, CHANNEL_CARD); @@ -455,10 +600,19 @@ static umode_t xe_hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct xe_hwmon *hwmon = dev_get_drvdata(dev); int ret = 0; + int channel = index ? CHANNEL_PKG : CHANNEL_CARD; + u32 power_attr = PL1_HWMON_ATTR; + u32 uval; xe_pm_runtime_get(hwmon->xe); - ret = xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, index)) ? attr->mode : 0; + if (hwmon->xe->info.has_mbx_power_limits) { + xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, &uval); + ret = (uval & PWR_LIM_EN) ? attr->mode : 0; + } else { + ret = xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, + channel)) ? attr->mode : 0; + } xe_pm_runtime_put(hwmon->xe); @@ -604,19 +758,27 @@ xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) switch (attr) { case hwmon_power_max: - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, + if (hwmon->xe->info.has_mbx_power_limits) { + xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, &uval); + return (uval) ? 0664 : 0; + } else { + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel)) ? 0664 : 0; + } case hwmon_power_rated_max: - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, - channel)) ? 0444 : 0; + if (hwmon->xe->info.has_mbx_power_limits) + return 0; + else + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, + channel)) ? 0444 : 0; case hwmon_power_crit: - if (channel == CHANNEL_PKG) - return (xe_hwmon_pcode_read_i1(hwmon, &uval) || - !(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644; - break; case hwmon_power_label: - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, - channel)) ? 0444 : 0; + if (channel == CHANNEL_PKG) { + xe_hwmon_pcode_read_i1(hwmon, &uval); + return (uval & POWER_SETUP_I1_WATTS) ? (attr == hwmon_power_label) ? + 0444 : 0644 : 0; + } + break; default: return 0; } @@ -628,10 +790,10 @@ xe_hwmon_power_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) { switch (attr) { case hwmon_power_max: - xe_hwmon_power_max_read(hwmon, channel, val); + xe_hwmon_power_max_read(hwmon, attr, channel, val); return 0; case hwmon_power_rated_max: - xe_hwmon_power_rated_max_read(hwmon, channel, val); + xe_hwmon_power_rated_max_read(hwmon, attr, channel, val); return 0; case hwmon_power_crit: return xe_hwmon_power_curr_crit_read(hwmon, channel, val, SF_POWER); @@ -645,7 +807,7 @@ xe_hwmon_power_write(struct xe_hwmon *hwmon, u32 attr, int channel, long val) { switch (attr) { case hwmon_power_max: - return xe_hwmon_power_max_write(hwmon, channel, val); + return xe_hwmon_power_max_write(hwmon, attr, channel, val); case hwmon_power_crit: return xe_hwmon_power_curr_crit_write(hwmon, channel, val, SF_POWER); default: @@ -965,18 +1127,42 @@ xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) int channel; struct xe_reg pkg_power_sku_unit; - /* - * The contents of register PKG_POWER_SKU_UNIT do not change, - * so read it once and store the shift values. - */ - pkg_power_sku_unit = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0); - if (xe_reg_is_valid(pkg_power_sku_unit)) { - val_sku_unit = xe_mmio_read32(mmio, pkg_power_sku_unit); - hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); - hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit); - hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); + if (hwmon->xe->info.has_mbx_power_limits) { + /* Check if card firmware support mailbox power limits commands. */ + if (xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_CARD, + &hwmon->pl1_on_boot[CHANNEL_CARD]) | + xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_PKG, + &hwmon->pl1_on_boot[CHANNEL_PKG])) { + drm_warn(&hwmon->xe->drm, + "Failed to read power limits, check card firmware !\n"); + } else { + drm_info(&hwmon->xe->drm, "Using mailbox commands for power limits\n"); + /* Write default limits to read from pcode from now on. */ + xe_hwmon_pcode_write_power_limit(hwmon, PL1_HWMON_ATTR, + CHANNEL_CARD, + hwmon->pl1_on_boot[CHANNEL_CARD]); + xe_hwmon_pcode_write_power_limit(hwmon, PL1_HWMON_ATTR, + CHANNEL_PKG, + hwmon->pl1_on_boot[CHANNEL_PKG]); + hwmon->scl_shift_power = PWR_UNIT; + hwmon->scl_shift_energy = ENERGY_UNIT; + hwmon->scl_shift_time = TIME_UNIT; + hwmon->boot_power_limit_read = true; + } + } else { + drm_info(&hwmon->xe->drm, "Using register for power limits\n"); + /* + * The contents of register PKG_POWER_SKU_UNIT do not change, + * so read it once and store the shift values. + */ + pkg_power_sku_unit = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0); + if (xe_reg_is_valid(pkg_power_sku_unit)) { + val_sku_unit = xe_mmio_read32(mmio, pkg_power_sku_unit); + hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); + hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit); + hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); + } } - /* * Initialize 'struct xe_hwmon_energy_info', i.e. set fields to the * first value of the energy register read diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 024175cfe61e6..ac4beaed58ffb 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -66,6 +66,7 @@ struct xe_device_desc { u8 has_heci_gscfi:1; u8 has_heci_cscfi:1; u8 has_llc:1; + u8 has_mbx_power_limits:1; u8 has_pxp:1; u8 has_sriov:1; u8 needs_scratch:1; @@ -306,6 +307,7 @@ static const struct xe_device_desc dg2_desc = { DG2_FEATURES, .has_display = true, .has_fan_control = true, + .has_mbx_power_limits = false, }; static const __maybe_unused struct xe_device_desc pvc_desc = { @@ -317,6 +319,7 @@ static const __maybe_unused struct xe_device_desc pvc_desc = { .has_heci_gscfi = 1, .max_remote_tiles = 1, .require_force_probe = true, + .has_mbx_power_limits = false, }; static const struct xe_device_desc mtl_desc = { @@ -342,6 +345,7 @@ static const struct xe_device_desc bmg_desc = { .dma_mask_size = 46, .has_display = true, .has_fan_control = true, + .has_mbx_power_limits = true, .has_heci_cscfi = 1, .needs_scratch = true, }; @@ -584,6 +588,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.dma_mask_size = desc->dma_mask_size; xe->info.is_dgfx = desc->is_dgfx; xe->info.has_fan_control = desc->has_fan_control; + xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; xe->info.has_llc = desc->has_llc; diff --git a/drivers/gpu/drm/xe/xe_pcode.c b/drivers/gpu/drm/xe/xe_pcode.c index cf955b3ed52cd..9189117fe825b 100644 --- a/drivers/gpu/drm/xe/xe_pcode.c +++ b/drivers/gpu/drm/xe/xe_pcode.c @@ -109,6 +109,17 @@ int xe_pcode_write_timeout(struct xe_tile *tile, u32 mbox, u32 data, int timeout return err; } +int xe_pcode_write64_timeout(struct xe_tile *tile, u32 mbox, u32 data0, u32 data1, int timeout) +{ + int err; + + mutex_lock(&tile->pcode.lock); + err = pcode_mailbox_rw(tile, mbox, &data0, &data1, timeout, false, false); + mutex_unlock(&tile->pcode.lock); + + return err; +} + int xe_pcode_read(struct xe_tile *tile, u32 mbox, u32 *val, u32 *val1) { int err; diff --git a/drivers/gpu/drm/xe/xe_pcode.h b/drivers/gpu/drm/xe/xe_pcode.h index ba33991d72a76..de38f44f32014 100644 --- a/drivers/gpu/drm/xe/xe_pcode.h +++ b/drivers/gpu/drm/xe/xe_pcode.h @@ -18,6 +18,9 @@ int xe_pcode_init_min_freq_table(struct xe_tile *tile, u32 min_gt_freq, int xe_pcode_read(struct xe_tile *tile, u32 mbox, u32 *val, u32 *val1); int xe_pcode_write_timeout(struct xe_tile *tile, u32 mbox, u32 val, int timeout_ms); +int xe_pcode_write64_timeout(struct xe_tile *tile, u32 mbox, u32 data0, + u32 data1, int timeout); + #define xe_pcode_write(tile, mbox, val) \ xe_pcode_write_timeout(tile, mbox, val, 1) diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index 127d4d26c4cfd..0befdea77db15 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -43,6 +43,13 @@ #define POWER_SETUP_I1_SHIFT 6 /* 10.6 fixed point format */ #define POWER_SETUP_I1_DATA_MASK REG_GENMASK(15, 0) +#define READ_PSYSGPU_POWER_LIMIT 0x6 +#define WRITE_PSYSGPU_POWER_LIMIT 0x7 +#define READ_PACKAGE_POWER_LIMIT 0x8 +#define WRITE_PACKAGE_POWER_LIMIT 0x9 +#define READ_PL_FROM_FW 0x1 +#define READ_PL_FROM_PCODE 0x0 + #define PCODE_FREQUENCY_CONFIG 0x6e /* Frequency Config Sub Commands (param1) */ #define PCODE_MBOX_FC_SC_READ_FUSED_P0 0x0 -- GitLab From 25e963a09e059ffdb15c09cc79cfded855b43668 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:54 +0530 Subject: [PATCH 160/902] drm/xe/hwmon: Move card reactive critical power under channel card Move power2/curr2_crit to channel 1 i.e power1/curr1_crit as this represents the entire card critical power/current. v2: Update the date of curr1_crit also in hwmon documentation. Signed-off-by: Karthik Poosa Fixes: 345dadc4f68b ("drm/xe/hwmon: Add infra to support card power and energy attributes") Reviewed-by: Badal Nilawar Link: https://lore.kernel.org/r/20250529163458.2354509-3-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- .../ABI/testing/sysfs-driver-intel-xe-hwmon | 20 +++++++++---------- drivers/gpu/drm/xe/xe_hwmon.c | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon index 4ca917ac6382d..5a91dcccd3ac3 100644 --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon @@ -60,26 +60,26 @@ Description: RO. Package default power limit (default TDP setting). Only supported for particular Intel Xe graphics platforms. -What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power2_crit -Date: February 2024 -KernelVersion: 6.8 +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power1_crit +Date: May 2025 +KernelVersion: 6.15 Contact: intel-xe@lists.freedesktop.org -Description: RW. Package reactive critical (I1) power limit in microwatts. +Description: RW. Card reactive critical (I1) power limit in microwatts. - Package reactive critical (I1) power limit in microwatts is exposed + Card reactive critical (I1) power limit in microwatts is exposed for client products. The power controller will throttle the operating frequency if the power averaged over a window exceeds this limit. Only supported for particular Intel Xe graphics platforms. -What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/curr2_crit -Date: February 2024 -KernelVersion: 6.8 +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/curr1_crit +Date: May 2025 +KernelVersion: 6.15 Contact: intel-xe@lists.freedesktop.org -Description: RW. Package reactive critical (I1) power limit in milliamperes. +Description: RW. Card reactive critical (I1) power limit in milliamperes. - Package reactive critical (I1) power limit in milliamperes is + Card reactive critical (I1) power limit in milliamperes is exposed for server products. The power controller will throttle the operating frequency if the power averaged over a window exceeds this limit. diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index e272128f51451..74f31639b37f9 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -632,8 +632,8 @@ static const struct attribute_group *hwmon_groups[] = { static const struct hwmon_channel_info * const hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL), - HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL, - HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT | HWMON_P_LABEL), + HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CRIT, + HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL), HWMON_CHANNEL_INFO(curr, HWMON_C_LABEL, HWMON_C_CRIT | HWMON_C_LABEL), HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL), HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT | HWMON_E_LABEL, HWMON_E_INPUT | HWMON_E_LABEL), @@ -773,7 +773,7 @@ xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) channel)) ? 0444 : 0; case hwmon_power_crit: case hwmon_power_label: - if (channel == CHANNEL_PKG) { + if (channel == CHANNEL_CARD) { xe_hwmon_pcode_read_i1(hwmon, &uval); return (uval & POWER_SETUP_I1_WATTS) ? (attr == hwmon_power_label) ? 0444 : 0644 : 0; -- GitLab From c713b9a23c73f6ce9c0197369668f216ed0e04c9 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:55 +0530 Subject: [PATCH 161/902] drm/xe/hwmon: Add support to manage PL2 though mailbox Add support to manage power limit PL2 (burst limit) through pcode mailbox commands. v2: - Update power1_cap definition in hwmon documentation. (Badal) - Clamp PL2 power limit to GPU firmware default value. v3: - Activate the power label when either the PL1 or PL2 power limit is enabled. v4: - Update description of pl2_on_boot variable to fix kernel-doc error. v5: - Remove unnecessary drm_warn. - Rectify powerX_label permission to read-only on platforms without mailbox power limits support. - Expose powerX_cap entries only on platforms with mailbox support. v6: - Improve commit message, refer to BIOS as GPU firmware. - Refer to card firmware as GPU firmware in code. - Remove unnecessary drm_dbg. - Print supported and unsupported power limits. (Rodrigo) - Enable powerN_cap/max_xxx entries only when power limits supported in GPU firmware. Signed-off-by: Karthik Poosa Reviewed-by: Badal Nilawar Link: https://lore.kernel.org/r/20250529163458.2354509-4-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- .../ABI/testing/sysfs-driver-intel-xe-hwmon | 30 +++++ drivers/gpu/drm/xe/xe_hwmon.c | 112 ++++++++++++------ 2 files changed, 109 insertions(+), 33 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon index 5a91dcccd3ac3..dffd6443664ad 100644 --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon @@ -148,3 +148,33 @@ Contact: intel-xe@lists.freedesktop.org Description: RO. Fan 3 speed in RPM. Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power1_cap +Date: May 2025 +KernelVersion: 6.15 +Contact: intel-xe@lists.freedesktop.org +Description: RW. Card burst (PL2) power limit in microwatts. + + The power controller will throttle the operating frequency + if the power averaged over a window (typically milli seconds) + exceeds this limit. A read value of 0 means that the PL2 + power limit is disabled, writing 0 disables the limit. + PL2 is greater than PL1 and its time window is lesser + compared to PL1. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power2_cap +Date: May 2025 +KernelVersion: 6.15 +Contact: intel-xe@lists.freedesktop.org +Description: RW. Package burst (PL2) power limit in microwatts. + + The power controller will throttle the operating frequency + if the power averaged over a window (typically milli seconds) + exceeds this limit. A read value of 0 means that the PL2 + power limit is disabled, writing 0 disables the limit. + PL2 is greater than PL1 and its time window is lesser + compared to PL1. + + Only supported for particular Intel Xe graphics platforms. diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 74f31639b37f9..7a5837199492a 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -51,6 +51,14 @@ enum xe_fan_channel { FAN_MAX, }; +/* Attribute index for powerX_xxx_interval sysfs entries */ +enum sensor_attr_power { + SENSOR_INDEX_PSYS_PL1, + SENSOR_INDEX_PKG_PL1, + SENSOR_INDEX_PSYS_PL2, + SENSOR_INDEX_PKG_PL2, +}; + /* * For platforms that support mailbox commands for power limits, REG_PKG_POWER_SKU_UNIT is * not supported and below are SKU units to be used. @@ -72,8 +80,9 @@ enum xe_fan_channel { * PL*_HWMON_ATTR - mapping of hardware power limits to corresponding hwmon power attribute. */ #define PL1_HWMON_ATTR hwmon_power_max +#define PL2_HWMON_ATTR hwmon_power_cap -#define PWR_ATTR_TO_STR(attr) (((attr) == hwmon_power_max) ? "PL1" : "Invalid") +#define PWR_ATTR_TO_STR(attr) (((attr) == hwmon_power_max) ? "PL1" : "PL2") /* * Timeout for power limit write mailbox command. @@ -124,6 +133,9 @@ struct xe_hwmon { bool boot_power_limit_read; /** @pl1_on_boot: power limit PL1 on boot */ u32 pl1_on_boot[CHANNEL_MAX]; + /** @pl2_on_boot: power limit PL2 on boot */ + u32 pl2_on_boot[CHANNEL_MAX]; + }; static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, @@ -151,8 +163,10 @@ static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 att /* return the value only if limit is enabled */ if (attr == PL1_HWMON_ATTR) *uval = (val0 & PWR_LIM_EN) ? val0 : 0; + else if (attr == PL2_HWMON_ATTR) + *uval = (val1 & PWR_LIM_EN) ? val1 : 0; else if (attr == hwmon_power_label) - *uval = (val0 & PWR_LIM_EN) ? 1 : 0; + *uval = (val0 & PWR_LIM_EN) ? 1 : (val1 & PWR_LIM_EN) ? 1 : 0; else *uval = 0; @@ -180,6 +194,8 @@ static int xe_hwmon_pcode_write_power_limit(const struct xe_hwmon *hwmon, u32 at if (attr == PL1_HWMON_ATTR) val0 = uval; + else if (attr == PL2_HWMON_ATTR) + val1 = uval; else return -EIO; @@ -273,7 +289,7 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg */ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *value) { - u64 reg_val, min, max; + u64 reg_val = 0, min, max; struct xe_device *xe = hwmon->xe; struct xe_reg rapl_limit, pkg_power_sku; struct xe_mmio *mmio = xe_root_tile_mmio(xe); @@ -327,7 +343,7 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe { struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); int ret = 0; - u32 reg_val; + u32 reg_val, max; struct xe_reg rapl_limit; mutex_lock(&hwmon->hwmon_lock); @@ -355,20 +371,25 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe /* Computation in 64-bits to avoid overflow. Round to nearest. */ reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER); - reg_val = PWR_LIM_EN | REG_FIELD_PREP(PWR_LIM_VAL, reg_val); /* - * Clamp power limit to card-firmware default as maximum, as an additional protection to + * Clamp power limit to GPU firmware default as maximum, as an additional protection to * pcode clamp. */ if (hwmon->xe->info.has_mbx_power_limits) { - if (reg_val > REG_FIELD_GET(PWR_LIM_VAL, hwmon->pl1_on_boot[channel])) { - reg_val = REG_FIELD_GET(PWR_LIM_VAL, hwmon->pl1_on_boot[channel]); - drm_dbg(&hwmon->xe->drm, "Clamping power limit to firmware default 0x%x\n", + max = (attr == PL1_HWMON_ATTR) ? + hwmon->pl1_on_boot[channel] : hwmon->pl2_on_boot[channel]; + max = REG_FIELD_PREP(PWR_LIM_VAL, max); + if (reg_val > max) { + reg_val = max; + drm_dbg(&hwmon->xe->drm, + "Clamping power limit to GPU firmware default 0x%x\n", reg_val); } } + reg_val = PWR_LIM_EN | REG_FIELD_PREP(PWR_LIM_VAL, reg_val); + if (hwmon->xe->info.has_mbx_power_limits) ret = xe_hwmon_pcode_write_power_limit(hwmon, attr, channel, reg_val); else @@ -452,8 +473,9 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); u32 x, y, x_w = 2; /* 2 bits */ u64 r, tau4, out; - int channel = to_sensor_dev_attr(attr)->index; + int channel = (to_sensor_dev_attr(attr)->index % 2) ? CHANNEL_PKG : CHANNEL_CARD; u32 power_attr = PL1_HWMON_ATTR; + int ret = 0; xe_pm_runtime_get(hwmon->xe); @@ -506,9 +528,9 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a u32 x, y, rxy, x_w = 2; /* 2 bits */ u64 tau4, r, max_win; unsigned long val; - int ret; - int channel = to_sensor_dev_attr(attr)->index; + int channel = (to_sensor_dev_attr(attr)->index % 2) ? CHANNEL_PKG : CHANNEL_CARD; u32 power_attr = PL1_HWMON_ATTR; + int ret; ret = kstrtoul(buf, 0, &val); if (ret) @@ -535,10 +557,8 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a tau4 = (u64)((1 << x_w) | x) << y; max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); - if (val > max_win) { - drm_warn(&hwmon->xe->drm, "power_interval invalid val 0x%lx\n", val); + if (val > max_win) return -EINVAL; - } /* val in hw units */ val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME) + 1; @@ -582,11 +602,11 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a /* PSYS PL1 */ static SENSOR_DEVICE_ATTR(power1_max_interval, 0664, xe_hwmon_power_max_interval_show, - xe_hwmon_power_max_interval_store, CHANNEL_CARD); - + xe_hwmon_power_max_interval_store, SENSOR_INDEX_PSYS_PL1); +/* PKG PL1 */ static SENSOR_DEVICE_ATTR(power2_max_interval, 0664, xe_hwmon_power_max_interval_show, - xe_hwmon_power_max_interval_store, CHANNEL_PKG); + xe_hwmon_power_max_interval_store, SENSOR_INDEX_PKG_PL1); static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_power1_max_interval.dev_attr.attr, @@ -600,7 +620,7 @@ static umode_t xe_hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct xe_hwmon *hwmon = dev_get_drvdata(dev); int ret = 0; - int channel = index ? CHANNEL_PKG : CHANNEL_CARD; + int channel = (index % 2) ? CHANNEL_PKG : CHANNEL_CARD; u32 power_attr = PL1_HWMON_ATTR; u32 uval; @@ -609,7 +629,7 @@ static umode_t xe_hwmon_attributes_visible(struct kobject *kobj, if (hwmon->xe->info.has_mbx_power_limits) { xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, &uval); ret = (uval & PWR_LIM_EN) ? attr->mode : 0; - } else { + } else if (power_attr != PL2_HWMON_ATTR) { ret = xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel)) ? attr->mode : 0; } @@ -632,8 +652,9 @@ static const struct attribute_group *hwmon_groups[] = { static const struct hwmon_channel_info * const hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL), - HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CRIT, - HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL), + HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CRIT | + HWMON_P_CAP, + HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CAP), HWMON_CHANNEL_INFO(curr, HWMON_C_LABEL, HWMON_C_CRIT | HWMON_C_LABEL), HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL), HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT | HWMON_E_LABEL, HWMON_E_INPUT | HWMON_E_LABEL), @@ -754,17 +775,32 @@ xe_hwmon_temp_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) static umode_t xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) { - u32 uval; + u32 uval = 0; + struct xe_reg rapl_limit; + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); switch (attr) { case hwmon_power_max: + case hwmon_power_cap: + case hwmon_power_label: if (hwmon->xe->info.has_mbx_power_limits) { xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, &uval); - return (uval) ? 0664 : 0; - } else { - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, - channel)) ? 0664 : 0; + } else if (attr != PL2_HWMON_ATTR) { + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + if (xe_reg_is_valid(rapl_limit)) + uval = xe_mmio_read32(mmio, rapl_limit); + } + if (uval & PWR_LIM_EN) { + if (attr == hwmon_power_label) + return 0444; + + drm_info(&hwmon->xe->drm, "%s is supported on channel %d\n", + PWR_ATTR_TO_STR(attr), channel); + return 0664; } + drm_dbg(&hwmon->xe->drm, "%s is unsupported on channel %d\n", + PWR_ATTR_TO_STR(attr), channel); + return 0; case hwmon_power_rated_max: if (hwmon->xe->info.has_mbx_power_limits) return 0; @@ -772,11 +808,9 @@ xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel)) ? 0444 : 0; case hwmon_power_crit: - case hwmon_power_label: if (channel == CHANNEL_CARD) { xe_hwmon_pcode_read_i1(hwmon, &uval); - return (uval & POWER_SETUP_I1_WATTS) ? (attr == hwmon_power_label) ? - 0444 : 0644 : 0; + return (uval & POWER_SETUP_I1_WATTS) ? 0644 : 0; } break; default: @@ -790,6 +824,7 @@ xe_hwmon_power_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) { switch (attr) { case hwmon_power_max: + case hwmon_power_cap: xe_hwmon_power_max_read(hwmon, attr, channel, val); return 0; case hwmon_power_rated_max: @@ -806,6 +841,7 @@ static int xe_hwmon_power_write(struct xe_hwmon *hwmon, u32 attr, int channel, long val) { switch (attr) { + case hwmon_power_cap: case hwmon_power_max: return xe_hwmon_power_max_write(hwmon, attr, channel, val); case hwmon_power_crit: @@ -1128,13 +1164,17 @@ xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) struct xe_reg pkg_power_sku_unit; if (hwmon->xe->info.has_mbx_power_limits) { - /* Check if card firmware support mailbox power limits commands. */ + /* Check if GPU firmware support mailbox power limits commands. */ if (xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_CARD, &hwmon->pl1_on_boot[CHANNEL_CARD]) | xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_PKG, - &hwmon->pl1_on_boot[CHANNEL_PKG])) { + &hwmon->pl1_on_boot[CHANNEL_PKG]) | + xe_hwmon_pcode_read_power_limit(hwmon, PL2_HWMON_ATTR, CHANNEL_CARD, + &hwmon->pl2_on_boot[CHANNEL_CARD]) | + xe_hwmon_pcode_read_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_PKG, + &hwmon->pl2_on_boot[CHANNEL_PKG])) { drm_warn(&hwmon->xe->drm, - "Failed to read power limits, check card firmware !\n"); + "Failed to read power limits, check GPU firmware !\n"); } else { drm_info(&hwmon->xe->drm, "Using mailbox commands for power limits\n"); /* Write default limits to read from pcode from now on. */ @@ -1144,6 +1184,12 @@ xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) xe_hwmon_pcode_write_power_limit(hwmon, PL1_HWMON_ATTR, CHANNEL_PKG, hwmon->pl1_on_boot[CHANNEL_PKG]); + xe_hwmon_pcode_write_power_limit(hwmon, PL2_HWMON_ATTR, + CHANNEL_CARD, + hwmon->pl2_on_boot[CHANNEL_CARD]); + xe_hwmon_pcode_write_power_limit(hwmon, PL2_HWMON_ATTR, + CHANNEL_PKG, + hwmon->pl2_on_boot[CHANNEL_PKG]); hwmon->scl_shift_power = PWR_UNIT; hwmon->scl_shift_energy = ENERGY_UNIT; hwmon->scl_shift_time = TIME_UNIT; -- GitLab From 719d8a59595287557352893478f0c4e0df32b107 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:56 +0530 Subject: [PATCH 162/902] drm/xe/hwmon: Expose powerX_cap_interval Expose powerX_cap_interval to manage burst power limit time window. Signed-off-by: Karthik Poosa Reviewed-by: Badal Nilawar Link: https://lore.kernel.org/r/20250529163458.2354509-5-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- .../ABI/testing/sysfs-driver-intel-xe-hwmon | 18 ++++++++++++++++++ drivers/gpu/drm/xe/xe_hwmon.c | 16 +++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon index dffd6443664ad..d9e2b17c68720 100644 --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon @@ -178,3 +178,21 @@ Description: RW. Package burst (PL2) power limit in microwatts. compared to PL1. Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power1_cap_interval +Date: May 2025 +KernelVersion: 6.15 +Contact: intel-xe@lists.freedesktop.org +Description: RW. Card burst power limit interval (Tau in PL2/Tau) in + milliseconds over which sustained power is averaged. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/power2_cap_interval +Date: May 2025 +KernelVersion: 6.15 +Contact: intel-xe@lists.freedesktop.org +Description: RW. Package burst power limit interval (Tau in PL2/Tau) in + milliseconds over which sustained power is averaged. + + Only supported for particular Intel Xe graphics platforms. diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 7a5837199492a..f07592aba2266 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -474,7 +474,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at u32 x, y, x_w = 2; /* 2 bits */ u64 r, tau4, out; int channel = (to_sensor_dev_attr(attr)->index % 2) ? CHANNEL_PKG : CHANNEL_CARD; - u32 power_attr = PL1_HWMON_ATTR; + u32 power_attr = (to_sensor_dev_attr(attr)->index > 1) ? PL2_HWMON_ATTR : PL1_HWMON_ATTR; int ret = 0; @@ -529,7 +529,7 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a u64 tau4, r, max_win; unsigned long val; int channel = (to_sensor_dev_attr(attr)->index % 2) ? CHANNEL_PKG : CHANNEL_CARD; - u32 power_attr = PL1_HWMON_ATTR; + u32 power_attr = (to_sensor_dev_attr(attr)->index > 1) ? PL2_HWMON_ATTR : PL1_HWMON_ATTR; int ret; ret = kstrtoul(buf, 0, &val); @@ -607,10 +607,20 @@ static SENSOR_DEVICE_ATTR(power1_max_interval, 0664, static SENSOR_DEVICE_ATTR(power2_max_interval, 0664, xe_hwmon_power_max_interval_show, xe_hwmon_power_max_interval_store, SENSOR_INDEX_PKG_PL1); +/* PSYS PL2 */ +static SENSOR_DEVICE_ATTR(power1_cap_interval, 0664, + xe_hwmon_power_max_interval_show, + xe_hwmon_power_max_interval_store, SENSOR_INDEX_PSYS_PL2); +/* PKG PL2 */ +static SENSOR_DEVICE_ATTR(power2_cap_interval, 0664, + xe_hwmon_power_max_interval_show, + xe_hwmon_power_max_interval_store, SENSOR_INDEX_PKG_PL2); static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_power1_max_interval.dev_attr.attr, &sensor_dev_attr_power2_max_interval.dev_attr.attr, + &sensor_dev_attr_power1_cap_interval.dev_attr.attr, + &sensor_dev_attr_power2_cap_interval.dev_attr.attr, NULL }; @@ -621,7 +631,7 @@ static umode_t xe_hwmon_attributes_visible(struct kobject *kobj, struct xe_hwmon *hwmon = dev_get_drvdata(dev); int ret = 0; int channel = (index % 2) ? CHANNEL_PKG : CHANNEL_CARD; - u32 power_attr = PL1_HWMON_ATTR; + u32 power_attr = (index > 1) ? PL2_HWMON_ATTR : PL1_HWMON_ATTR; u32 uval; xe_pm_runtime_get(hwmon->xe); -- GitLab From 0c5405d3aa4ad871837bb1261f4128de09680c83 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:57 +0530 Subject: [PATCH 163/902] drm/xe/hwmon: Read energy status from PMT Read card and package energy status using pmt apis instead of xe_mmio for supported platforms. Enable Battlemage to read energy from PMT. v2: - Remove unused has_pmt_energy field. (Badal) - Use GENMASK to extract energy data. (Badal) v3: - Move PMT energy register offset and GENMASK to xe_pmt.h - Address review comments. (Jani) v4: - Remove unnecessary debug print. (Badal) v5: - Resolve an unused variable warning. - Add a return value check. Signed-off-by: Karthik Poosa Reviewed-by: Badal Nilawar Link: https://lore.kernel.org/r/20250529163458.2354509-6-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/regs/xe_pcode_regs.h | 2 - drivers/gpu/drm/xe/regs/xe_pmt.h | 5 +++ drivers/gpu/drm/xe/xe_hwmon.c | 49 +++++++++++++++++++------ drivers/gpu/drm/xe/xe_vsec.c | 4 +- drivers/gpu/drm/xe/xe_vsec.h | 4 ++ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index c556a04670eef..fb097607b86ca 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -18,12 +18,10 @@ #define PVC_GT0_PLATFORM_ENERGY_STATUS XE_REG(0x28106c) #define PVC_GT0_PACKAGE_POWER_SKU XE_REG(0x281080) -#define BMG_PACKAGE_ENERGY_STATUS XE_REG(0x138120) #define BMG_FAN_1_SPEED XE_REG(0x138140) #define BMG_FAN_2_SPEED XE_REG(0x138170) #define BMG_FAN_3_SPEED XE_REG(0x1381a0) #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) -#define BMG_PLATFORM_ENERGY_STATUS XE_REG(0x138458) #endif /* _XE_PCODE_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/regs/xe_pmt.h b/drivers/gpu/drm/xe/regs/xe_pmt.h index f45abcd96ba8a..b0efd9b48d1e0 100644 --- a/drivers/gpu/drm/xe/regs/xe_pmt.h +++ b/drivers/gpu/drm/xe/regs/xe_pmt.h @@ -10,6 +10,11 @@ #define BMG_PMT_BASE_OFFSET 0xDB000 #define BMG_DISCOVERY_OFFSET (SOC_BASE + BMG_PMT_BASE_OFFSET) +#define PUNIT_TELEMETRY_GUID XE_REG(BMG_DISCOVERY_OFFSET + 0x4) +#define BMG_ENERGY_STATUS_PMT_OFFSET (0x30) +#define ENERGY_PKG REG_GENMASK64(31, 0) +#define ENERGY_CARD REG_GENMASK64(63, 32) + #define BMG_TELEMETRY_BASE_OFFSET 0xE0000 #define BMG_TELEMETRY_OFFSET (SOC_BASE + BMG_TELEMETRY_BASE_OFFSET) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index f07592aba2266..c57c613471c32 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -20,6 +20,8 @@ #include "xe_pcode_api.h" #include "xe_sriov.h" #include "xe_pm.h" +#include "xe_vsec.h" +#include "regs/xe_pmt.h" enum xe_hwmon_reg { REG_TEMP, @@ -252,12 +254,7 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return GT_PERF_STATUS; break; case REG_PKG_ENERGY_STATUS: - if (xe->info.platform == XE_BATTLEMAGE) { - if (channel == CHANNEL_PKG) - return BMG_PACKAGE_ENERGY_STATUS; - else - return BMG_PLATFORM_ENERGY_STATUS; - } else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { + if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { return PVC_GT0_PLATFORM_ENERGY_STATUS; } else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) { return PCU_CR_PACKAGE_ENERGY_STATUS; @@ -450,9 +447,32 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy) struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); struct xe_hwmon_energy_info *ei = &hwmon->ei[channel]; u64 reg_val; + int ret = 0; + + /* Energy is supported only for card and pkg */ + if (channel > CHANNEL_PKG) { + *energy = 0; + return; + } - reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, - channel)); + if (hwmon->xe->info.platform == XE_BATTLEMAGE) { + ret = xe_pmt_telem_read(to_pci_dev(hwmon->xe->drm.dev), + xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID), + ®_val, BMG_ENERGY_STATUS_PMT_OFFSET, sizeof(reg_val)); + if (ret != sizeof(reg_val)) { + drm_warn(&hwmon->xe->drm, "energy read from pmt failed, ret %d\n", ret); + *energy = 0; + return; + } + + if (channel == CHANNEL_PKG) + reg_val = REG_FIELD_GET64(ENERGY_PKG, reg_val); + else + reg_val = REG_FIELD_GET64(ENERGY_CARD, reg_val); + } else { + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, + channel)); + } if (reg_val >= ei->reg_val_prev) ei->accum_energy += reg_val - ei->reg_val_prev; @@ -934,11 +954,18 @@ xe_hwmon_in_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) static umode_t xe_hwmon_energy_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) { + long energy = 0; + switch (attr) { case hwmon_energy_input: case hwmon_energy_label: - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, - channel)) ? 0444 : 0; + if (hwmon->xe->info.platform == XE_BATTLEMAGE) { + xe_hwmon_energy_get(hwmon, channel, &energy); + return energy ? 0444 : 0; + } else { + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, + channel)) ? 0444 : 0; + } default: return 0; } @@ -1283,4 +1310,4 @@ int xe_hwmon_register(struct xe_device *xe) return 0; } - +MODULE_IMPORT_NS("INTEL_PMT_TELEMETRY"); diff --git a/drivers/gpu/drm/xe/xe_vsec.c b/drivers/gpu/drm/xe/xe_vsec.c index b378848d3b7bc..3e573b0b7ebd8 100644 --- a/drivers/gpu/drm/xe/xe_vsec.c +++ b/drivers/gpu/drm/xe/xe_vsec.c @@ -149,8 +149,8 @@ static int xe_guid_decode(u32 guid, int *index, u32 *offset) return 0; } -static int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset, - u32 count) +int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset, + u32 count) { struct xe_device *xe = pdev_to_xe_device(pdev); void __iomem *telem_addr = xe->mmio.regs + BMG_TELEMETRY_OFFSET; diff --git a/drivers/gpu/drm/xe/xe_vsec.h b/drivers/gpu/drm/xe/xe_vsec.h index 5777c53faec2a..dabfb4e02d707 100644 --- a/drivers/gpu/drm/xe/xe_vsec.h +++ b/drivers/gpu/drm/xe/xe_vsec.h @@ -4,8 +4,12 @@ #ifndef _XE_VSEC_H_ #define _XE_VSEC_H_ +#include + +struct pci_dev; struct xe_device; void xe_vsec_init(struct xe_device *xe); +int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset, u32 count); #endif -- GitLab From 48a1126836cc3b7e63c31730dcd34df0d82176cd Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 29 May 2025 22:04:58 +0530 Subject: [PATCH 164/902] drm/xe/hwmon: Expose power sysfs entries based on firmware support Enable hwmon sysfs entries (power_xxx) only when GPU firmware supports it. Previously, these entries were created if the MMIO register was present. Now, we enable based on the data in the register. v2: Remove a unnecessary comment. (Rodrigo) Signed-off-by: Karthik Poosa Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250529163458.2354509-7-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hwmon.c | 63 ++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index c57c613471c32..778354c91f598 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -298,16 +298,6 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channe } else { rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); pkg_power_sku = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); - - /* - * Valid check of REG_PKG_RAPL_LIMIT is already done in xe_hwmon_power_is_visible. - * So not checking it again here. - */ - if (!xe_reg_is_valid(pkg_power_sku)) { - drm_warn(&xe->drm, "pkg_power_sku invalid\n"); - *value = 0; - goto unlock; - } reg_val = xe_mmio_read32(mmio, rapl_limit); } @@ -652,17 +642,20 @@ static umode_t xe_hwmon_attributes_visible(struct kobject *kobj, int ret = 0; int channel = (index % 2) ? CHANNEL_PKG : CHANNEL_CARD; u32 power_attr = (index > 1) ? PL2_HWMON_ATTR : PL1_HWMON_ATTR; - u32 uval; + u32 uval = 0; + struct xe_reg rapl_limit; + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); xe_pm_runtime_get(hwmon->xe); if (hwmon->xe->info.has_mbx_power_limits) { xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, &uval); - ret = (uval & PWR_LIM_EN) ? attr->mode : 0; } else if (power_attr != PL2_HWMON_ATTR) { - ret = xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, - channel)) ? attr->mode : 0; + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + if (xe_reg_is_valid(rapl_limit)) + uval = xe_mmio_read32(mmio, rapl_limit); } + ret = (uval & PWR_LIM_EN) ? attr->mode : 0; xe_pm_runtime_put(hwmon->xe); @@ -806,24 +799,20 @@ static umode_t xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) { u32 uval = 0; - struct xe_reg rapl_limit; + struct xe_reg reg; struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); switch (attr) { case hwmon_power_max: case hwmon_power_cap: - case hwmon_power_label: if (hwmon->xe->info.has_mbx_power_limits) { xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, &uval); } else if (attr != PL2_HWMON_ATTR) { - rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); - if (xe_reg_is_valid(rapl_limit)) - uval = xe_mmio_read32(mmio, rapl_limit); + reg = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + if (xe_reg_is_valid(reg)) + uval = xe_mmio_read32(mmio, reg); } if (uval & PWR_LIM_EN) { - if (attr == hwmon_power_label) - return 0444; - drm_info(&hwmon->xe->drm, "%s is supported on channel %d\n", PWR_ATTR_TO_STR(attr), channel); return 0664; @@ -832,17 +821,39 @@ xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) PWR_ATTR_TO_STR(attr), channel); return 0; case hwmon_power_rated_max: - if (hwmon->xe->info.has_mbx_power_limits) + if (hwmon->xe->info.has_mbx_power_limits) { return 0; - else - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, - channel)) ? 0444 : 0; + } else { + reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + if (xe_reg_is_valid(reg)) + uval = xe_mmio_read32(mmio, reg); + return uval ? 0444 : 0; + } case hwmon_power_crit: if (channel == CHANNEL_CARD) { xe_hwmon_pcode_read_i1(hwmon, &uval); return (uval & POWER_SETUP_I1_WATTS) ? 0644 : 0; } break; + case hwmon_power_label: + if (hwmon->xe->info.has_mbx_power_limits) { + xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, &uval); + } else { + reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + if (xe_reg_is_valid(reg)) + uval = xe_mmio_read32(mmio, reg); + + if (!uval) { + reg = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + if (xe_reg_is_valid(reg)) + uval = xe_mmio_read32(mmio, reg); + } + } + if ((!(uval & PWR_LIM_EN)) && channel == CHANNEL_CARD) { + xe_hwmon_pcode_read_i1(hwmon, &uval); + return (uval & POWER_SETUP_I1_WATTS) ? 0444 : 0; + } + return (uval) ? 0444 : 0; default: return 0; } -- GitLab From 61761a6b57f2818983466d24aab60baab471ba21 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Thu, 29 May 2025 21:39:37 +0530 Subject: [PATCH 165/902] drm/xe: drop redundant conversion to bool The result of integer comparison already evaluates to bool. No need for explicit conversion. No functional impact. Fixes: 0e414bf7ad01 ("drm/xe: Expose PCIe link downgrade attributes") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202505292205.MoljmkjQ-lkp@intel.com/ Signed-off-by: Raag Jadav Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250529160937.490147-1-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_device_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_sysfs.c b/drivers/gpu/drm/xe/xe_device_sysfs.c index 2e657692e5b5f..b9440f8c781e3 100644 --- a/drivers/gpu/drm/xe/xe_device_sysfs.c +++ b/drivers/gpu/drm/xe/xe_device_sysfs.c @@ -115,7 +115,7 @@ auto_link_downgrade_capable_show(struct device *dev, struct device_attribute *at xe_pm_runtime_put(xe); cap = REG_FIELD_GET(LINK_DOWNGRADE, val); - return sysfs_emit(buf, "%u\n", cap == DOWNGRADE_CAPABLE ? true : false); + return sysfs_emit(buf, "%u\n", cap == DOWNGRADE_CAPABLE); } static DEVICE_ATTR_ADMIN_RO(auto_link_downgrade_capable); -- GitLab From e4931f8be347ec5f19df4d6d33aea37145378c42 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 29 May 2025 10:23:56 -0700 Subject: [PATCH 166/902] drm/xe/vsec: fix CONFIG_INTEL_VSEC dependency The XE driver can be built with or without VSEC support, but fails to link as built-in if vsec is in a loadable module: x86_64-linux-ld: vmlinux.o: in function `xe_vsec_init': (.text+0x1e83e16): undefined reference to `intel_vsec_register' The normal fix for this is to add a 'depends on INTEL_VSEC || !INTEL_VSEC', forcing XE to be a loadable module as well, but that causes a circular dependency: symbol DRM_XE depends on INTEL_VSEC symbol INTEL_VSEC depends on X86_PLATFORM_DEVICES symbol X86_PLATFORM_DEVICES is selected by DRM_XE The problem here is selecting a symbol from another subsystem, so change that as well and rephrase the 'select' into the corresponding dependency. Since X86_PLATFORM_DEVICES is 'default y', there is no change to defconfig builds here. Fixes: 0c45e76fcc62 ("drm/xe/vsec: Support BMG devices") Signed-off-by: Arnd Bergmann Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250529172355.2395634-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 9bce047901b22..98b46c5342787 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -2,6 +2,8 @@ config DRM_XE tristate "Intel Xe Graphics" depends on DRM && PCI && MMU && (m || (y && KUNIT=y)) + depends on INTEL_VSEC || !INTEL_VSEC + depends on X86_PLATFORM_DEVICES || !(X86 && ACPI) select INTERVAL_TREE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs @@ -27,7 +29,6 @@ config DRM_XE select BACKLIGHT_CLASS_DEVICE if ACPI select INPUT if ACPI select ACPI_VIDEO if X86 && ACPI - select X86_PLATFORM_DEVICES if X86 && ACPI select ACPI_WMI if X86 && ACPI select SYNC_FILE select IOSF_MBI -- GitLab From 9d5558649f68e2e84a87a909631b30e15ca0f8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Wed, 28 May 2025 18:41:05 +0200 Subject: [PATCH 167/902] drm/xe: Rework eviction rejection of bound external bos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For preempt_fence mode VM's we're rejecting eviction of shared bos during VM_BIND. However, since we do this in the move() callback, we're getting an eviction failure warning from TTM. The TTM callback intended for these things is eviction_valuable(). However, the latter doesn't pass in the struct ttm_operation_ctx needed to determine whether the caller needs this. Instead, attach the needed information to the vm under the vm->resv, until we've been able to update TTM to provide the needed information. And add sufficient lockdep checks to prevent misuse and races. v2: - Fix a copy-paste error in xe_vm_clear_validating() v3: - Fix kerneldoc errors. Signed-off-by: Thomas Hellström Fixes: 0af944f0e308 ("drm/xe: Reject BO eviction if BO is bound to current VM") Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250528164105.234718-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_bo.c | 46 ++++++++++++--------- drivers/gpu/drm/xe/xe_vm.h | 69 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_vm_types.h | 8 ++++ 3 files changed, 105 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 3fafdcb8d95be..08c8c4b84a178 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -841,21 +841,6 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, goto out; } - /* Reject BO eviction if BO is bound to current VM. */ - if (evict && ctx->resv) { - struct drm_gpuvm_bo *vm_bo; - - drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) { - struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm); - - if (xe_vm_resv(vm) == ctx->resv && - xe_vm_in_preempt_fence_mode(vm)) { - ret = -EBUSY; - goto out; - } - } - } - /* * Failed multi-hop where the old_mem is still marked as * TTM_PL_FLAG_TEMPORARY, should just be a dummy move. @@ -1013,6 +998,25 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, return lret; } +static bool +xe_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) +{ + struct drm_gpuvm_bo *vm_bo; + + if (!ttm_bo_eviction_valuable(bo, place)) + return false; + + if (!xe_bo_is_xe_bo(bo)) + return true; + + drm_gem_for_each_gpuvm_bo(vm_bo, &bo->base) { + if (xe_vm_is_validating(gpuvm_to_vm(vm_bo->vm))) + return false; + } + + return true; +} + /** * xe_bo_shrink() - Try to shrink an xe bo. * @ctx: The struct ttm_operation_ctx used for shrinking. @@ -1047,7 +1051,7 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, (flags.purge && !xe_tt->purgeable)) return -EBUSY; - if (!ttm_bo_eviction_valuable(bo, &place)) + if (!xe_bo_eviction_valuable(bo, &place)) return -EBUSY; if (!xe_bo_is_xe_bo(bo) || !xe_bo_get_unless_zero(xe_bo)) @@ -1588,7 +1592,7 @@ const struct ttm_device_funcs xe_ttm_funcs = { .io_mem_pfn = xe_ttm_io_mem_pfn, .access_memory = xe_ttm_access_memory, .release_notify = xe_ttm_bo_release_notify, - .eviction_valuable = ttm_bo_eviction_valuable, + .eviction_valuable = xe_bo_eviction_valuable, .delete_mem_notify = xe_ttm_bo_delete_mem_notify, .swap_notify = xe_ttm_bo_swap_notify, }; @@ -2431,6 +2435,8 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict) .no_wait_gpu = false, .gfp_retry_mayfail = true, }; + struct pin_cookie cookie; + int ret; if (vm) { lockdep_assert_held(&vm->lock); @@ -2440,8 +2446,12 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict) ctx.resv = xe_vm_resv(vm); } + cookie = xe_vm_set_validating(vm, allow_res_evict); trace_xe_bo_validate(bo); - return ttm_bo_validate(&bo->ttm, &bo->placement, &ctx); + ret = ttm_bo_validate(&bo->ttm, &bo->placement, &ctx); + xe_vm_clear_validating(vm, allow_res_evict, cookie); + + return ret; } bool xe_bo_is_xe_bo(struct ttm_buffer_object *bo) diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 99e164852f637..88d6c0ef89c79 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -303,6 +303,75 @@ void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap); void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p); void xe_vm_snapshot_free(struct xe_vm_snapshot *snap); +/** + * xe_vm_set_validating() - Register this task as currently making bos resident + * @allow_res_evict: Allow eviction of buffer objects bound to @vm when + * validating. + * @vm: Pointer to the vm or NULL. + * + * Register this task as currently making bos resident for the vm. Intended + * to avoid eviction by the same task of shared bos bound to the vm. + * Call with the vm's resv lock held. + * + * Return: A pin cookie that should be used for xe_vm_clear_validating(). + */ +static inline struct pin_cookie xe_vm_set_validating(struct xe_vm *vm, + bool allow_res_evict) +{ + struct pin_cookie cookie = {}; + + if (vm && !allow_res_evict) { + xe_vm_assert_held(vm); + cookie = lockdep_pin_lock(&xe_vm_resv(vm)->lock.base); + /* Pairs with READ_ONCE in xe_vm_is_validating() */ + WRITE_ONCE(vm->validating, current); + } + + return cookie; +} + +/** + * xe_vm_clear_validating() - Unregister this task as currently making bos resident + * @vm: Pointer to the vm or NULL + * @allow_res_evict: Eviction from @vm was allowed. Must be set to the same + * value as for xe_vm_set_validation(). + * @cookie: Cookie obtained from xe_vm_set_validating(). + * + * Register this task as currently making bos resident for the vm. Intended + * to avoid eviction by the same task of shared bos bound to the vm. + * Call with the vm's resv lock held. + */ +static inline void xe_vm_clear_validating(struct xe_vm *vm, bool allow_res_evict, + struct pin_cookie cookie) +{ + if (vm && !allow_res_evict) { + lockdep_unpin_lock(&xe_vm_resv(vm)->lock.base, cookie); + /* Pairs with READ_ONCE in xe_vm_is_validating() */ + WRITE_ONCE(vm->validating, NULL); + } +} + +/** + * xe_vm_is_validating() - Whether bos bound to the vm are currently being made resident + * by the current task. + * @vm: Pointer to the vm. + * + * If this function returns %true, we should be in a vm resv locked region, since + * the current process is the same task that called xe_vm_set_validating(). + * The function asserts that that's indeed the case. + * + * Return: %true if the task is currently making bos resident, %false otherwise. + */ +static inline bool xe_vm_is_validating(struct xe_vm *vm) +{ + /* Pairs with WRITE_ONCE in xe_vm_is_validating() */ + if (READ_ONCE(vm->validating) == current) { + xe_vm_assert_held(vm); + return true; + } + return false; +} + #if IS_ENABLED(CONFIG_DRM_XE_USERPTR_INVAL_INJECT) void xe_vma_userptr_force_invalidate(struct xe_userptr_vma *uvma); #else diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index bfc145baad496..0e1318a15c9e8 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -310,6 +310,14 @@ struct xe_vm { * protected by the vm resv. */ u64 tlb_flush_seqno; + /** + * @validating: The task that is currently making bos resident for this vm. + * Protected by the VM's resv for writing. Opportunistic reading can be done + * using READ_ONCE. Note: This is a workaround for the + * TTM eviction_valuable() callback not being passed a struct + * ttm_operation_context(). Future work might want to address this. + */ + struct task_struct *validating; /** @batch_invalidate_tlb: Always invalidate TLB before batch start */ bool batch_invalidate_tlb; /** @xef: XE file handle for tracking this VM's drm client */ -- GitLab From 38fafa9f392f3110d2de431432d43f4eef99cd1b Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 28 May 2025 12:33:29 +0100 Subject: [PATCH 168/902] drm/xe/sched: stop re-submitting signalled jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Customer is reporting a really subtle issue where we get random DMAR faults, hangs and other nasties for kernel migration jobs when stressing stuff like s2idle/s3/s4. The explosions seems to happen somewhere after resuming the system with splats looking something like: PM: suspend exit rfkill: input handler disabled xe 0000:00:02.0: [drm] GT0: Engine reset: engine_class=bcs, logical_mask: 0x2, guc_id=0 xe 0000:00:02.0: [drm] GT0: Timedout job: seqno=24496, lrc_seqno=24496, guc_id=0, flags=0x13 in no process [-1] xe 0000:00:02.0: [drm] GT0: Kernel-submitted job timed out The likely cause appears to be a race between suspend cancelling the worker that processes the free_job()'s, such that we still have pending jobs to be freed after the cancel. Following from this, on resume the pending_list will now contain at least one already complete job, but it looks like we call drm_sched_resubmit_jobs(), which will then call run_job() on everything still on the pending_list. But if the job was already complete, then all the resources tied to the job, like the bb itself, any memory that is being accessed, the iommu mappings etc. might be long gone since those are usually tied to the fence signalling. This scenario can be seen in ftrace when running a slightly modified xe_pm IGT (kernel was only modified to inject artificial latency into free_job to make the race easier to hit): xe_sched_job_run: dev=0000:00:02.0, fence=0xffff888276cc8540, seqno=0, lrc_seqno=0, gt=0, guc_id=0, batch_addr=0x000000146910 ... xe_exec_queue_stop: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x0, flags=0x13 xe_exec_queue_stop: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=1, guc_state=0x0, flags=0x4 xe_exec_queue_stop: dev=0000:00:02.0, 4:0x1, gt=1, width=1, guc_id=0, guc_state=0x0, flags=0x3 xe_exec_queue_stop: dev=0000:00:02.0, 1:0x1, gt=1, width=1, guc_id=1, guc_state=0x0, flags=0x3 xe_exec_queue_stop: dev=0000:00:02.0, 4:0x1, gt=1, width=1, guc_id=2, guc_state=0x0, flags=0x3 xe_exec_queue_resubmit: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x0, flags=0x13 xe_sched_job_run: dev=0000:00:02.0, fence=0xffff888276cc8540, seqno=0, lrc_seqno=0, gt=0, guc_id=0, batch_addr=0x000000146910 ... ..... xe_exec_queue_memory_cat_error: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x3, flags=0x13 So the job_run() is clearly triggered twice for the same job, even though the first must have already signalled to completion during suspend. We can also see a CAT error after the re-submit. To prevent this only resubmit jobs on the pending_list that have not yet signalled. v2: - Make sure to re-arm the fence callbacks with sched_start(). v3 (Matt B): - Stop using drm_sched_resubmit_jobs(), which appears to be deprecated and just open-code a simple loop such that we skip calling run_job() on anything already signalled. Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4856 Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Matthew Brost Cc: William Tseng Cc: # v6.8+ Reviewed-by: Matthew Brost Reviewed-by: Tejas Upadhyay Link: https://lore.kernel.org/r/20250528113328.289392-2-matthew.auld@intel.com --- drivers/gpu/drm/xe/xe_gpu_scheduler.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.h b/drivers/gpu/drm/xe/xe_gpu_scheduler.h index c250ea773491e..308061f0cf372 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.h +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.h @@ -51,7 +51,15 @@ static inline void xe_sched_tdr_queue_imm(struct xe_gpu_scheduler *sched) static inline void xe_sched_resubmit_jobs(struct xe_gpu_scheduler *sched) { - drm_sched_resubmit_jobs(&sched->base); + struct drm_sched_job *s_job; + + list_for_each_entry(s_job, &sched->base.pending_list, list) { + struct drm_sched_fence *s_fence = s_job->s_fence; + struct dma_fence *hw_fence = s_fence->parent; + + if (hw_fence && !dma_fence_is_signaled(hw_fence)) + sched->base.ops->run_job(s_job); + } } static inline bool -- GitLab From 1d891ee820fd0fbb4101eacb0d922b5050a24933 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 22 May 2025 15:54:03 -0700 Subject: [PATCH 169/902] drm/xe/pxp: Use the correct define in the set_property_funcs array The define of the extension type was accidentally used instead of the one of the property itself. They're both zero, so no functional issue, but we should use the correct define for code correctness. Fixes: 41a97c4a1294 ("drm/xe/pxp/uapi: Add API to mark a BO as using PXP") Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://lore.kernel.org/r/20250522225401.3953243-6-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 08c8c4b84a178..61d208c852814 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2567,7 +2567,7 @@ typedef int (*xe_gem_create_set_property_fn)(struct xe_device *xe, u64 value); static const xe_gem_create_set_property_fn gem_create_set_property_funcs[] = { - [DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_set_pxp_type, + [DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE] = gem_create_set_pxp_type, }; static int gem_create_user_ext_set_property(struct xe_device *xe, -- GitLab From 21784ca96025b62d95b670b7639ad70ddafa69b8 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 22 May 2025 15:54:04 -0700 Subject: [PATCH 170/902] drm/xe/pxp: Clarify PXP queue creation behavior if PXP is not ready MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expected flow of operations when using PXP is to query the PXP status and wait for it to transition to "ready" before attempting to create an exec_queue. This flow is followed by the Mesa driver, but there is no guarantee that an incorrectly coded (or malicious) app will not attempt to create the queue first without querying the status. Therefore, we need to clarify what the expected behavior of the queue creation ioctl is in this scenario. Currently, the ioctl always fails with an -EBUSY code no matter the error, but for consistency it is better to distinguish between "failed to init" (-EIO) and "not ready" (-EBUSY), the same way the query ioctl does. Note that, while this is a change in the return code of an ioctl, the behavior of the ioctl in this particular corner case was not clearly spec'd, so no one should have been relying on it (and we know that Mesa, which is the only known userspace for this, didn't). v2: Minor rework of the doc (Rodrigo) Fixes: 72d479601d67 ("drm/xe/pxp/uapi: Add userspace and LRC support for PXP-using queues") Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Cc: José Roberto de Souza Reviewed-by: José Roberto de Souza Reviewed-by: John Harrison Acked-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250522225401.3953243-7-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 8 ++++++-- include/uapi/drm/xe_drm.h | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 454ea7dc08ac8..b5bc15f436fa2 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -541,10 +541,14 @@ int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) */ xe_pm_runtime_get(pxp->xe); - if (!pxp_prerequisites_done(pxp)) { - ret = -EBUSY; + /* get_readiness_status() returns 0 for in-progress and 1 for done */ + ret = xe_pxp_get_readiness_status(pxp); + if (ret <= 0) { + if (!ret) + ret = -EBUSY; goto out; } + ret = 0; wait_for_idle: /* diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 9c08738c3b918..6a702ba7817c3 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -1210,6 +1210,11 @@ struct drm_xe_vm_bind { * there is no need to explicitly set that. When a queue of type * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. + * The user is expected to query the PXP status via the query ioctl (see + * %DRM_XE_DEVICE_QUERY_PXP_STATUS) and to wait for PXP to be ready before + * attempting to create a queue with this property. When a queue is created + * before PXP is ready, the ioctl will return -EBUSY if init is still in + * progress or -EIO if init failed. * Given that going into a power-saving state kills PXP HWDRM sessions, * runtime PM will be blocked while queues of this type are alive. * All PXP queues will be killed if a PXP invalidation event occurs. -- GitLab From ccd3c6820a9024bcb68c249b644b5e42f0f7b9d2 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 22 May 2025 15:54:05 -0700 Subject: [PATCH 171/902] drm/xe/pxp: Decouple queue addition from PXP start Starting PXP and adding a queue to the PXP queue list are separate actions. Given that a queue can only be added to the list if PXP is active, the 2 actions were bundled together to avoid having to re-lock and re-check the status to perform the queue addition after having done so during the PXP start. However, we don't save a lot of complexity by doing so and we lose in clarity of code, so overall it's cleaner to just keep the 2 actions separate. v2: remove leftover rpm_get (John), fix rpm_put in error case Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://lore.kernel.org/r/20250522225401.3953243-8-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 147 +++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index b5bc15f436fa2..3d62008c99f15 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -504,69 +504,62 @@ int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 t return 0; } -static void __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) +static int __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) { - spin_lock_irq(&pxp->queues.lock); - list_add_tail(&q->pxp.link, &pxp->queues.list); - spin_unlock_irq(&pxp->queues.lock); + int ret = 0; + + /* + * A queue can be added to the list only if the PXP is in active status, + * otherwise the termination might not handle it correctly. + */ + mutex_lock(&pxp->mutex); + + if (pxp->status == XE_PXP_ACTIVE) { + spin_lock_irq(&pxp->queues.lock); + list_add_tail(&q->pxp.link, &pxp->queues.list); + spin_unlock_irq(&pxp->queues.lock); + } else if (pxp->status == XE_PXP_ERROR || pxp->status == XE_PXP_SUSPENDED) { + ret = -EIO; + } else { + ret = -EBUSY; /* try again later */ + } + + mutex_unlock(&pxp->mutex); + + return ret; } -/** - * xe_pxp_exec_queue_add - add a queue to the PXP list - * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) - * @q: the queue to add to the list - * - * If PXP is enabled and the prerequisites are done, start the PXP ARB - * session (if not already running) and add the queue to the PXP list. Note - * that the queue must have previously been marked as using PXP with - * xe_pxp_exec_queue_set_type. - * - * Returns 0 if the PXP ARB session is running and the queue is in the list, - * -ENODEV if PXP is disabled, -EBUSY if the PXP prerequisites are not done, - * other errno value if something goes wrong during the session start. - */ -int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) +static int pxp_start(struct xe_pxp *pxp, u8 type) { int ret = 0; + bool restart = false; if (!xe_pxp_is_enabled(pxp)) return -ENODEV; /* we only support HWDRM sessions right now */ - xe_assert(pxp->xe, q->pxp.type == DRM_XE_PXP_TYPE_HWDRM); - - /* - * Runtime suspend kills PXP, so we take a reference to prevent it from - * happening while we have active queues that use PXP - */ - xe_pm_runtime_get(pxp->xe); + xe_assert(pxp->xe, type == DRM_XE_PXP_TYPE_HWDRM); /* get_readiness_status() returns 0 for in-progress and 1 for done */ ret = xe_pxp_get_readiness_status(pxp); - if (ret <= 0) { - if (!ret) - ret = -EBUSY; - goto out; - } + if (ret <= 0) + return ret ?: -EBUSY; + ret = 0; wait_for_idle: /* * if there is an action in progress, wait for it. We need to wait * outside the lock because the completion is done from within the lock. - * Note that the two action should never be pending at the same time. + * Note that the two actions should never be pending at the same time. */ if (!wait_for_completion_timeout(&pxp->termination, - msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) { - ret = -ETIMEDOUT; - goto out; - } + msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) + return -ETIMEDOUT; if (!wait_for_completion_timeout(&pxp->activation, - msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) { - ret = -ETIMEDOUT; - goto out; - } + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) + return -ETIMEDOUT; mutex_lock(&pxp->mutex); @@ -574,11 +567,9 @@ wait_for_idle: switch (pxp->status) { case XE_PXP_ERROR: ret = -EIO; - break; + goto out_unlock; case XE_PXP_ACTIVE: - __exec_queue_add(pxp, q); - mutex_unlock(&pxp->mutex); - goto out; + goto out_unlock; case XE_PXP_READY_TO_START: pxp->status = XE_PXP_START_IN_PROGRESS; reinit_completion(&pxp->activation); @@ -586,8 +577,8 @@ wait_for_idle: case XE_PXP_START_IN_PROGRESS: /* If a start is in progress then the completion must not be done */ XE_WARN_ON(completion_done(&pxp->activation)); - mutex_unlock(&pxp->mutex); - goto wait_for_idle; + restart = true; + goto out_unlock; case XE_PXP_NEEDS_TERMINATION: mark_termination_in_progress(pxp); break; @@ -595,29 +586,25 @@ wait_for_idle: case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: /* If a termination is in progress then the completion must not be done */ XE_WARN_ON(completion_done(&pxp->termination)); - mutex_unlock(&pxp->mutex); - goto wait_for_idle; + restart = true; + goto out_unlock; case XE_PXP_SUSPENDED: default: drm_err(&pxp->xe->drm, "unexpected state during PXP start: %u\n", pxp->status); ret = -EIO; - break; + goto out_unlock; } mutex_unlock(&pxp->mutex); - if (ret) - goto out; - if (!completion_done(&pxp->termination)) { ret = pxp_terminate_hw(pxp); if (ret) { drm_err(&pxp->xe->drm, "PXP termination failed before start\n"); mutex_lock(&pxp->mutex); pxp->status = XE_PXP_ERROR; - mutex_unlock(&pxp->mutex); - goto out; + goto out_unlock; } goto wait_for_idle; @@ -639,21 +626,59 @@ wait_for_idle: if (pxp->status != XE_PXP_START_IN_PROGRESS) { drm_err(&pxp->xe->drm, "unexpected state after PXP start: %u\n", pxp->status); pxp->status = XE_PXP_NEEDS_TERMINATION; - mutex_unlock(&pxp->mutex); - goto wait_for_idle; + restart = true; + goto out_unlock; } /* If everything went ok, update the status and add the queue to the list */ - if (!ret) { + if (!ret) pxp->status = XE_PXP_ACTIVE; - __exec_queue_add(pxp, q); - } else { + else pxp->status = XE_PXP_ERROR; - } +out_unlock: mutex_unlock(&pxp->mutex); -out: + if (restart) + goto wait_for_idle; + + return ret; +} + +/** + * xe_pxp_exec_queue_add - add a queue to the PXP list + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @q: the queue to add to the list + * + * If PXP is enabled and the prerequisites are done, start the PXP default + * session (if not already running) and add the queue to the PXP list. + * + * Returns 0 if the PXP session is running and the queue is in the list, + * -ENODEV if PXP is disabled, -EBUSY if the PXP prerequisites are not done, + * other errno value if something goes wrong during the session start. + */ +int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) +{ + int ret; + + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + /* + * Runtime suspend kills PXP, so we take a reference to prevent it from + * happening while we have active queues that use PXP + */ + xe_pm_runtime_get(pxp->xe); + +start: + ret = pxp_start(pxp, q->pxp.type); + + if (!ret) { + ret = __exec_queue_add(pxp, q); + if (ret == -EBUSY) + goto start; + } + /* * in the successful case the PM ref is released from * xe_pxp_exec_queue_remove -- GitLab From dea7a2b4f60e04b80f43e3281cdbb29a2aa29152 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 30 May 2025 15:31:57 -0700 Subject: [PATCH 172/902] drm/xe/hwmon: Simplify and fix 32b wrap Like done in commit eaa287069a70 ("drm/xe/guc_submit: Simplify and fix diff calculation"), just use u32 for wrapping the value, which is simpler and more correct: when wrapping on 32b, the accumulated value was off by one. Also, do not mix the u64 value from pmt with the u32 value used for the calculation. Cc: Badal Nilawar Cc: Raag Jadav Reviewed-by: Raag Jadav Link: https://lore.kernel.org/r/20250530-xe-hwmon-wrap-v2-1-ce653db7fe4a@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_hwmon.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 778354c91f598..0d32e977537ca 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -436,7 +436,7 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy) { struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); struct xe_hwmon_energy_info *ei = &hwmon->ei[channel]; - u64 reg_val; + u32 reg_val; int ret = 0; /* Energy is supported only for card and pkg */ @@ -446,29 +446,27 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy) } if (hwmon->xe->info.platform == XE_BATTLEMAGE) { + u64 pmt_val; + ret = xe_pmt_telem_read(to_pci_dev(hwmon->xe->drm.dev), xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID), - ®_val, BMG_ENERGY_STATUS_PMT_OFFSET, sizeof(reg_val)); - if (ret != sizeof(reg_val)) { + &pmt_val, BMG_ENERGY_STATUS_PMT_OFFSET, sizeof(pmt_val)); + if (ret != sizeof(pmt_val)) { drm_warn(&hwmon->xe->drm, "energy read from pmt failed, ret %d\n", ret); *energy = 0; return; } if (channel == CHANNEL_PKG) - reg_val = REG_FIELD_GET64(ENERGY_PKG, reg_val); + reg_val = REG_FIELD_GET64(ENERGY_PKG, pmt_val); else - reg_val = REG_FIELD_GET64(ENERGY_CARD, reg_val); + reg_val = REG_FIELD_GET64(ENERGY_CARD, pmt_val); } else { reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, channel)); } - if (reg_val >= ei->reg_val_prev) - ei->accum_energy += reg_val - ei->reg_val_prev; - else - ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val; - + ei->accum_energy += reg_val - ei->reg_val_prev; ei->reg_val_prev = reg_val; *energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY, -- GitLab From 8d425229acb24354d3add6f67bc1b0188f16adea Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 30 May 2025 18:48:35 +0200 Subject: [PATCH 173/902] drm/xe: Convert page fault messages to be GT-oriented We are processing here G2H messages, so we should use GT oriented messages to retain information about the origin GT. While at it, print error codes in a user-friendly way. Signed-off-by: Michal Wajdeczko Cc: Lucas De Marchi Cc: Matthew Brost Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250530164835.461-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 74 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 7a8f87709e39c..e0e68eda82bd8 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -14,6 +14,7 @@ #include "abi/guc_actions_abi.h" #include "xe_bo.h" #include "xe_gt.h" +#include "xe_gt_printk.h" #include "xe_gt_stats.h" #include "xe_gt_tlb_invalidation.h" #include "xe_guc.h" @@ -244,22 +245,22 @@ static int send_pagefault_reply(struct xe_guc *guc, return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); } -static void print_pagefault(struct xe_device *xe, struct pagefault *pf) +static void print_pagefault(struct xe_gt *gt, struct pagefault *pf) { - drm_dbg(&xe->drm, "\n\tASID: %d\n" - "\tVFID: %d\n" - "\tPDATA: 0x%04x\n" - "\tFaulted Address: 0x%08x%08x\n" - "\tFaultType: %d\n" - "\tAccessType: %d\n" - "\tFaultLevel: %d\n" - "\tEngineClass: %d %s\n" - "\tEngineInstance: %d\n", - pf->asid, pf->vfid, pf->pdata, upper_32_bits(pf->page_addr), - lower_32_bits(pf->page_addr), - pf->fault_type, pf->access_type, pf->fault_level, - pf->engine_class, xe_hw_engine_class_to_str(pf->engine_class), - pf->engine_instance); + xe_gt_dbg(gt, "\n\tASID: %d\n" + "\tVFID: %d\n" + "\tPDATA: 0x%04x\n" + "\tFaulted Address: 0x%08x%08x\n" + "\tFaultType: %d\n" + "\tAccessType: %d\n" + "\tFaultLevel: %d\n" + "\tEngineClass: %d %s\n" + "\tEngineInstance: %d\n", + pf->asid, pf->vfid, pf->pdata, upper_32_bits(pf->page_addr), + lower_32_bits(pf->page_addr), + pf->fault_type, pf->access_type, pf->fault_level, + pf->engine_class, xe_hw_engine_class_to_str(pf->engine_class), + pf->engine_instance); } #define PF_MSG_LEN_DW 4 @@ -311,7 +312,6 @@ static bool pf_queue_full(struct pf_queue *pf_queue) int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) { struct xe_gt *gt = guc_to_gt(guc); - struct xe_device *xe = gt_to_xe(gt); struct pf_queue *pf_queue; unsigned long flags; u32 asid; @@ -336,7 +336,7 @@ int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) pf_queue->num_dw; queue_work(gt->usm.pf_wq, &pf_queue->worker); } else { - drm_warn(&xe->drm, "PF Queue full, shouldn't be possible"); + xe_gt_warn(gt, "PageFault Queue full, shouldn't be possible\n"); } spin_unlock_irqrestore(&pf_queue->lock, flags); @@ -349,7 +349,6 @@ static void pf_queue_work_func(struct work_struct *w) { struct pf_queue *pf_queue = container_of(w, struct pf_queue, worker); struct xe_gt *gt = pf_queue->gt; - struct xe_device *xe = gt_to_xe(gt); struct xe_guc_pagefault_reply reply = {}; struct pagefault pf = {}; unsigned long threshold; @@ -360,9 +359,9 @@ static void pf_queue_work_func(struct work_struct *w) while (get_pagefault(pf_queue, &pf)) { ret = handle_pagefault(gt, &pf); if (unlikely(ret)) { - print_pagefault(xe, &pf); + print_pagefault(gt, &pf); pf.fault_unsuccessful = 1; - drm_dbg(&xe->drm, "Fault response: Unsuccessful %d\n", ret); + xe_gt_dbg(gt, "Fault response: Unsuccessful %pe\n", ERR_PTR(ret)); } reply.dw0 = FIELD_PREP(PFR_VALID, 1) | @@ -515,21 +514,21 @@ static int sub_granularity_in_byte(int val) return (granularity_in_byte(val) / 32); } -static void print_acc(struct xe_device *xe, struct acc *acc) +static void print_acc(struct xe_gt *gt, struct acc *acc) { - drm_warn(&xe->drm, "Access counter request:\n" - "\tType: %s\n" - "\tASID: %d\n" - "\tVFID: %d\n" - "\tEngine: %d:%d\n" - "\tGranularity: 0x%x KB Region/ %d KB sub-granularity\n" - "\tSub_Granularity Vector: 0x%08x\n" - "\tVA Range base: 0x%016llx\n", - acc->access_type ? "AC_NTFY_VAL" : "AC_TRIG_VAL", - acc->asid, acc->vfid, acc->engine_class, acc->engine_instance, - granularity_in_byte(acc->granularity) / SZ_1K, - sub_granularity_in_byte(acc->granularity) / SZ_1K, - acc->sub_granularity, acc->va_range_base); + xe_gt_warn(gt, "Access counter request:\n" + "\tType: %s\n" + "\tASID: %d\n" + "\tVFID: %d\n" + "\tEngine: %d:%d\n" + "\tGranularity: 0x%x KB Region/ %d KB sub-granularity\n" + "\tSub_Granularity Vector: 0x%08x\n" + "\tVA Range base: 0x%016llx\n", + acc->access_type ? "AC_NTFY_VAL" : "AC_TRIG_VAL", + acc->asid, acc->vfid, acc->engine_class, acc->engine_instance, + granularity_in_byte(acc->granularity) / SZ_1K, + sub_granularity_in_byte(acc->granularity) / SZ_1K, + acc->sub_granularity, acc->va_range_base); } static struct xe_vma *get_acc_vma(struct xe_vm *vm, struct acc *acc) @@ -627,7 +626,6 @@ static void acc_queue_work_func(struct work_struct *w) { struct acc_queue *acc_queue = container_of(w, struct acc_queue, worker); struct xe_gt *gt = acc_queue->gt; - struct xe_device *xe = gt_to_xe(gt); struct acc acc = {}; unsigned long threshold; int ret; @@ -637,8 +635,8 @@ static void acc_queue_work_func(struct work_struct *w) while (get_acc(acc_queue, &acc)) { ret = handle_acc(gt, &acc); if (unlikely(ret)) { - print_acc(xe, &acc); - drm_warn(&xe->drm, "ACC: Unsuccessful %d\n", ret); + print_acc(gt, &acc); + xe_gt_warn(gt, "ACC: Unsuccessful %pe\n", ERR_PTR(ret)); } if (time_after(jiffies, threshold) && @@ -683,7 +681,7 @@ int xe_guc_access_counter_notify_handler(struct xe_guc *guc, u32 *msg, u32 len) acc_queue->head = (acc_queue->head + len) % ACC_QUEUE_NUM_DW; queue_work(gt->usm.acc_wq, &acc_queue->worker); } else { - drm_warn(>_to_xe(gt)->drm, "ACC Queue full, dropping ACC"); + xe_gt_warn(gt, "ACC Queue full, dropping ACC\n"); } spin_unlock(&acc_queue->lock); -- GitLab From eae784475896cbd3faa2063cb2bed6cd8e085abf Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 30 May 2025 23:05:24 +0200 Subject: [PATCH 174/902] drm/xe: Use GT-oriented printer to dump topology on init During the probe we dump the discovered GT topology, but instead of a generic printer we can use our own GT-oriented printer which contains information about the source GT. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Matt Roper Reviewed-by: Jonathan Cavitt Link: https://lore.kernel.org/r/20250530210524.505-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_topology.c b/drivers/gpu/drm/xe/xe_gt_topology.c index 516c81e3b8dd9..acec6559e2f21 100644 --- a/drivers/gpu/drm/xe/xe_gt_topology.c +++ b/drivers/gpu/drm/xe/xe_gt_topology.c @@ -12,6 +12,7 @@ #include "regs/xe_gt_regs.h" #include "xe_assert.h" #include "xe_gt.h" +#include "xe_gt_printk.h" #include "xe_mmio.h" #include "xe_wa.h" @@ -243,8 +244,7 @@ xe_gt_topology_init(struct xe_gt *gt) load_eu_mask(gt, gt->fuse_topo.eu_mask_per_dss, >->fuse_topo.eu_type); load_l3_bank_mask(gt, gt->fuse_topo.l3_bank_mask); - p = drm_dbg_printer(>_to_xe(gt)->drm, DRM_UT_DRIVER, "GT topology"); - + p = xe_gt_dbg_printer(gt); xe_gt_topology_dump(gt, &p); } -- GitLab From d65650a9d153c91f0cde0f5026268812e0b697f3 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 28 May 2025 11:00:21 +0200 Subject: [PATCH 175/902] drm/xe/guc: Resend potentially lost H2G MMIO request There could be a scenario where the VF driver is resuming faster than the driver PF is able to complete the VF FLR sequence which includes reset of the VF scratch registers. This may result in deletion of the ongoing HXG message (it could be either a host request or a GuC response). When we detect that HXG message was likey lost (scratch register with HXG header was zeroed) try to send this request once more before giving up. Signed-off-by: Michal Wajdeczko Cc: Satyanarayana K V P Reviewed-by: Satyanarayana K V P Link: https://lore.kernel.org/r/20250528090021.329-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index 350434a8b9537..52453845d1bd3 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -1289,6 +1289,7 @@ int xe_guc_mmio_send_recv(struct xe_guc *guc, const u32 *request, struct xe_reg reply_reg = xe_gt_is_media_type(gt) ? MED_VF_SW_FLAG(0) : VF_SW_FLAG(0); const u32 LAST_INDEX = VF_SW_FLAG_COUNT - 1; + bool lost = false; int ret; int i; @@ -1322,6 +1323,12 @@ retry: FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC), 50000, &reply, false); if (ret) { + /* scratch registers might be cleared during FLR, try once more */ + if (!reply && !lost) { + xe_gt_dbg(gt, "GuC mmio request %#x: lost, trying again\n", request[0]); + lost = true; + goto retry; + } timeout: xe_gt_err(gt, "GuC mmio request %#x: no reply %#x\n", request[0], reply); -- GitLab From d8636cce7a1c81b67ee1fcfd03fe8397e0101a32 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 28 May 2025 14:54:04 -0700 Subject: [PATCH 176/902] drm/xe/configfs: Drop trailing semicolons Drop the semicolons from the dummy implementation: they shouldn't be there. Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250528-engine-mask-v4-1-f4636d2a890a@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_configfs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_configfs.h b/drivers/gpu/drm/xe/xe_configfs.h index d7d041ec26117..ef6d231b3024b 100644 --- a/drivers/gpu/drm/xe/xe_configfs.h +++ b/drivers/gpu/drm/xe/xe_configfs.h @@ -15,10 +15,10 @@ void xe_configfs_exit(void); bool xe_configfs_get_survivability_mode(struct pci_dev *pdev); void xe_configfs_clear_survivability_mode(struct pci_dev *pdev); #else -static inline int xe_configfs_init(void) { return 0; }; -static inline void xe_configfs_exit(void) {}; -static inline bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) { return false; }; -static inline void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) {}; +static inline int xe_configfs_init(void) { return 0; } +static inline void xe_configfs_exit(void) { } +static inline bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) { return false; } +static inline void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) { } #endif #endif -- GitLab From 2b0ef1f7a2980bf0c5589ff42806eee2d55ea8e6 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 28 May 2025 14:54:05 -0700 Subject: [PATCH 177/902] drm/xe: Convert "fused off" messages to be gt-based It's useful to see in the log message what GT was being checked for disabled/fused-off engines. Especially on multi-tile platforms the different tiles may be fused differently making it harder to parse the information. Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250528-engine-mask-v4-2-f4636d2a890a@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_hw_engine.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 93241fd0a4ba3..33681169b8570 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -693,7 +693,7 @@ static void read_media_fuses(struct xe_gt *gt) if (!(BIT(j) & vdbox_mask)) { gt->info.engine_mask &= ~BIT(i); - drm_info(&xe->drm, "vcs%u fused off\n", j); + xe_gt_info(gt, "vcs%u fused off\n", j); } } @@ -703,7 +703,7 @@ static void read_media_fuses(struct xe_gt *gt) if (!(BIT(j) & vebox_mask)) { gt->info.engine_mask &= ~BIT(i); - drm_info(&xe->drm, "vecs%u fused off\n", j); + xe_gt_info(gt, "vecs%u fused off\n", j); } } } @@ -728,15 +728,13 @@ static void read_copy_fuses(struct xe_gt *gt) if (!(BIT(j / 2) & bcs_mask)) { gt->info.engine_mask &= ~BIT(i); - drm_info(&xe->drm, "bcs%u fused off\n", j); + xe_gt_info(gt, "bcs%u fused off\n", j); } } } static void read_compute_fuses_from_dss(struct xe_gt *gt) { - struct xe_device *xe = gt_to_xe(gt); - /* * CCS fusing based on DSS masks only applies to platforms that can * have more than one CCS. @@ -755,14 +753,13 @@ static void read_compute_fuses_from_dss(struct xe_gt *gt) if (!xe_gt_topology_has_dss_in_quadrant(gt, j)) { gt->info.engine_mask &= ~BIT(i); - drm_info(&xe->drm, "ccs%u fused off\n", j); + xe_gt_info(gt, "ccs%u fused off\n", j); } } } static void read_compute_fuses_from_reg(struct xe_gt *gt) { - struct xe_device *xe = gt_to_xe(gt); u32 ccs_mask; ccs_mask = xe_mmio_read32(>->mmio, XEHP_FUSE4); @@ -774,7 +771,7 @@ static void read_compute_fuses_from_reg(struct xe_gt *gt) if ((ccs_mask & BIT(j)) == 0) { gt->info.engine_mask &= ~BIT(i); - drm_info(&xe->drm, "ccs%u fused off\n", j); + xe_gt_info(gt, "ccs%u fused off\n", j); } } } @@ -789,8 +786,6 @@ static void read_compute_fuses(struct xe_gt *gt) static void check_gsc_availability(struct xe_gt *gt) { - struct xe_device *xe = gt_to_xe(gt); - if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0))) return; @@ -806,7 +801,7 @@ static void check_gsc_availability(struct xe_gt *gt) xe_mmio_write32(>->mmio, GUNIT_GSC_INTR_ENABLE, 0); xe_mmio_write32(>->mmio, GUNIT_GSC_INTR_MASK, ~0); - drm_dbg(&xe->drm, "GSC FW not used, disabling gsccs\n"); + xe_gt_dbg(gt, "GSC FW not used, disabling gsccs\n"); } } -- GitLab From 58b51df807d7394a09ddb95b47099d59465e3777 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 28 May 2025 14:54:06 -0700 Subject: [PATCH 178/902] drm/xe: Allow to disable engines Sometimes it's useful to load the driver with a smaller set of engines to allow more targeted debugging, particularly on early enabling. Besides checking what is fused off in hardware, add similar logic to disable engines in software. This will use configfs to allow users to set what engine to disable, so already add prepare for that. The exact configfs interface will be added later. Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250528-engine-mask-v4-3-f4636d2a890a@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_configfs.c | 15 +++++++++++++++ drivers/gpu/drm/xe/xe_configfs.h | 3 +++ drivers/gpu/drm/xe/xe_hw_engine.c | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c index cb9f175c89a1c..8320d57ef5a80 100644 --- a/drivers/gpu/drm/xe/xe_configfs.c +++ b/drivers/gpu/drm/xe/xe_configfs.c @@ -226,6 +226,21 @@ void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) config_item_put(&dev->group.cg_item); } +/** + * xe_configfs_get_engines_allowed - get engine allowed mask from configfs + * @pdev: pci device + * + * Find the configfs group that belongs to the pci device and return + * the mask of engines allowed to be used. + * + * Return: engine mask with allowed engines + */ +u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) +{ + /* dummy implementation */ + return U64_MAX; +} + int __init xe_configfs_init(void) { struct config_group *root = &xe_configfs.su_group; diff --git a/drivers/gpu/drm/xe/xe_configfs.h b/drivers/gpu/drm/xe/xe_configfs.h index ef6d231b3024b..fb87640080896 100644 --- a/drivers/gpu/drm/xe/xe_configfs.h +++ b/drivers/gpu/drm/xe/xe_configfs.h @@ -5,6 +5,7 @@ #ifndef _XE_CONFIGFS_H_ #define _XE_CONFIGFS_H_ +#include #include struct pci_dev; @@ -14,11 +15,13 @@ int xe_configfs_init(void); void xe_configfs_exit(void); bool xe_configfs_get_survivability_mode(struct pci_dev *pdev); void xe_configfs_clear_survivability_mode(struct pci_dev *pdev); +u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev); #else static inline int xe_configfs_init(void) { return 0; } static inline void xe_configfs_exit(void) { } static inline bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) { return false; } static inline void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) { } +static inline u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) { return U64_MAX; } #endif #endif diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 33681169b8570..3439c8522d013 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -17,6 +17,7 @@ #include "regs/xe_irq_regs.h" #include "xe_assert.h" #include "xe_bo.h" +#include "xe_configfs.h" #include "xe_device.h" #include "xe_execlist.h" #include "xe_force_wake.h" @@ -805,6 +806,24 @@ static void check_gsc_availability(struct xe_gt *gt) } } +static void check_sw_disable(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + u64 sw_allowed = xe_configfs_get_engines_allowed(to_pci_dev(xe->drm.dev)); + enum xe_hw_engine_id id; + + for (id = 0; id < XE_NUM_HW_ENGINES; ++id) { + if (!(gt->info.engine_mask & BIT(id))) + continue; + + if (!(sw_allowed & BIT(id))) { + gt->info.engine_mask &= ~BIT(id); + xe_gt_info(gt, "%s disabled via configfs\n", + engine_infos[id].name); + } + } +} + int xe_hw_engines_init_early(struct xe_gt *gt) { int i; @@ -813,6 +832,7 @@ int xe_hw_engines_init_early(struct xe_gt *gt) read_copy_fuses(gt); read_compute_fuses(gt); check_gsc_availability(gt); + check_sw_disable(gt); BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT < XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN); BUILD_BUG_ON(XE_HW_ENGINE_PREEMPT_TIMEOUT > XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX); -- GitLab From d09bc3edfe5c702463e2640314b7db2219242446 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 28 May 2025 14:54:07 -0700 Subject: [PATCH 179/902] drm/xe/configfs: Add attribute to disable engines Add the userspace interface to load the driver with fewer engines. The syntax is to just echo the engine names to a file in configfs, like below: echo 'rcs0,bcs0' > /sys/kernel/config/xe//engine_allowed With that engines other than rcs0 and bcs0 will not be enabled. To enable all instances from a class, a '*' can be used. Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250528-engine-mask-v4-4-f4636d2a890a@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_configfs.c | 149 ++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c index 8320d57ef5a80..8ec1ff1e4e808 100644 --- a/drivers/gpu/drm/xe/xe_configfs.c +++ b/drivers/gpu/drm/xe/xe_configfs.c @@ -3,14 +3,19 @@ * Copyright © 2025 Intel Corporation */ +#include #include +#include #include #include #include +#include #include "xe_configfs.h" #include "xe_module.h" +#include "xe_hw_engine_types.h" + /** * DOC: Xe Configfs * @@ -48,6 +53,30 @@ * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode * # echo 0000:03:00.0 > /sys/bus/pci/drivers/xe/bind (Enters survivability mode if supported) * + * Allowed engines: + * ---------------- + * + * Allow only a set of engine(s) to be available, disabling the other engines + * even if they are available in hardware. This is applied after HW fuses are + * considered on each tile. Examples: + * + * Allow only one render and one copy engines, nothing else:: + * + * # echo 'rcs0,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed + * + * Allow only compute engines and first copy engine:: + * + * # echo 'ccs*,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed + * + * Note that the engine names are the per-GT hardware names. On multi-tile + * platforms, writing ``rcs0,bcs0`` to this file would allow the first render + * and copy engines on each tile. + * + * The requested configuration may not be supported by the platform and driver + * may fail to probe. For example: if at least one copy engine is expected to be + * available for migrations, but it's disabled. This is intended for debugging + * purposes only. + * * Remove devices * ============== * @@ -60,11 +89,30 @@ struct xe_config_device { struct config_group group; bool survivability_mode; + u64 engines_allowed; /* protects attributes */ struct mutex lock; }; +struct engine_info { + const char *cls; + u64 mask; +}; + +/* Some helpful macros to aid on the sizing of buffer allocation when parsing */ +#define MAX_ENGINE_CLASS_CHARS 5 +#define MAX_ENGINE_INSTANCE_CHARS 2 + +static const struct engine_info engine_info[] = { + { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK }, + { .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK }, + { .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK }, + { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK }, + { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK }, + { .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK }, +}; + static struct xe_config_device *to_xe_config_device(struct config_item *item) { return container_of(to_config_group(item), struct xe_config_device, group); @@ -94,10 +142,96 @@ static ssize_t survivability_mode_store(struct config_item *item, const char *pa return len; } +static ssize_t engines_allowed_show(struct config_item *item, char *page) +{ + struct xe_config_device *dev = to_xe_config_device(item); + char *p = page; + + for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { + u64 mask = engine_info[i].mask; + + if ((dev->engines_allowed & mask) == mask) { + p += sprintf(p, "%s*\n", engine_info[i].cls); + } else if (mask & dev->engines_allowed) { + u16 bit0 = __ffs64(mask), bit; + + mask &= dev->engines_allowed; + + for_each_set_bit(bit, (const unsigned long *)&mask, 64) + p += sprintf(p, "%s%u\n", engine_info[i].cls, + bit - bit0); + } + } + + return p - page; +} + +static bool lookup_engine_mask(const char *pattern, u64 *mask) +{ + for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { + u8 instance; + u16 bit; + + if (!str_has_prefix(pattern, engine_info[i].cls)) + continue; + + pattern += strlen(engine_info[i].cls); + + if (!strcmp(pattern, "*")) { + *mask = engine_info[i].mask; + return true; + } + + if (kstrtou8(pattern, 10, &instance)) + return false; + + bit = __ffs64(engine_info[i].mask) + instance; + if (bit >= fls64(engine_info[i].mask)) + return false; + + *mask = BIT_ULL(bit); + return true; + } + + return false; +} + +static ssize_t engines_allowed_store(struct config_item *item, const char *page, + size_t len) +{ + struct xe_config_device *dev = to_xe_config_device(item); + size_t patternlen, p; + u64 mask, val = 0; + + for (p = 0; p < len; p += patternlen + 1) { + char buf[MAX_ENGINE_CLASS_CHARS + MAX_ENGINE_INSTANCE_CHARS + 1]; + + patternlen = strcspn(page + p, ",\n"); + if (patternlen >= sizeof(buf)) + return -EINVAL; + + memcpy(buf, page + p, patternlen); + buf[patternlen] = '\0'; + + if (!lookup_engine_mask(buf, &mask)) + return -EINVAL; + + val |= mask; + } + + mutex_lock(&dev->lock); + dev->engines_allowed = val; + mutex_unlock(&dev->lock); + + return len; +} + CONFIGFS_ATTR(, survivability_mode); +CONFIGFS_ATTR(, engines_allowed); static struct configfs_attribute *xe_config_device_attrs[] = { &attr_survivability_mode, + &attr_engines_allowed, NULL, }; @@ -139,6 +273,9 @@ static struct config_group *xe_config_make_device_group(struct config_group *gro if (!dev) return ERR_PTR(-ENOMEM); + /* Default values */ + dev->engines_allowed = U64_MAX; + config_group_init_type_name(&dev->group, name, &xe_config_device_type); mutex_init(&dev->lock); @@ -237,8 +374,16 @@ void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) */ u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) { - /* dummy implementation */ - return U64_MAX; + struct xe_config_device *dev = configfs_find_group(pdev); + u64 engines_allowed; + + if (!dev) + return U64_MAX; + + engines_allowed = dev->engines_allowed; + config_item_put(&dev->group.cg_item); + + return engines_allowed; } int __init xe_configfs_init(void) -- GitLab From 399c5f54090c1c7d8f9eae7897940e8a11604884 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 28 May 2025 14:54:08 -0700 Subject: [PATCH 180/902] drm/xe/configfs: Add internal API to documentation Add the internal configfs API like is done with other parts of the driver. Also ensure the correct number of '=' chars are used for the header. Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250528-engine-mask-v4-5-f4636d2a890a@intel.com Signed-off-by: Lucas De Marchi --- Documentation/gpu/xe/xe_configfs.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/gpu/xe/xe_configfs.rst b/Documentation/gpu/xe/xe_configfs.rst index 9b9d941eb20ed..7f8ec39dc6dd5 100644 --- a/Documentation/gpu/xe/xe_configfs.rst +++ b/Documentation/gpu/xe/xe_configfs.rst @@ -2,9 +2,15 @@ .. _xe_configfs: -============ +=========== Xe Configfs -============ +=========== .. kernel-doc:: drivers/gpu/drm/xe/xe_configfs.c :doc: Xe Configfs + +Internal API +============ + +.. kernel-doc:: drivers/gpu/drm/xe/xe_configfs.c + :internal: -- GitLab From 28b996ce73982a44fa86736ca0e3684cb1ae8b24 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Fri, 30 May 2025 15:56:27 +0200 Subject: [PATCH 181/902] drm/xe: remove unmatched xe_vm_unlock() from __xe_exec_queue_init() There is unmatched xe_vm_unlock() in the __xe_exec_queue_init(). Leftover from commit fbeaad071a98 ("drm/xe: Create LRC BO without VM") Fixes: fbeaad071a98 ("drm/xe: Create LRC BO without VM") Signed-off-by: Maciej Patelczyk Reviewed-by: Jonathan Cavitt Reviewed-by: Matthew Brost Signed-off-by: Niranjana Vishwanathapura Link: https://lore.kernel.org/r/20250530135627.2821612-1-maciej.patelczyk@intel.com --- drivers/gpu/drm/xe/xe_exec_queue.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 32c6923df7c37..fee22358cc09b 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -114,7 +114,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, static int __xe_exec_queue_init(struct xe_exec_queue *q) { - struct xe_vm *vm = q->vm; int i, err; u32 flags = 0; @@ -136,7 +135,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags); if (IS_ERR(q->lrc[i])) { err = PTR_ERR(q->lrc[i]); - goto err_unlock; + goto err_lrc; } } @@ -146,9 +145,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) return 0; -err_unlock: - if (vm) - xe_vm_unlock(vm); err_lrc: for (i = i - 1; i >= 0; --i) xe_lrc_put(q->lrc[i]); -- GitLab From ce2ae1b97ac399805d0904d894b8c3a104d93271 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 2 Jun 2025 12:33:23 +0200 Subject: [PATCH 182/902] drm/xe/vf: Introduce helpers to access GGTT configuration In upcoming patch we want to separate tile-oriented VF functions from GT-oriented functions and to allow the former access a GGTT configuration stored at GT level we need to provide some helpers. Signed-off-by: Michal Wajdeczko Cc: Tomasz Lis Reviewed-by: Tomasz Lis Link: https://lore.kernel.org/r/20250602103325.549-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 34 +++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 5 ++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 4ff7ae1a5f16c..acfb3b1b08324 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -561,6 +561,40 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) return gt->sriov.vf.self_config.lmem_size; } +/** + * xe_gt_sriov_vf_ggtt - VF GGTT configuration. + * @gt: the &xe_gt + * + * This function is for VF use only. + * + * Return: size of the GGTT assigned to VF. + */ +u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt) +{ + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, gt->sriov.vf.guc_version.major); + xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); + + return gt->sriov.vf.self_config.ggtt_size; +} + +/** + * xe_gt_sriov_vf_ggtt_base - VF GGTT base offset. + * @gt: the &xe_gt + * + * This function is for VF use only. + * + * Return: base offset of the GGTT assigned to VF. + */ +u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt) +{ + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, gt->sriov.vf.guc_version.major); + xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); + + return gt->sriov.vf.self_config.ggtt_base; +} + /** * xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration * @gt: the &xe_gt struct instance diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index 9db41afddd5a8..2f96ac0c5dcaf 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -20,7 +20,6 @@ int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); -s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt); void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); @@ -28,6 +27,10 @@ void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt); u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt); u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt); +u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt); +u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt); +s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt); + u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg); void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val); -- GitLab From eb9b34734c41a08166e41836bb6a47bc117c77a1 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 2 Jun 2025 12:33:24 +0200 Subject: [PATCH 183/902] drm/xe/vf: Move tile-related VF functions to separate file Some of our VF functions, even if they take a GT pointer, work only on primary GT and really are tile-related and would be better to keep them separate from the rest of true GT-oriented functions. Move them to a file and update to take a tile pointer instead. Signed-off-by: Michal Wajdeczko Cc: Tomasz Lis Reviewed-by: Tomasz Lis Link: https://lore.kernel.org/r/20250602103325.549-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/Makefile | 3 +- drivers/gpu/drm/xe/xe_ggtt.c | 4 +- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 245 -------------------------- drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 4 - drivers/gpu/drm/xe/xe_sriov_vf.c | 3 +- drivers/gpu/drm/xe/xe_tile_sriov_vf.c | 245 ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tile_sriov_vf.h | 18 ++ 7 files changed, 269 insertions(+), 253 deletions(-) create mode 100644 drivers/gpu/drm/xe/xe_tile_sriov_vf.c create mode 100644 drivers/gpu/drm/xe/xe_tile_sriov_vf.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index c5d6681645ede..01d231777901a 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -139,7 +139,8 @@ xe-y += \ xe_guc_relay.o \ xe_memirq.o \ xe_sriov.o \ - xe_sriov_vf.o + xe_sriov_vf.o \ + xe_tile_sriov_vf.o xe-$(CONFIG_PCI_IOV) += \ xe_gt_sriov_pf.o \ diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index af8e53014b874..b9a0fd5ccaba3 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -22,12 +22,12 @@ #include "xe_device.h" #include "xe_gt.h" #include "xe_gt_printk.h" -#include "xe_gt_sriov_vf.h" #include "xe_gt_tlb_invalidation.h" #include "xe_map.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_sriov.h" +#include "xe_tile_sriov_vf.h" #include "xe_wa.h" #include "xe_wopcm.h" @@ -258,7 +258,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) return err; if (IS_SRIOV_VF(xe)) { - err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0)); + err = xe_tile_sriov_vf_prepare_ggtt(ggtt->tile); if (err) return err; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index acfb3b1b08324..792523cfa6e67 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -613,168 +613,6 @@ s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) return config->ggtt_shift; } -static int vf_init_ggtt_balloons(struct xe_gt *gt) -{ - struct xe_tile *tile = gt_to_tile(gt); - struct xe_ggtt *ggtt = tile->mem.ggtt; - - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); - xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - - tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) - return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); - - tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); - return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); - } - - return 0; -} - -/** - * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range. - * @gt: the &xe_gt struct instance - * Return: 0 on success or a negative error code on failure. - */ -int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt) -{ - struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; - struct xe_tile *tile = gt_to_tile(gt); - struct xe_device *xe = gt_to_xe(gt); - u64 start, end; - int err; - - xe_gt_assert(gt, IS_SRIOV_VF(xe)); - xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - lockdep_assert_held(&tile->mem.ggtt->lock); - - if (!config->ggtt_size) - return -ENODATA; - - /* - * VF can only use part of the GGTT as allocated by the PF: - * - * WOPCM GUC_GGTT_TOP - * |<------------ Total GGTT size ------------------>| - * - * VF GGTT base -->|<- size ->| - * - * +--------------------+----------+-----------------+ - * |////////////////////| block |\\\\\\\\\\\\\\\\\| - * +--------------------+----------+-----------------+ - * - * |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| - */ - - start = xe_wopcm_size(xe); - end = config->ggtt_base; - if (end != start) { - err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], - start, end); - if (err) - return err; - } - - start = config->ggtt_base + config->ggtt_size; - end = GUC_GGTT_TOP; - if (end != start) { - err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1], - start, end); - if (err) { - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); - return err; - } - } - - return 0; -} - -static int vf_balloon_ggtt(struct xe_gt *gt) -{ - struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt; - int err; - - mutex_lock(&ggtt->lock); - err = xe_gt_sriov_vf_balloon_ggtt_locked(gt); - mutex_unlock(&ggtt->lock); - - return err; -} - -/** - * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. - * @gt: the &xe_gt struct instance - */ -void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt) -{ - struct xe_tile *tile = gt_to_tile(gt); - - xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); -} - -static void vf_deballoon_ggtt(struct xe_gt *gt) -{ - struct xe_tile *tile = gt_to_tile(gt); - - mutex_lock(&tile->mem.ggtt->lock); - xe_gt_sriov_vf_deballoon_ggtt_locked(gt); - mutex_unlock(&tile->mem.ggtt->lock); -} - -static void vf_fini_ggtt_balloons(struct xe_gt *gt) -{ - struct xe_tile *tile = gt_to_tile(gt); - - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); - xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); -} - -static void cleanup_ggtt(struct drm_device *drm, void *arg) -{ - struct xe_gt *gt = arg; - - vf_deballoon_ggtt(gt); - vf_fini_ggtt_balloons(gt); -} - -/** - * xe_gt_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. - * @gt: the &xe_gt - * - * This function is for VF use only. - * - * Return: 0 on success or a negative error code on failure. - */ -int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt) -{ - struct xe_tile *tile = gt_to_tile(gt); - struct xe_device *xe = tile_to_xe(tile); - int err; - - if (xe_gt_is_media_type(gt)) - return 0; - - err = vf_init_ggtt_balloons(gt); - if (err) - return err; - - err = vf_balloon_ggtt(gt); - if (err) { - vf_fini_ggtt_balloons(gt); - return err; - } - - return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, gt); -} - static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor) { u32 request[VF2PF_HANDSHAKE_REQUEST_MSG_LEN] = { @@ -870,89 +708,6 @@ failed: return err; } -/** - * DOC: GGTT nodes shifting during VF post-migration recovery - * - * The first fixup applied to the VF KMD structures as part of post-migration - * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved - * from range previously assigned to this VF, into newly provisioned area. - * The changes include balloons, which are resized accordingly. - * - * The balloon nodes are there to eliminate unavailable ranges from use: one - * reserves the GGTT area below the range for current VF, and another one - * reserves area above. - * - * Below is a GGTT layout of example VF, with a certain address range assigned to - * said VF, and inaccessible areas above and below: - * - * 0 4GiB - * |<--------------------------- Total GGTT size ----------------------------->| - * WOPCM GUC_TOP - * |<-------------- Area mappable by xe_ggtt instance ---------------->| - * - * +---+---------------------------------+----------+----------------------+---+ - * |\\\|/////////////////////////////////| VF mem |//////////////////////|\\\| - * +---+---------------------------------+----------+----------------------+---+ - * - * Hardware enforced access rules before migration: - * - * |<------- inaccessible for VF ------->||<-- inaccessible for VF ->| - * - * GGTT nodes used for tracking allocations: - * - * |<---------- balloon ------------>|<- nodes->|<----- balloon ------>| - * - * After the migration, GGTT area assigned to the VF might have shifted, either - * to lower or to higher address. But we expect the total size and extra areas to - * be identical, as migration can only happen between matching platforms. - * Below is an example of GGTT layout of the VF after migration. Content of the - * GGTT for VF has been moved to a new area, and we receive its address from GuC: - * - * +---+----------------------+----------+---------------------------------+---+ - * |\\\|//////////////////////| VF mem |/////////////////////////////////|\\\| - * +---+----------------------+----------+---------------------------------+---+ - * - * Hardware enforced access rules after migration: - * - * |<- inaccessible for VF -->||<------- inaccessible for VF ------->| - * - * So the VF has a new slice of GGTT assigned, and during migration process, the - * memory content was copied to that new area. But the &xe_ggtt nodes are still - * tracking allocations using the old addresses. The nodes within VF owned area - * have to be shifted, and balloon nodes need to be resized to properly mask out - * areas not owned by the VF. - * - * Fixed &xe_ggtt nodes used for tracking allocations: - * - * |<------ balloon ------>|<- nodes->|<----------- balloon ----------->| - * - * Due to use of GPU profiles, we do not expect the old and new GGTT ares to - * overlap; but our node shifting will fix addresses properly regardless. - */ - -/** - * xe_gt_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range. - * @gt: the &xe_gt struct instance - * @shift: the shift value - * - * Since Global GTT is not virtualized, each VF has an assigned range - * within the global space. This range might have changed during migration, - * which requires all memory addresses pointing to GGTT to be shifted. - */ -void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift) -{ - struct xe_tile *tile = gt_to_tile(gt); - struct xe_ggtt *ggtt = tile->mem.ggtt; - - xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - - mutex_lock(&ggtt->lock); - xe_gt_sriov_vf_deballoon_ggtt_locked(gt); - xe_ggtt_shift_nodes_locked(ggtt, shift); - xe_gt_sriov_vf_balloon_ggtt_locked(gt); - mutex_unlock(&ggtt->lock); -} - /** * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery, * or just mark that a GuC is ready for it. diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index 2f96ac0c5dcaf..6250fe774d89a 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -17,10 +17,6 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt); int xe_gt_sriov_vf_query_config(struct xe_gt *gt); int xe_gt_sriov_vf_connect(struct xe_gt *gt); int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); -int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); -int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); -void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); -void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index 46466932375c2..6526fe450e553 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -15,6 +15,7 @@ #include "xe_sriov.h" #include "xe_sriov_printk.h" #include "xe_sriov_vf.h" +#include "xe_tile_sriov_vf.h" /** * DOC: VF restore procedure in PF KMD and VF KMD @@ -211,7 +212,7 @@ static bool vf_post_migration_fixup_ggtt_nodes(struct xe_device *xe) shift = xe_gt_sriov_vf_ggtt_shift(gt); if (shift) { need_fixups = true; - xe_gt_sriov_vf_fixup_ggtt_nodes(gt, shift); + xe_tile_sriov_vf_fixup_ggtt_nodes(tile, shift); } } return need_fixups; diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_vf.c b/drivers/gpu/drm/xe/xe_tile_sriov_vf.c new file mode 100644 index 0000000000000..88e832894432b --- /dev/null +++ b/drivers/gpu/drm/xe/xe_tile_sriov_vf.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +#include + +#include "regs/xe_gtt_defs.h" + +#include "xe_assert.h" +#include "xe_ggtt.h" +#include "xe_gt_sriov_vf.h" +#include "xe_sriov.h" +#include "xe_tile_sriov_vf.h" +#include "xe_wopcm.h" + +static int vf_init_ggtt_balloons(struct xe_tile *tile) +{ + struct xe_ggtt *ggtt = tile->mem.ggtt; + + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); + + tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) + return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); + + tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); + return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); + } + + return 0; +} + +/** + * xe_tile_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range. + * @tile: the &xe_tile struct instance + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) +{ + u64 ggtt_base = xe_gt_sriov_vf_ggtt_base(tile->primary_gt); + u64 ggtt_size = xe_gt_sriov_vf_ggtt(tile->primary_gt); + struct xe_device *xe = tile_to_xe(tile); + u64 start, end; + int err; + + xe_tile_assert(tile, IS_SRIOV_VF(xe)); + xe_tile_assert(tile, ggtt_size); + lockdep_assert_held(&tile->mem.ggtt->lock); + + /* + * VF can only use part of the GGTT as allocated by the PF: + * + * WOPCM GUC_GGTT_TOP + * |<------------ Total GGTT size ------------------>| + * + * VF GGTT base -->|<- size ->| + * + * +--------------------+----------+-----------------+ + * |////////////////////| block |\\\\\\\\\\\\\\\\\| + * +--------------------+----------+-----------------+ + * + * |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| + */ + + start = xe_wopcm_size(xe); + end = ggtt_base; + if (end != start) { + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], + start, end); + if (err) + return err; + } + + start = ggtt_base + ggtt_size; + end = GUC_GGTT_TOP; + if (end != start) { + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1], + start, end); + if (err) { + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); + return err; + } + } + + return 0; +} + +static int vf_balloon_ggtt(struct xe_tile *tile) +{ + struct xe_ggtt *ggtt = tile->mem.ggtt; + int err; + + mutex_lock(&ggtt->lock); + err = xe_tile_sriov_vf_balloon_ggtt_locked(tile); + mutex_unlock(&ggtt->lock); + + return err; +} + +/** + * xe_tile_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. + * @tile: the &xe_tile struct instance + */ +void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile) +{ + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); + + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); +} + +static void vf_deballoon_ggtt(struct xe_tile *tile) +{ + mutex_lock(&tile->mem.ggtt->lock); + xe_tile_sriov_vf_deballoon_ggtt_locked(tile); + mutex_unlock(&tile->mem.ggtt->lock); +} + +static void vf_fini_ggtt_balloons(struct xe_tile *tile) +{ + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); + + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); +} + +static void cleanup_ggtt(struct drm_device *drm, void *arg) +{ + struct xe_tile *tile = arg; + + vf_deballoon_ggtt(tile); + vf_fini_ggtt_balloons(tile); +} + +/** + * xe_tile_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. + * @tile: the &xe_tile + * + * This function is for VF use only. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile) +{ + struct xe_device *xe = tile_to_xe(tile); + int err; + + err = vf_init_ggtt_balloons(tile); + if (err) + return err; + + err = vf_balloon_ggtt(tile); + if (err) { + vf_fini_ggtt_balloons(tile); + return err; + } + + return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, tile); +} + +/** + * DOC: GGTT nodes shifting during VF post-migration recovery + * + * The first fixup applied to the VF KMD structures as part of post-migration + * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved + * from range previously assigned to this VF, into newly provisioned area. + * The changes include balloons, which are resized accordingly. + * + * The balloon nodes are there to eliminate unavailable ranges from use: one + * reserves the GGTT area below the range for current VF, and another one + * reserves area above. + * + * Below is a GGTT layout of example VF, with a certain address range assigned to + * said VF, and inaccessible areas above and below: + * + * 0 4GiB + * |<--------------------------- Total GGTT size ----------------------------->| + * WOPCM GUC_TOP + * |<-------------- Area mappable by xe_ggtt instance ---------------->| + * + * +---+---------------------------------+----------+----------------------+---+ + * |\\\|/////////////////////////////////| VF mem |//////////////////////|\\\| + * +---+---------------------------------+----------+----------------------+---+ + * + * Hardware enforced access rules before migration: + * + * |<------- inaccessible for VF ------->||<-- inaccessible for VF ->| + * + * GGTT nodes used for tracking allocations: + * + * |<---------- balloon ------------>|<- nodes->|<----- balloon ------>| + * + * After the migration, GGTT area assigned to the VF might have shifted, either + * to lower or to higher address. But we expect the total size and extra areas to + * be identical, as migration can only happen between matching platforms. + * Below is an example of GGTT layout of the VF after migration. Content of the + * GGTT for VF has been moved to a new area, and we receive its address from GuC: + * + * +---+----------------------+----------+---------------------------------+---+ + * |\\\|//////////////////////| VF mem |/////////////////////////////////|\\\| + * +---+----------------------+----------+---------------------------------+---+ + * + * Hardware enforced access rules after migration: + * + * |<- inaccessible for VF -->||<------- inaccessible for VF ------->| + * + * So the VF has a new slice of GGTT assigned, and during migration process, the + * memory content was copied to that new area. But the &xe_ggtt nodes are still + * tracking allocations using the old addresses. The nodes within VF owned area + * have to be shifted, and balloon nodes need to be resized to properly mask out + * areas not owned by the VF. + * + * Fixed &xe_ggtt nodes used for tracking allocations: + * + * |<------ balloon ------>|<- nodes->|<----------- balloon ----------->| + * + * Due to use of GPU profiles, we do not expect the old and new GGTT ares to + * overlap; but our node shifting will fix addresses properly regardless. + */ + +/** + * xe_tile_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range. + * @tile: the &xe_tile struct instance + * @shift: the shift value + * + * Since Global GTT is not virtualized, each VF has an assigned range + * within the global space. This range might have changed during migration, + * which requires all memory addresses pointing to GGTT to be shifted. + */ +void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift) +{ + struct xe_ggtt *ggtt = tile->mem.ggtt; + + mutex_lock(&ggtt->lock); + + xe_tile_sriov_vf_deballoon_ggtt_locked(tile); + xe_ggtt_shift_nodes_locked(ggtt, shift); + xe_tile_sriov_vf_balloon_ggtt_locked(tile); + + mutex_unlock(&ggtt->lock); +} diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_vf.h b/drivers/gpu/drm/xe/xe_tile_sriov_vf.h new file mode 100644 index 0000000000000..93eb043171e83 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_tile_sriov_vf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef _XE_TILE_SRIOV_VF_H_ +#define _XE_TILE_SRIOV_VF_H_ + +#include + +struct xe_tile; + +int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile); +int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile); +void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile); +void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift); + +#endif -- GitLab From c12c729e97508f4cd073a7cd5150d7512fa84f34 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 2 Jun 2025 12:33:25 +0200 Subject: [PATCH 184/902] drm/xe/vf: Add sanity check for GGTT configuration The VF GGTT configuration was prepared by the PF, which should be trusted, was obtained from the GuC, which likely already did some sanity checks too, but since it's a received data, we should have our own sanity checks to detect early any misconfiguration. Signed-off-by: Michal Wajdeczko Cc: Satyanarayana K V P Reviewed-by: Satyanarayana K V P Link: https://lore.kernel.org/r/20250602103325.549-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_tile_sriov_vf.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_vf.c b/drivers/gpu/drm/xe/xe_tile_sriov_vf.c index 88e832894432b..f221dbed16f09 100644 --- a/drivers/gpu/drm/xe/xe_tile_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_tile_sriov_vf.c @@ -11,6 +11,7 @@ #include "xe_ggtt.h" #include "xe_gt_sriov_vf.h" #include "xe_sriov.h" +#include "xe_sriov_printk.h" #include "xe_tile_sriov_vf.h" #include "xe_wopcm.h" @@ -44,6 +45,7 @@ int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) u64 ggtt_base = xe_gt_sriov_vf_ggtt_base(tile->primary_gt); u64 ggtt_size = xe_gt_sriov_vf_ggtt(tile->primary_gt); struct xe_device *xe = tile_to_xe(tile); + u64 wopcm = xe_wopcm_size(xe); u64 start, end; int err; @@ -66,7 +68,14 @@ int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) * |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| */ - start = xe_wopcm_size(xe); + if (ggtt_base < wopcm || ggtt_base > GUC_GGTT_TOP || + ggtt_size > GUC_GGTT_TOP - ggtt_base) { + xe_sriov_err(xe, "tile%u: Invalid GGTT configuration: %#llx-%#llx\n", + tile->id, ggtt_base, ggtt_base + ggtt_size - 1); + return -ERANGE; + } + + start = wopcm; end = ggtt_base; if (end != start) { err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], -- GitLab From ce924116e43ffbfa544d82976c4b9d11bcde9334 Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Wed, 28 May 2025 12:15:56 +0530 Subject: [PATCH 185/902] drm/i915/display: Fix u32 overflow in SNPS PHY HDMI PLL setup When configuring the HDMI PLL, calculations use DIV_ROUND_UP_ULL and DIV_ROUND_DOWN_ULL macros, which internally rely on do_div. However, do_div expects a 32-bit (u32) divisor, and at higher data rates, the divisor can exceed this limit. This leads to incorrect division results and ultimately misconfigured PLL values. This fix replaces do_div calls with div64_base64 calls where diviser can exceed u32 limit. Fixes: 5947642004bf ("drm/i915/display: Add support for SNPS PHY HDMI PLL algorithm for DG2") Cc: Ankit Nautiyal Cc: Suraj Kandpal Cc: Jani Nikula Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://lore.kernel.org/r/20250528064557.4172149-1-dibin.moolakadan.subrahmanian@intel.com --- .../gpu/drm/i915/display/intel_snps_hdmi_pll.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c index c6321dafef4f3..74bb3bedf30f5 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c +++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c @@ -41,12 +41,12 @@ static s64 interp(s64 x, s64 x1, s64 x2, s64 y1, s64 y2) { s64 dydx; - dydx = DIV_ROUND_UP_ULL((y2 - y1) * 100000, (x2 - x1)); + dydx = DIV64_U64_ROUND_UP((y2 - y1) * 100000, (x2 - x1)); - return (y1 + DIV_ROUND_UP_ULL(dydx * (x - x1), 100000)); + return (y1 + DIV64_U64_ROUND_UP(dydx * (x - x1), 100000)); } -static void get_ana_cp_int_prop(u32 vco_clk, +static void get_ana_cp_int_prop(u64 vco_clk, u32 refclk_postscalar, int mpll_ana_v2i, int c, int a, @@ -115,16 +115,16 @@ static void get_ana_cp_int_prop(u32 vco_clk, CURVE0_MULTIPLIER)); scaled_interpolated_sqrt = - int_sqrt(DIV_ROUND_UP_ULL(interpolated_product, vco_div_refclk_float) * + int_sqrt(DIV64_U64_ROUND_UP(interpolated_product, vco_div_refclk_float) * DIV_ROUND_DOWN_ULL(1000000000000ULL, 55)); /* Scale vco_div_refclk for ana_cp_int */ scaled_vco_div_refclk2 = DIV_ROUND_UP_ULL(vco_div_refclk_float, 1000000); - adjusted_vco_clk2 = 1460281 * DIV_ROUND_UP_ULL(scaled_interpolated_sqrt * + adjusted_vco_clk2 = 1460281 * DIV64_U64_ROUND_UP(scaled_interpolated_sqrt * scaled_vco_div_refclk2, curve_1_interpolated); - *ana_cp_prop = DIV_ROUND_UP_ULL(adjusted_vco_clk2, curve_2_scaled2); + *ana_cp_prop = DIV64_U64_ROUND_UP(adjusted_vco_clk2, curve_2_scaled2); *ana_cp_prop = max(1, min(*ana_cp_prop, 127)); } @@ -165,10 +165,10 @@ static void compute_hdmi_tmds_pll(u64 pixel_clock, u32 refclk, /* Select appropriate v2i point */ if (datarate <= INTEL_SNPS_PHY_HDMI_9999MHZ) { mpll_ana_v2i = 2; - tx_clk_div = ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_9999MHZ, datarate)); + tx_clk_div = ilog2(div64_u64(INTEL_SNPS_PHY_HDMI_9999MHZ, datarate)); } else { mpll_ana_v2i = 3; - tx_clk_div = ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_16GHZ, datarate)); + tx_clk_div = ilog2(div64_u64(INTEL_SNPS_PHY_HDMI_16GHZ, datarate)); } vco_clk = (datarate << tx_clk_div) >> 1; -- GitLab From 04e32c392acea62cda89dd2c848e76295b0024bc Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 11 May 2025 20:18:48 -0400 Subject: [PATCH 186/902] drm/amd/display: [FW Promotion] Release 0.1.11.0 Refactoring some DMUB related structs and enum. Acked-by: Wayne Lin Signed-off-by: Taimur Hassan Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index b66bd10cdc9b8..57fa05bddb458 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2139,6 +2139,11 @@ union dmub_cmd_fams2_config { } stream_v1; //v1 }; +struct dmub_fams2_config_v2 { + struct dmub_cmd_fams2_global_config global; + struct dmub_fams2_stream_static_state_v1 stream_v1[DMUB_MAX_STREAMS]; //v1 +}; + /** * DMUB rb command definition for FAMS2 (merged SubVP, FPO, Legacy) */ @@ -2147,6 +2152,22 @@ struct dmub_rb_cmd_fams2 { union dmub_cmd_fams2_config config; }; +/** + * Indirect buffer descriptor + */ +struct dmub_ib_data { + union dmub_addr src; // location of indirect buffer in memory + uint16_t size; // indirect buffer size in bytes +}; + +/** + * DMUB rb command definition for commands passed over indirect buffer + */ +struct dmub_rb_cmd_ib { + struct dmub_cmd_header header; + struct dmub_ib_data ib_data; +}; + /** * enum dmub_cmd_idle_opt_type - Idle optimization command type. */ @@ -2170,6 +2191,11 @@ enum dmub_cmd_idle_opt_type { * DCN hardware notify power state. */ DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE = 3, + + /** + * DCN notify to release HW. + */ + DMUB_CMD__IDLE_OPT_RELEASE_HW = 4, }; /** @@ -2931,8 +2957,9 @@ enum dmub_cmd_fams_type { */ DMUB_CMD__FAMS_SET_MANUAL_TRIGGER = 3, DMUB_CMD__FAMS2_CONFIG = 4, - DMUB_CMD__FAMS2_DRR_UPDATE = 5, - DMUB_CMD__FAMS2_FLIP = 6, + DMUB_CMD__FAMS2_IB_CONFIG = 5, + DMUB_CMD__FAMS2_DRR_UPDATE = 6, + DMUB_CMD__FAMS2_FLIP = 7, }; /** @@ -5926,8 +5953,11 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__PSP_ASSR_ENABLE command. */ struct dmub_rb_cmd_assr_enable assr_enable; + struct dmub_rb_cmd_fams2 fams2_config; + struct dmub_rb_cmd_ib ib_fams2_config; + struct dmub_rb_cmd_fams2_drr_update fams2_drr_update; struct dmub_rb_cmd_fams2_flip fams2_flip; -- GitLab From 6123117005d9e6368a625a7164acebd65a304f41 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 13 May 2025 15:00:47 -0400 Subject: [PATCH 187/902] drm/amd/display: Re-order FAMS2 sub commands [Why & How] New enums need to be added to the end to avoid back compat issues. Reviewed-by: Dillon Varone Signed-off-by: Alvin Lee Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 57fa05bddb458..202904af4682a 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2957,9 +2957,9 @@ enum dmub_cmd_fams_type { */ DMUB_CMD__FAMS_SET_MANUAL_TRIGGER = 3, DMUB_CMD__FAMS2_CONFIG = 4, - DMUB_CMD__FAMS2_IB_CONFIG = 5, - DMUB_CMD__FAMS2_DRR_UPDATE = 6, - DMUB_CMD__FAMS2_FLIP = 7, + DMUB_CMD__FAMS2_DRR_UPDATE = 5, + DMUB_CMD__FAMS2_FLIP = 6, + DMUB_CMD__FAMS2_IB_CONFIG = 7, }; /** -- GitLab From b6943f4adc957840242dcaa5919c38fd5c70ccf9 Mon Sep 17 00:00:00 2001 From: Austin Zheng Date: Mon, 14 Apr 2025 16:49:13 -0400 Subject: [PATCH 188/902] drm/amd/display: DML21 Fixes - Store state related info inside mode_lib. - Fix bad DCFCLK deep sleep - Update FAMS structure in DMUB header Reviewed-by: Alvin Lee Signed-off-by: Austin Zheng Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml21/inc/dml_top.h | 1 - .../display/dc/dml2/dml21/inc/dml_top_types.h | 10 ++- .../src/dml2_core/dml2_core_dcn4_calcs.c | 7 +- .../src/dml2_core/dml2_core_shared_types.h | 82 ++++++++++++++++++- .../dml2/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c | 3 - .../src/inc/dml2_internal_shared_types.h | 10 ++- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 18 +++- 7 files changed, 116 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top.h index c047d56527c47..a64ec4dcf11ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top.h @@ -43,5 +43,4 @@ bool dml2_build_mode_programming(struct dml2_build_mode_programming_in_out *in_o */ bool dml2_build_mcache_programming(struct dml2_build_mcache_programming_in_out *in_out); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h index 0dbf886d89261..bcb99a1550111 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h @@ -279,7 +279,10 @@ struct dml2_per_stream_programming { } phantom_stream; union dmub_cmd_fams2_config fams2_base_params; - union dmub_cmd_fams2_config fams2_sub_params; + union { + union dmub_cmd_fams2_config fams2_sub_params; + union dmub_fams2_stream_static_sub_state_v2 fams2_sub_params_v2; + }; }; //----------------- @@ -674,9 +677,14 @@ struct dml2_display_cfg_programming { // unlimited # of mcache struct dml2_mcache_surface_allocation non_optimized_mcache_allocation[DML2_MAX_PLANES]; + bool failed_prefetch; + bool failed_uclk_pstate; bool failed_mcache_validation; bool failed_dpmm; bool failed_mode_programming; + bool failed_mode_programming_dcfclk; + bool failed_mode_programming_prefetch; + bool failed_mode_programming_flip; bool failed_map_watermarks; } informative; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index c4dad7164d314..0addef1f844e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -7905,6 +7905,7 @@ static noinline_for_stack void dml_core_ms_prefetch_check(struct dml2_core_inter } + static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out_params) { struct dml2_core_internal_display_mode_lib *mode_lib = in_out_params->mode_lib; @@ -11880,7 +11881,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex } //Maximum Bandwidth Used - s->TotalWRBandwidth = 0; + mode_lib->mp.TotalWRBandwidth = 0; for (k = 0; k < display_cfg->num_streams; ++k) { s->WRBandwidth = 0; if (display_cfg->stream_descriptors[k].writeback.active_writebacks_per_stream > 0) { @@ -11889,7 +11890,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex (display_cfg->stream_descriptors[k].timing.h_total * display_cfg->stream_descriptors[k].writeback.writeback_stream[0].input_height / ((double)display_cfg->stream_descriptors[k].timing.pixel_clock_khz / 1000)) * (display_cfg->stream_descriptors[k].writeback.writeback_stream[0].pixel_format == dml2_444_32 ? 4.0 : 8.0); - s->TotalWRBandwidth = s->TotalWRBandwidth + s->WRBandwidth; + mode_lib->mp.TotalWRBandwidth = mode_lib->mp.TotalWRBandwidth + s->WRBandwidth; } } @@ -13243,7 +13244,7 @@ void dml2_core_calcs_get_informative(const struct dml2_core_internal_display_mod out->informative.misc.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->mp.DisplayPipeLineDeliveryTimeLumaPrefetch[k]; out->informative.misc.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = mode_lib->mp.DisplayPipeLineDeliveryTimeChromaPrefetch[k]; - out->informative.misc.WritebackRequiredBandwidth = mode_lib->scratch.dml_core_mode_programming_locals.TotalWRBandwidth / 1000.0; + out->informative.misc.WritebackRequiredBandwidth = mode_lib->mp.TotalWRBandwidth / 1000.0; out->informative.misc.WritebackAllowDRAMClockChangeEndPosition[k] = mode_lib->mp.WritebackAllowDRAMClockChangeEndPosition[k]; out->informative.misc.WritebackAllowFCLKChangeEndPosition[k] = mode_lib->mp.WritebackAllowFCLKChangeEndPosition[k]; out->informative.misc.DSCCLK_calculated[k] = mode_lib->mp.DSCCLK[k]; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h index bdee6ad7bc59c..5f5b15b478e32 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h @@ -329,6 +329,7 @@ struct dml2_core_internal_mode_support_info { bool temp_read_or_ppt_support; struct dml2_core_internal_watermarks watermarks; + bool dcfclk_support; }; struct dml2_core_internal_mode_support { @@ -350,9 +351,11 @@ struct dml2_core_internal_mode_support { double SOCCLK; /// min_clocks.dcn4x.dispclk_khz, &state_table->dispclk); - if (result) - result = round_up_to_next_dpm(&display_cfg->min_clocks.dcn4x.deepsleep_dcfclk_khz, &state_table->dcfclk); - for (i = 0; i < DML2_MAX_DCN_PIPES; i++) { if (result) result = round_up_to_next_dpm(&display_cfg->plane_programming[i].min_clocks.dcn4x.dppclk_khz, &state_table->dppclk); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h index 00688b9f1df4c..d52aa82283b36 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h @@ -202,6 +202,8 @@ struct dml2_core_mode_support_result { } active; unsigned int dispclk_khz; + unsigned int dpprefclk_khz; + unsigned int dtbrefclk_khz; unsigned int dcfclk_deepsleep_khz; unsigned int socclk_khz; @@ -446,13 +448,17 @@ struct dml2_core_internal_state_intermediates { }; struct dml2_core_mode_support_locals { - struct dml2_core_calcs_mode_support_ex mode_support_ex_params; + union { + struct dml2_core_calcs_mode_support_ex mode_support_ex_params; + }; struct dml2_display_cfg svp_expanded_display_cfg; struct dml2_calculate_mcache_allocation_in_out calc_mcache_allocation_params; }; struct dml2_core_mode_programming_locals { - struct dml2_core_calcs_mode_programming_ex mode_programming_ex_params; + union { + struct dml2_core_calcs_mode_programming_ex mode_programming_ex_params; + }; struct dml2_display_cfg svp_expanded_display_cfg; }; diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 202904af4682a..346d843b45bf4 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -104,6 +104,14 @@ */ #define DMUB_MAX_FPO_STREAMS 4 +/* Define to ensure that the "common" members always appear in the same + * order in different structs for back compat purposes + */ +#define COMMON_STREAM_STATIC_SUB_STATE \ + struct dmub_fams2_cmd_legacy_stream_static_state legacy; \ + struct dmub_fams2_cmd_subvp_stream_static_state subvp; \ + struct dmub_fams2_cmd_drr_stream_static_state drr; + /* Maximum number of streams on any ASIC. */ #define DMUB_MAX_STREAMS 6 @@ -2021,11 +2029,13 @@ union dmub_fams2_stream_static_sub_state { }; //v0 union dmub_fams2_cmd_stream_static_sub_state { - struct dmub_fams2_cmd_legacy_stream_static_state legacy; - struct dmub_fams2_cmd_subvp_stream_static_state subvp; - struct dmub_fams2_cmd_drr_stream_static_state drr; + COMMON_STREAM_STATIC_SUB_STATE }; //v1 +union dmub_fams2_stream_static_sub_state_v2 { + COMMON_STREAM_STATIC_SUB_STATE +}; //v2 + struct dmub_fams2_stream_static_state { enum fams2_stream_type type; uint32_t otg_vline_time_ns; @@ -2091,7 +2101,7 @@ struct dmub_fams2_cmd_stream_static_base_state { struct dmub_fams2_stream_static_state_v1 { struct dmub_fams2_cmd_stream_static_base_state base; - union dmub_fams2_cmd_stream_static_sub_state sub_state; + union dmub_fams2_stream_static_sub_state_v2 sub_state; }; //v1 /** -- GitLab From 0a91b4f300de870746a21730135376611aa85479 Mon Sep 17 00:00:00 2001 From: Camille Cho Date: Wed, 7 May 2025 19:00:54 +0800 Subject: [PATCH 189/902] drm/amd/display: Support OLED SDR with AMD ABC [Why] Nits programming for SDR panel is only supported by VESA ABC. [How] 1. Loose nits programming for OLED SDR panel with AMD ABC. 2. We support two ABC methods. Disable one before we program the other in case panel freaks out. 3. Update HDR judgement in setBR with a solider condition. Reviewed-by: Krunoslav Kovac Signed-off-by: Camille Cho Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../link/protocols/link_edp_panel_control.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index da74c2b5854f3..035795042a01d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -173,6 +173,15 @@ bool edp_set_backlight_level_nits(struct dc_link *link, target_luminance = (struct target_luminance_value *)&backlight_millinits; + //make sure we disable AMD ABC first. + core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL, + &backlight_enable, sizeof(uint8_t)); + if (backlight_enable) { + backlight_enable = 0; + core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL, + &backlight_enable, 1); + } + core_link_read_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &backlight_enable, sizeof(uint8_t)); @@ -193,10 +202,22 @@ bool edp_set_backlight_level_nits(struct dc_link *link, *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms; uint8_t backlight_control = isHDR ? 1 : 0; + uint8_t backlight_enable = 0; + // OLEDs have no PWM, they can only use AUX if (link->dpcd_sink_ext_caps.bits.oled == 1) backlight_control = 1; + //make sure we disable VESA ABC first. + core_link_read_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, + &backlight_enable, sizeof(uint8_t)); + + if (backlight_enable & DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE) { + backlight_enable &= ~DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE; + core_link_write_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, + &backlight_enable, sizeof(backlight_enable)); + } + if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, (uint8_t *)(&dpcd_backlight_set), sizeof(dpcd_backlight_set)) != DC_OK) -- GitLab From 71e17aedb465a8b2b7b6260d9fc85dddec04b341 Mon Sep 17 00:00:00 2001 From: Yihan Zhu Date: Wed, 7 May 2025 14:25:07 -0400 Subject: [PATCH 190/902] drm/amd/display: move RMCM programming [WHY & HOW] Move only RMCM programming outside of dcn401. Extended HW definition in dc for memory layout to extend support. Reviewed-by: Jun Lei Signed-off-by: Yihan Zhu Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 31 ++ drivers/gpu/drm/amd/display/dc/dc_types.h | 2 - .../dc/dml2/dml21/dml21_translation_helper.c | 4 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 - .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 288 +----------------- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 8 - .../drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c | 3 - 7 files changed, 42 insertions(+), 302 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1d917be36fc43..a63f7fe277fa2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -67,6 +67,7 @@ struct dmub_notification; #define MIN_VIEWPORT_SIZE 12 #define MAX_NUM_EDP 2 #define MAX_HOST_ROUTERS_NUM 2 +#define MAX_SUPPORTED_FORMATS 7 /* Display Core Interfaces */ struct dc_versions { @@ -192,6 +193,34 @@ struct dpp_color_caps { struct rom_curve_caps ogam_rom_caps; }; +/* Below structure is to describe the HW support for mem layout, extend support + range to match what OS could handle in the roadmap */ +struct lut3d_caps { + uint32_t dma_3d_lut : 1; /*< DMA mode support for 3D LUT */ + struct { + uint32_t swizzle_3d_rgb : 1; + uint32_t swizzle_3d_bgr : 1; + uint32_t linear_1d : 1; + } mem_layout_support; + struct { + uint32_t unorm_12msb : 1; + uint32_t unorm_12lsb : 1; + uint32_t float_fp1_5_10 : 1; + } mem_format_support; + struct { + uint32_t order_rgba : 1; + uint32_t order_bgra : 1; + } mem_pixel_order_support; + /*< size options are 9, 17, 33, 45, 65 */ + struct { + uint32_t dim_9 : 1; /* 3D LUT support for 9x9x9 */ + uint32_t dim_17 : 1; /* 3D LUT support for 17x17x17 */ + uint32_t dim_33 : 1; /* 3D LUT support for 33x33x33 */ + uint32_t dim_45 : 1; /* 3D LUT support for 45x45x45 */ + uint32_t dim_65 : 1; /* 3D LUT support for 65x65x65 */ + } lut_dim_caps; +}; + /** * struct mpc_color_caps - color pipeline capabilities for multiple pipe and * plane combined blocks @@ -211,6 +240,8 @@ struct mpc_color_caps { uint16_t num_3dluts : 3; uint16_t shared_3d_lut:1; struct rom_curve_caps ogam_rom_caps; + struct lut3d_caps mcm_3d_lut_caps; + struct lut3d_caps rmcm_3d_lut_caps; }; /** diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index a4cd0eb39a3af..794b5f30d252f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1255,7 +1255,6 @@ enum dc_cm2_gpu_mem_layout { enum dc_cm2_gpu_mem_pixel_component_order { DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, - DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA }; enum dc_cm2_gpu_mem_format { @@ -1277,7 +1276,6 @@ struct dc_cm2_gpu_mem_format_parameters { enum dc_cm2_gpu_mem_size { DC_CM2_GPU_MEM_SIZE_171717, - DC_CM2_GPU_MEM_SIZE_333333, DC_CM2_GPU_MEM_SIZE_TRANSFORMED, }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c index d47cacfdb6955..8b45b0bcc396d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c @@ -888,10 +888,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm case DC_CM2_GPU_MEM_SIZE_171717: plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube; break; - case DC_CM2_GPU_MEM_SIZE_333333: - plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube; - break; case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: + default: //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined break; } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index c277df12c8172..4ea3b4ad179bf 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -1971,14 +1971,6 @@ static void dcn20_program_pipe( pipe_ctx->plane_state->update_flags.bits.hdr_mult)) hws->funcs.set_hdr_multiplier(pipe_ctx); - if (hws->funcs.populate_mcm_luts) { - if (pipe_ctx->plane_state) { - hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts, - pipe_ctx->plane_state->lut_bank_a); - pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a; - } - } - if (pipe_ctx->plane_state && (pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || pipe_ctx->plane_state->update_flags.bits.gamma_change || diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index c4177a9a662fa..ea28c75fdacec 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -2,6 +2,8 @@ // // Copyright 2024 Advanced Micro Devices, Inc. + +#include "os_types.h" #include "dm_services.h" #include "basics/dc_common.h" #include "dm_helpers.h" @@ -396,249 +398,6 @@ static void dcn401_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ct } } -static void dcn401_set_mcm_location_post_blend(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bPostBlend) -{ - struct mpc *mpc = dc->res_pool->mpc; - int mpcc_id = pipe_ctx->plane_res.hubp->inst; - - if (!pipe_ctx->plane_state) - return; - - mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); - pipe_ctx->plane_state->mcm_location = (bPostBlend) ? - MPCC_MOVABLE_CM_LOCATION_AFTER : - MPCC_MOVABLE_CM_LOCATION_BEFORE; -} - -static void dc_get_lut_mode( - enum dc_cm2_gpu_mem_layout layout, - enum hubp_3dlut_fl_mode *mode, - enum hubp_3dlut_fl_addressing_mode *addr_mode) -{ - switch (layout) { - case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: - *mode = hubp_3dlut_fl_mode_native_1; - *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; - break; - case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR: - *mode = hubp_3dlut_fl_mode_native_2; - *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; - break; - case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR: - *mode = hubp_3dlut_fl_mode_transform; - *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; - break; - default: - *mode = hubp_3dlut_fl_mode_disable; - *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; - break; - } -} - -static void dc_get_lut_format( - enum dc_cm2_gpu_mem_format dc_format, - enum hubp_3dlut_fl_format *format) -{ - switch (dc_format) { - case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: - *format = hubp_3dlut_fl_format_unorm_12msb_bitslice; - break; - case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: - *format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; - break; - case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10: - *format = hubp_3dlut_fl_format_float_fp1_5_10; - break; - } -} - -static void dc_get_lut_xbar( - enum dc_cm2_gpu_mem_pixel_component_order order, - enum hubp_3dlut_fl_crossbar_bit_slice *cr_r, - enum hubp_3dlut_fl_crossbar_bit_slice *y_g, - enum hubp_3dlut_fl_crossbar_bit_slice *cb_b) -{ - switch (order) { - case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: - *cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; - *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; - break; - case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA: - *cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; - *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; - break; - } -} - -static void dc_get_lut_width( - enum dc_cm2_gpu_mem_size size, - enum hubp_3dlut_fl_width *width) -{ - switch (size) { - case DC_CM2_GPU_MEM_SIZE_333333: - *width = hubp_3dlut_fl_width_33; - break; - case DC_CM2_GPU_MEM_SIZE_171717: - *width = hubp_3dlut_fl_width_17; - break; - case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: - *width = hubp_3dlut_fl_width_transformed; - break; - } -} -static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc) -{ - if (mpc->funcs->rmcm.update_3dlut_fast_load_select && - mpc->funcs->rmcm.program_lut_read_write_control && - hubp->funcs->hubp_program_3dlut_fl_addr && - mpc->funcs->rmcm.program_bit_depth && - hubp->funcs->hubp_program_3dlut_fl_mode && - hubp->funcs->hubp_program_3dlut_fl_addressing_mode && - hubp->funcs->hubp_program_3dlut_fl_format && - hubp->funcs->hubp_update_3dlut_fl_bias_scale && - mpc->funcs->rmcm.program_bias_scale && - hubp->funcs->hubp_program_3dlut_fl_crossbar && - hubp->funcs->hubp_program_3dlut_fl_width && - mpc->funcs->rmcm.update_3dlut_fast_load_select && - mpc->funcs->rmcm.populate_lut && - mpc->funcs->rmcm.program_lut_mode && - hubp->funcs->hubp_enable_3dlut_fl && - mpc->funcs->rmcm.enable_3dlut_fl) - return true; - - return false; -} - -bool dcn401_program_rmcm_luts( - struct hubp *hubp, - struct pipe_ctx *pipe_ctx, - enum dc_cm2_transfer_func_source lut3d_src, - struct dc_cm2_func_luts *mcm_luts, - struct mpc *mpc, - bool lut_bank_a, - int mpcc_id) -{ - struct dpp *dpp_base = pipe_ctx->plane_res.dpp; - union mcm_lut_params m_lut_params; - enum MCM_LUT_XABLE shaper_xable, lut3d_xable = MCM_LUT_DISABLE, lut1d_xable; - enum hubp_3dlut_fl_mode mode; - enum hubp_3dlut_fl_addressing_mode addr_mode; - enum hubp_3dlut_fl_format format = 0; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0; - enum hubp_3dlut_fl_width width = 0; - struct dc *dc = hubp->ctx->dc; - - bool bypass_rmcm_3dlut = false; - bool bypass_rmcm_shaper = false; - - dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); - - /* 3DLUT */ - switch (lut3d_src) { - case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: - memset(&m_lut_params, 0, sizeof(m_lut_params)); - // Don't know what to do in this case. - //case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: - break; - case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: - dc_get_lut_width(mcm_luts->lut3d_data.gpu_mem_params.size, &width); - if (!dc_is_rmcm_3dlut_supported(hubp, mpc) || - !mpc->funcs->rmcm.is_config_supported(width)) - return false; - - //0. disable fl on mpc - mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xF); - - //1. power down the block - mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false); - - //2. program RMCM - //2a. 3dlut reg programming - mpc->funcs->rmcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, - (!bypass_rmcm_3dlut) && lut3d_xable != MCM_LUT_DISABLE, mpcc_id); - - hubp->funcs->hubp_program_3dlut_fl_addr(hubp, - mcm_luts->lut3d_data.gpu_mem_params.addr); - - mpc->funcs->rmcm.program_bit_depth(mpc, - mcm_luts->lut3d_data.gpu_mem_params.bit_depth, mpcc_id); - - // setting native or transformed mode, - dc_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, &mode, &addr_mode); - - //these program the mcm 3dlut - hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode); - - hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode); - - //seems to be only for the MCM - dc_get_lut_format(mcm_luts->lut3d_data.gpu_mem_params.format_params.format, &format); - hubp->funcs->hubp_program_3dlut_fl_format(hubp, format); - - mpc->funcs->rmcm.program_bias_scale(mpc, - mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias, - mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale, - mpcc_id); - hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp, - mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias, - mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale); - - dc_get_lut_xbar( - mcm_luts->lut3d_data.gpu_mem_params.component_order, - &crossbar_bit_slice_cr_r, - &crossbar_bit_slice_y_g, - &crossbar_bit_slice_cb_b); - - hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, - crossbar_bit_slice_cr_r, - crossbar_bit_slice_y_g, - crossbar_bit_slice_cb_b); - - mpc->funcs->rmcm.program_3dlut_size(mpc, width, mpcc_id); - - mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); - - //2b. shaper reg programming - memset(&m_lut_params, 0, sizeof(m_lut_params)); - - if (mcm_luts->shaper->type == TF_TYPE_HWPWL) { - m_lut_params.pwl = &mcm_luts->shaper->pwl; - } else if (mcm_luts->shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { - ASSERT(false); - cm_helper_translate_curve_to_hw_format( - dc->ctx, - mcm_luts->shaper, - &dpp_base->regamma_params, true); - m_lut_params.pwl = &dpp_base->regamma_params; - } - if (m_lut_params.pwl) { - mpc->funcs->rmcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); - mpc->funcs->rmcm.program_lut_mode(mpc, !bypass_rmcm_shaper, lut_bank_a, mpcc_id); - } else { - //RMCM 3dlut won't work without its shaper - return false; - } - - //3. Select the hubp connected to this RMCM - hubp->funcs->hubp_enable_3dlut_fl(hubp, true); - mpc->funcs->rmcm.enable_3dlut_fl(mpc, true, mpcc_id); - - //4. power on the block - if (m_lut_params.pwl) - mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true); - - break; - default: - return false; - } - - return true; -} - void dcn401_populate_mcm_luts(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_cm2_func_luts mcm_luts, @@ -664,25 +423,6 @@ void dcn401_populate_mcm_luts(struct dc *dc, dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); - //MCM - setting its location (Before/After) blender - //set to post blend (true) - dcn401_set_mcm_location_post_blend( - dc, - pipe_ctx, - mcm_luts.lut3d_data.mpc_mcm_post_blend); - - //RMCM - 3dLUT+Shaper - if (mcm_luts.lut3d_data.rmcm_3dlut_enable) { - dcn401_program_rmcm_luts( - hubp, - pipe_ctx, - lut3d_src, - &mcm_luts, - mpc, - lut_bank_a, - mpcc_id); - } - /* 1D LUT */ if (mcm_luts.lut1d_func) { memset(&m_lut_params, 0, sizeof(m_lut_params)); @@ -740,9 +480,6 @@ void dcn401_populate_mcm_luts(struct dc *dc, break; case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: switch (mcm_luts.lut3d_data.gpu_mem_params.size) { - case DC_CM2_GPU_MEM_SIZE_333333: - width = hubp_3dlut_fl_width_33; - break; case DC_CM2_GPU_MEM_SIZE_171717: width = hubp_3dlut_fl_width_17; break; @@ -817,11 +554,14 @@ void dcn401_populate_mcm_luts(struct dc *dc, //navi 4x has a bug and r and blue are swapped and need to be worked around here in //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x - dc_get_lut_xbar( - mcm_luts.lut3d_data.gpu_mem_params.component_order, - &crossbar_bit_slice_cr_r, - &crossbar_bit_slice_y_g, - &crossbar_bit_slice_cb_b); + switch (mcm_luts.lut3d_data.gpu_mem_params.component_order) { + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: + default: + crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; + crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; + break; + } if (hubp->funcs->hubp_program_3dlut_fl_crossbar) hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, @@ -2269,14 +2009,6 @@ void dcn401_program_pipe( pipe_ctx->plane_state->update_flags.bits.hdr_mult)) hws->funcs.set_hdr_multiplier(pipe_ctx); - if (hws->funcs.populate_mcm_luts) { - if (pipe_ctx->plane_state) { - hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts, - pipe_ctx->plane_state->lut_bank_a); - pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a; - } - } - if (pipe_ctx->plane_state && (pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || pipe_ctx->plane_state->update_flags.bits.gamma_change || diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h index ce65b4f6c6727..781cf0efccc6c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h @@ -109,12 +109,4 @@ void dcn401_detect_pipe_changes( void dcn401_plane_atomic_power_down(struct dc *dc, struct dpp *dpp, struct hubp *hubp); -bool dcn401_program_rmcm_luts( - struct hubp *hubp, - struct pipe_ctx *pipe_ctx, - enum dc_cm2_transfer_func_source lut3d_src, - struct dc_cm2_func_luts *mcm_luts, - struct mpc *mpc, - bool lut_bank_a, - int mpcc_id); #endif /* __DC_HWSS_DCN401_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c index b4cea2b8cb2a8..50ea62a009e89 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c @@ -30,7 +30,6 @@ #include "basics/conversion.h" #include "dcn10/dcn10_cm_common.h" #include "dc.h" -#include "dcn401/dcn401_mpc.h" #define REG(reg)\ mpc30->mpc_regs->reg @@ -1022,8 +1021,6 @@ static const struct mpc_funcs dcn32_mpc_funcs = { .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, .get_mpc_out_mux = mpc1_get_mpc_out_mux, .set_bg_color = mpc1_set_bg_color, - .set_movable_cm_location = mpc401_set_movable_cm_location, - .populate_lut = mpc401_populate_lut, }; -- GitLab From db122ece325a3a19eeabf98e61db70fe890b4b5a Mon Sep 17 00:00:00 2001 From: Oleh Kuzhylnyi Date: Thu, 24 Apr 2025 14:40:09 +0200 Subject: [PATCH 191/902] drm/amd/display: Indirect buffer transport for FAMS2 commands [Why] The quantity and duration of FAMS2 commands are set to increase in future products. This necessitates the implementation of a new mechanism for chaining commands together, allowing all commands to be processed within a single transaction. [How] The indirect buffer acts as a shared buffer on the driver side, mapped to DMUB's internal CW7 address. Its source address and size are sent through mailbox command to DMUB, triggering the transaction. Reviewed-by: Alvin Lee Signed-off-by: Oleh Kuzhylnyi Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 59 ++++++++++++++++++- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 + .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 9 ++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d3100f641ac6e..10d5240dfb682 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2404,6 +2404,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_5_TRACEBUFF DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_6_FW_STATE DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_7_SCRATCH_MEM + DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_IB_MEM DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_SHARED_STATE }; int r; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index afbcf866520e0..8c52d3fea1d8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1656,7 +1656,7 @@ bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_com return result; } -void dc_dmub_srv_fams2_update_config(struct dc *dc, +static void dc_dmub_srv_rb_based_fams2_update_config(struct dc *dc, struct dc_state *context, bool enable) { @@ -1722,6 +1722,63 @@ void dc_dmub_srv_fams2_update_config(struct dc *dc, dm_execute_dmub_cmd_list(dc->ctx, num_cmds, cmd, DM_DMUB_WAIT_TYPE_WAIT); } +static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc, + struct dc_state *context, + bool enable) +{ + struct dmub_fams2_config_v2 *config = (struct dmub_fams2_config_v2 *)dc->ctx->dmub_srv->dmub->ib_mem_gart.cpu_addr; + union dmub_rb_cmd cmd; + uint32_t i; + + memset(config, 0, sizeof(*config)); + memset(&cmd, 0, sizeof(cmd)); + + cmd.ib_fams2_config.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + cmd.ib_fams2_config.header.sub_type = DMUB_CMD__FAMS2_IB_CONFIG; + + cmd.ib_fams2_config.ib_data.src.quad_part = dc->ctx->dmub_srv->dmub->ib_mem_gart.gpu_addr; + cmd.ib_fams2_config.ib_data.size = sizeof(*config); + + if (enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable) { + /* copy static feature configuration overrides */ + config->global.features.bits.enable_stall_recovery = dc->debug.fams2_config.bits.enable_stall_recovery; + config->global.features.bits.enable_offload_flip = dc->debug.fams2_config.bits.enable_offload_flip; + config->global.features.bits.enable_debug = dc->debug.fams2_config.bits.enable_debug; + + /* send global configuration parameters */ + memcpy(&config->global, &context->bw_ctx.bw.dcn.fams2_global_config, + sizeof(struct dmub_cmd_fams2_global_config)); + + /* construct per-stream configs */ + for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) { + /* copy stream static base state */ + memcpy(&config->stream_v1[i].base, + &context->bw_ctx.bw.dcn.fams2_stream_base_params[i], + sizeof(config->stream_v1[i].base)); + + /* copy stream static sub-state */ + memcpy(&config->stream_v1[i].sub_state, + &context->bw_ctx.bw.dcn.fams2_stream_sub_params[i], + sizeof(config->stream_v1[i].sub_state)); + } + } + + config->global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2; + config->global.features.bits.enable = enable; + + dm_execute_dmub_cmd_list(dc->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +} + +void dc_dmub_srv_fams2_update_config(struct dc *dc, + struct dc_state *context, + bool enable) +{ + if (dc->debug.fams_version.major == 2) + dc_dmub_srv_rb_based_fams2_update_config(dc, context, enable); + if (dc->debug.fams_version.major == 3) + dc_dmub_srv_ib_based_fams2_update_config(dc, context, enable); +} + void dc_dmub_srv_fams2_drr_update(struct dc *dc, uint32_t tg_inst, uint32_t vtotal_min, diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 3f3fa1b6a69e8..211486724e848 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -129,6 +129,7 @@ enum dmub_window_id { DMUB_WINDOW_5_TRACEBUFF, DMUB_WINDOW_6_FW_STATE, DMUB_WINDOW_7_SCRATCH_MEM, + DMUB_WINDOW_IB_MEM, DMUB_WINDOW_SHARED_STATE, DMUB_WINDOW_TOTAL, }; @@ -539,6 +540,7 @@ struct dmub_srv { uint32_t fw_version; bool is_virtual; struct dmub_fb scratch_mem_fb; + struct dmub_fb ib_mem_gart; volatile struct dmub_shared_state_feature_block *shared_state; volatile const struct dmub_fw_state *fw_state; diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index acca7943a8c82..5f827104b4f8f 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -65,6 +65,9 @@ /* Default scratch mem size. */ #define DMUB_SCRATCH_MEM_SIZE (1024) +/* Default indirect buffer size. */ +#define DMUB_IB_MEM_SIZE (1280) + /* Number of windows in use. */ #define DMUB_NUM_WINDOWS (DMUB_WINDOW_TOTAL) /* Base addresses. */ @@ -559,6 +562,7 @@ enum dmub_status window_sizes[DMUB_WINDOW_5_TRACEBUFF] = trace_buffer_size; window_sizes[DMUB_WINDOW_6_FW_STATE] = fw_state_size; window_sizes[DMUB_WINDOW_7_SCRATCH_MEM] = DMUB_SCRATCH_MEM_SIZE; + window_sizes[DMUB_WINDOW_IB_MEM] = DMUB_IB_MEM_SIZE; window_sizes[DMUB_WINDOW_SHARED_STATE] = max(DMUB_FW_HEADER_SHARED_STATE_SIZE, shared_state_size); out->fb_size = @@ -645,6 +649,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, struct dmub_fb *tracebuff_fb = params->fb[DMUB_WINDOW_5_TRACEBUFF]; struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE]; struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM]; + struct dmub_fb *ib_mem_gart = params->fb[DMUB_WINDOW_IB_MEM]; struct dmub_fb *shared_state_fb = params->fb[DMUB_WINDOW_SHARED_STATE]; struct dmub_rb_init_params rb_params, outbox0_rb_params; @@ -655,7 +660,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, return DMUB_STATUS_INVALID; if (!inst_fb || !stack_fb || !data_fb || !bios_fb || !mail_fb || - !tracebuff_fb || !fw_state_fb || !scratch_mem_fb) { + !tracebuff_fb || !fw_state_fb || !scratch_mem_fb || !ib_mem_gart) { ASSERT(0); return DMUB_STATUS_INVALID; } @@ -741,6 +746,8 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, dmub->scratch_mem_fb = *scratch_mem_fb; + dmub->ib_mem_gart = *ib_mem_gart; + if (dmub->hw_funcs.setup_windows) dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4, &cw5, &cw6, ®ion6); -- GitLab From 8ade4736075a83d92e6cb87dc89c114760460994 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 2 May 2025 10:40:50 -0500 Subject: [PATCH 192/902] drm/amd/display: Drop unnecessary `amdgpu` prefix [Why] The `drm_*()` print macros will handle including the driver in the print already. The extra print of the word `amdgpu` is unnecessary. [How] Modify all prints to drop `amdgpu: `. Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 +++++++++---------- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 10d5240dfb682..9a7c5a038e37e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1847,7 +1847,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) mutex_init(&adev->dm.audio_lock); if (amdgpu_dm_irq_init(adev)) { - drm_err(adev_to_drm(adev), "amdgpu: failed to initialize DM IRQ support.\n"); + drm_err(adev_to_drm(adev), "failed to initialize DM IRQ support.\n"); goto error; } @@ -2037,7 +2037,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev); if (!adev->dm.hpd_rx_offload_wq) { - drm_err(adev_to_drm(adev), "amdgpu: failed to create hpd rx offload workqueue.\n"); + drm_err(adev_to_drm(adev), "failed to create hpd rx offload workqueue.\n"); goto error; } @@ -2053,7 +2053,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.freesync_module = mod_freesync_create(adev->dm.dc); if (!adev->dm.freesync_module) { drm_err(adev_to_drm(adev), - "amdgpu: failed to initialize freesync_module.\n"); + "failed to initialize freesync_module.\n"); } else drm_dbg_driver(adev_to_drm(adev), "amdgpu: freesync_module init done %p.\n", adev->dm.freesync_module); @@ -2064,7 +2064,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.vblank_control_workqueue = create_singlethread_workqueue("dm_vblank_control_workqueue"); if (!adev->dm.vblank_control_workqueue) - drm_err(adev_to_drm(adev), "amdgpu: failed to initialize vblank_workqueue.\n"); + drm_err(adev_to_drm(adev), "failed to initialize vblank_workqueue.\n"); } if (adev->dm.dc->caps.ips_support && @@ -2075,7 +2075,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc); if (!adev->dm.hdcp_workqueue) - drm_err(adev_to_drm(adev), "amdgpu: failed to initialize hdcp_workqueue.\n"); + drm_err(adev_to_drm(adev), "failed to initialize hdcp_workqueue.\n"); else drm_dbg_driver(adev_to_drm(adev), "amdgpu: hdcp_workqueue init done %p.\n", adev->dm.hdcp_workqueue); @@ -2085,20 +2085,20 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_completion(&adev->dm.dmub_aux_transfer_done); adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL); if (!adev->dm.dmub_notify) { - drm_info(adev_to_drm(adev), "amdgpu: fail to allocate adev->dm.dmub_notify"); + drm_info(adev_to_drm(adev), "fail to allocate adev->dm.dmub_notify"); goto error; } adev->dm.delayed_hpd_wq = create_singlethread_workqueue("amdgpu_dm_hpd_wq"); if (!adev->dm.delayed_hpd_wq) { - drm_err(adev_to_drm(adev), "amdgpu: failed to create hpd offload workqueue.\n"); + drm_err(adev_to_drm(adev), "failed to create hpd offload workqueue.\n"); goto error; } amdgpu_dm_outbox_init(adev); if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY, dmub_aux_setconfig_callback, false)) { - drm_err(adev_to_drm(adev), "amdgpu: fail to register dmub aux callback"); + drm_err(adev_to_drm(adev), "fail to register dmub aux callback"); goto error; } @@ -2107,7 +2107,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_FUSED_IO, dmub_aux_fused_io_callback, false)) { - drm_err(adev_to_drm(adev), "amdgpu: fail to register dmub fused io callback"); + drm_err(adev_to_drm(adev), "fail to register dmub fused io callback"); goto error; } /* Enable outbox notification only after IRQ handlers are registered and DMUB is alive. @@ -2125,7 +2125,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dm_initialize_drm_device(adev)) { drm_err(adev_to_drm(adev), - "amdgpu: failed to initialize sw for display support.\n"); + "failed to initialize sw for display support.\n"); goto error; } @@ -2140,14 +2140,14 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) { drm_err(adev_to_drm(adev), - "amdgpu: failed to initialize sw for display support.\n"); + "failed to initialize sw for display support.\n"); goto error; } #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) amdgpu_dm_crtc_secure_display_create_contexts(adev); if (!adev->dm.secure_display_ctx.crtc_ctx) - drm_err(adev_to_drm(adev), "amdgpu: failed to initialize secure display contexts.\n"); + drm_err(adev_to_drm(adev), "failed to initialize secure display contexts.\n"); if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 0, 1)) adev->dm.secure_display_ctx.support_mul_roi = true; @@ -2571,7 +2571,7 @@ static int dm_sw_init(struct amdgpu_ip_block *ip_block) adev->dm.cgs_device = amdgpu_cgs_create_device(adev); if (!adev->dm.cgs_device) { - drm_err(adev_to_drm(adev), "amdgpu: failed to create cgs device.\n"); + drm_err(adev_to_drm(adev), "failed to create cgs device.\n"); return -EINVAL; } @@ -4002,19 +4002,19 @@ static int register_hpd_handlers(struct amdgpu_device *adev) if (dc_is_dmub_outbox_supported(adev->dm.dc)) { if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD, dmub_hpd_callback, true)) { - drm_err(adev_to_drm(adev), "amdgpu: fail to register dmub hpd callback"); + drm_err(adev_to_drm(adev), "fail to register dmub hpd callback"); return -EINVAL; } if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_IRQ, dmub_hpd_callback, true)) { - drm_err(adev_to_drm(adev), "amdgpu: fail to register dmub hpd callback"); + drm_err(adev_to_drm(adev), "fail to register dmub hpd callback"); return -EINVAL; } if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_SENSE_NOTIFY, dmub_hpd_sense_callback, true)) { - drm_err(adev_to_drm(adev), "amdgpu: fail to register dmub hpd sense callback"); + drm_err(adev_to_drm(adev), "fail to register dmub hpd sense callback"); return -EINVAL; } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 25e8befbcc479..7187d5aedf0a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -107,7 +107,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, if (payload.write && result >= 0) { if (result) { /*one byte indicating partially written bytes*/ - drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n"); + drm_dbg_dp(adev_to_drm(adev), "AUX partially written\n"); result = payload.data[0]; } else if (!payload.reply[0]) /*I2C_ACK|AUX_ACK*/ @@ -133,11 +133,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, break; } - drm_dbg_dp(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); + drm_dbg_dp(adev_to_drm(adev), "DP AUX transfer fail:%d\n", operation_result); } if (payload.reply[0]) - drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.", + drm_dbg_dp(adev_to_drm(adev), "AUX reply command not ACK: 0x%02x.", payload.reply[0]); return result; -- GitLab From deb24e64c8881c462b29e2c69afd9e6669058be5 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 13 May 2025 16:06:50 +0800 Subject: [PATCH 193/902] drm/amd/display: Avoid trying AUX transactions on disconnected ports [Why & How] Observe that we try to access DPCD 0x600h of disconnected DP ports. In order not to wasting time on retrying these ports, call dpcd_write_rx_power_ctrl() after checking its connection status. Reviewed-by: Aurabindo Pillai Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 273a3be6d593a..f16cba4b9119d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -140,7 +140,8 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init) } } - if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init) + if (((!link->wa_flags.dp_keep_receiver_powered) || hw_init) && + (link->type != dc_connection_none)) dpcd_write_rx_power_ctrl(link, false); } } -- GitLab From 35b74eccf8289e4a458133be9f9795d152b6f11e Mon Sep 17 00:00:00 2001 From: Jingwen Zhu Date: Thu, 8 May 2025 11:19:49 +0800 Subject: [PATCH 194/902] drm/amd/display: Add disconnect case on dongle check [why] In the case of an external monitor disconnection, the kernel mode will attempt to post new timing validation with two path counts (eDP + external monitor removed to virtual). [how] Skip validating color depth and pixel encoding in the scenario involving a DP to HDMI active converter dongle. Reviewed-by: Wenjing Liu Signed-off-by: Jingwen Zhu Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/link/link_validation.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c index 29606fda029d6..e2235fd32998c 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c @@ -86,6 +86,10 @@ static bool dp_active_dongle_validate_timing( if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through) return false; break; + case PIXEL_ENCODING_UNDEFINED: + /* These color depths are currently not supported */ + ASSERT(false); + break; default: /* Invalid Pixel Encoding*/ return false; @@ -104,6 +108,10 @@ static bool dp_active_dongle_validate_timing( if (dongle_caps->dp_hdmi_max_bpc < 12) return false; break; + case COLOR_DEPTH_UNDEFINED: + /* These color depths are currently not supported */ + ASSERT(false); + break; case COLOR_DEPTH_141414: case COLOR_DEPTH_161616: default: -- GitLab From ed8045a731107e96b1fda80879a85b5de7658941 Mon Sep 17 00:00:00 2001 From: Oleh Kuzhylnyi Date: Wed, 14 May 2025 14:21:15 +0200 Subject: [PATCH 195/902] drm/amd/display: Add DML path for FAMS methods [Why] DML needs a path for FAMS methods. [How] Apply instance of fams2_stream_sub_params_v2 structure with a FAMS placeholder for DML. Reviewed-by: Alvin Lee Signed-off-by: Oleh Kuzhylnyi Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 2 +- .../drm/amd/display/dc/dml2/dml21/dml21_utils.c | 14 +++++++++++--- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 8c52d3fea1d8f..00ea81fa9573b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1758,7 +1758,7 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc, /* copy stream static sub-state */ memcpy(&config->stream_v1[i].sub_state, - &context->bw_ctx.bw.dcn.fams2_stream_sub_params[i], + &context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[i], sizeof(config->stream_v1[i].sub_state)); } } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c index 930e86cdb88a2..ee721606b8839 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c @@ -384,6 +384,7 @@ void dml21_build_fams2_programming(const struct dc *dc, /* reset fams2 data */ memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); + memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES); memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); if (dml_ctx->v21.mode_programming.programming->fams2_required) { @@ -414,9 +415,16 @@ void dml21_build_fams2_programming(const struct dc *dc, memcpy(static_base_state, &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, sizeof(union dmub_cmd_fams2_config)); - memcpy(static_sub_state, - &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, - sizeof(union dmub_cmd_fams2_config)); + + if (dc->debug.fams_version.major == 3) { + memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams], + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2, + sizeof(union dmub_fams2_stream_static_sub_state_v2)); + } else { + memcpy(static_sub_state, + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, + sizeof(union dmub_cmd_fams2_config)); + } switch (dc->debug.fams_version.minor) { case 1: diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 0cf349cafb3e5..56b0b3f59efcc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -556,7 +556,10 @@ struct dcn_bw_output { struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES]; struct dmub_cmd_fams2_global_config fams2_global_config; union dmub_cmd_fams2_config fams2_stream_base_params[DML2_MAX_PLANES]; - union dmub_cmd_fams2_config fams2_stream_sub_params[DML2_MAX_PLANES]; + union { + union dmub_cmd_fams2_config fams2_stream_sub_params[DML2_MAX_PLANES]; + union dmub_fams2_stream_static_sub_state_v2 fams2_stream_sub_params_v2[DML2_MAX_PLANES]; + }; struct dml2_display_arb_regs arb_regs; }; -- GitLab From a4d04bc90d2d539cf27f72128a0301a261e1249d Mon Sep 17 00:00:00 2001 From: Navid Assadian Date: Wed, 30 Apr 2025 15:38:20 -0400 Subject: [PATCH 196/902] drm/amd/display: Do not bypass chroma scaling in 1:1 case [Why] When doing 2:1 downscaling on a YUV sub-sampled format, the chroma scaling ratio is 1:1. Since chroma has cositing, it is needed to do scaling on the chroma plane(s) and not to bypass chroma scaling. [How] Do not set the chroma taps to one when the chroma ratio is identity and the input format is a sub-sampled YUV format. Reviewed-by: Samson Tam Signed-off-by: Navid Assadian Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c | 28 +++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c index e0008c5f08ad2..d5f3bcb68d535 100644 --- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c @@ -884,7 +884,9 @@ static bool spl_get_isharp_en(struct spl_in *spl_in, /* Calculate number of tap with adaptive scaling off */ static void spl_get_taps_non_adaptive_scaler( - struct spl_scratch *spl_scratch, const struct spl_taps *in_taps, bool always_scale) + struct spl_scratch *spl_scratch, + const struct spl_taps *in_taps, + bool is_subsampled) { bool check_max_downscale = false; @@ -945,14 +947,15 @@ static void spl_get_taps_non_adaptive_scaler( SPL_ASSERT(check_max_downscale); - if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz) && !always_scale) + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)) spl_scratch->scl_data.taps.h_taps = 1; - if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert) && !always_scale) + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)) spl_scratch->scl_data.taps.v_taps = 1; - if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !always_scale) + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !is_subsampled) spl_scratch->scl_data.taps.h_taps_c = 1; - if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c) && !always_scale) + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c) && !is_subsampled) spl_scratch->scl_data.taps.v_taps_c = 1; + } /* Calculate optimal number of taps */ @@ -965,15 +968,13 @@ static bool spl_get_optimal_number_of_taps( unsigned int max_taps_y, max_taps_c; unsigned int min_taps_y, min_taps_c; enum lb_memory_config lb_config; - bool skip_easf = false; - bool always_scale = spl_in->basic_out.always_scale; + bool skip_easf = false; bool is_subsampled = spl_is_subsampled_format(spl_in->basic_in.format); - if (spl_scratch->scl_data.viewport.width > spl_scratch->scl_data.h_active && max_downscale_src_width != 0 && spl_scratch->scl_data.viewport.width > max_downscale_src_width) { - spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, always_scale); + spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, is_subsampled); *enable_easf_v = false; *enable_easf_h = false; *enable_isharp = false; @@ -982,7 +983,7 @@ static bool spl_get_optimal_number_of_taps( /* Disable adaptive scaler and sharpener when integer scaling is enabled */ if (spl_in->scaling_quality.integer_scaling) { - spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, always_scale); + spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, is_subsampled); *enable_easf_v = false; *enable_easf_h = false; *enable_isharp = false; @@ -997,8 +998,9 @@ static bool spl_get_optimal_number_of_taps( * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling * taps = 4 for upscaling */ - if (skip_easf) - spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, always_scale); + if (skip_easf) { + spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps, is_subsampled); + } else { if (spl_is_video_format(spl_in->basic_in.format)) { spl_scratch->scl_data.taps.h_taps = 6; @@ -1124,7 +1126,6 @@ static bool spl_get_optimal_number_of_taps( (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert))) { spl_scratch->scl_data.taps.h_taps = 1; spl_scratch->scl_data.taps.v_taps = 1; - if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !is_subsampled) spl_scratch->scl_data.taps.h_taps_c = 1; @@ -1149,6 +1150,7 @@ static bool spl_get_optimal_number_of_taps( if ((!*enable_easf_v) && !is_subsampled && (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c))) spl_scratch->scl_data.taps.v_taps_c = 1; + } } return true; -- GitLab From dbb767be864a667ac33c283c7ec9c26245b44d24 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Fri, 9 May 2025 11:19:28 -0400 Subject: [PATCH 197/902] drm/amd/display: Add support for 2nd sharpening range [Why & How] Add support for 2nd sharpening range for cases where we want override existing DCN sharpening range Reviewed-by: Ilya Bakoulin Signed-off-by: Samson Tam Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 6 ++++++ .../gpu/drm/amd/display/dc/dc_spl_translate.c | 19 +++++++++-------- .../dc/resource/dcn401/dcn401_resource.c | 21 +++++++++++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a63f7fe277fa2..6b0471f635f24 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -46,6 +46,8 @@ #include "dmub/inc/dmub_cmd.h" +#include "sspl/dc_spl_types.h" + struct abm_save_restore; /* forward declaration */ @@ -512,6 +514,8 @@ struct dc_config { bool set_pipe_unlock_order; bool enable_dpia_pre_training; bool unify_link_enc_assignment; + struct spl_sharpness_range dcn_sharpness_range; + struct spl_sharpness_range dcn_override_sharpness_range; }; enum visual_confirm { @@ -1420,6 +1424,8 @@ struct dc_plane_state { int sharpness_level; enum linear_light_scaling linear_light_scaling; unsigned int sdr_white_level_nits; + struct spl_sharpness_range sharpness_range; + enum sharpness_range_source sharpness_source; }; struct dc_plane_info { diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c index e3a8283b4098c..7f57661433eb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -156,15 +156,16 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl spl_in->adaptive_sharpness.enable = true; spl_in->adaptive_sharpness.sharpness_level = 0; } else if (sharpness_setting == SHARPNESS_CUSTOM) { - spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_min = 0; - spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_max = 1750; - spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_mid = 750; - spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_min = 0; - spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_max = 3500; - spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_mid = 1500; - spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_min = 0; - spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_max = 2750; - spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_mid = 1500; + /* SAT: read harpness_range from dc_plane_state */ + spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_min = plane_state->sharpness_range.sdr_rgb_min; + spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_max = plane_state->sharpness_range.sdr_rgb_max; + spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_mid = plane_state->sharpness_range.sdr_rgb_mid; + spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_min = plane_state->sharpness_range.sdr_yuv_min; + spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_max = plane_state->sharpness_range.sdr_yuv_max; + spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_mid = plane_state->sharpness_range.sdr_yuv_mid; + spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_min = plane_state->sharpness_range.hdr_rgb_min; + spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_max = plane_state->sharpness_range.hdr_rgb_max; + spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_mid = plane_state->sharpness_range.hdr_rgb_mid; if (force_sharpness_level > 0) { if (force_sharpness_level > 10) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index f420c4dafa03c..fbb6db1baaadf 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1959,6 +1959,27 @@ static bool dcn401_resource_construct( dc->caps.color.mpc.ocsc = 1; dc->config.use_spl = true; dc->config.prefer_easf = true; + + dc->config.dcn_sharpness_range.sdr_rgb_min = 0; + dc->config.dcn_sharpness_range.sdr_rgb_max = 1750; + dc->config.dcn_sharpness_range.sdr_rgb_mid = 750; + dc->config.dcn_sharpness_range.sdr_yuv_min = 0; + dc->config.dcn_sharpness_range.sdr_yuv_max = 3500; + dc->config.dcn_sharpness_range.sdr_yuv_mid = 1500; + dc->config.dcn_sharpness_range.hdr_rgb_min = 0; + dc->config.dcn_sharpness_range.hdr_rgb_max = 2750; + dc->config.dcn_sharpness_range.hdr_rgb_mid = 1500; + + dc->config.dcn_override_sharpness_range.sdr_rgb_min = 0; + dc->config.dcn_override_sharpness_range.sdr_rgb_max = 3250; + dc->config.dcn_override_sharpness_range.sdr_rgb_mid = 1250; + dc->config.dcn_override_sharpness_range.sdr_yuv_min = 0; + dc->config.dcn_override_sharpness_range.sdr_yuv_max = 3500; + dc->config.dcn_override_sharpness_range.sdr_yuv_mid = 1500; + dc->config.dcn_override_sharpness_range.hdr_rgb_min = 0; + dc->config.dcn_override_sharpness_range.hdr_rgb_max = 2750; + dc->config.dcn_override_sharpness_range.hdr_rgb_mid = 1500; + dc->config.dc_mode_clk_limit_support = true; dc->config.enable_windowed_mpo_odm = true; dc->config.set_pipe_unlock_order = true; /* Need to ensure DET gets freed before allocating */ -- GitLab From 56f618407d7b952970648bcc5535a8cfa0e93c3a Mon Sep 17 00:00:00 2001 From: Ray Wu Date: Thu, 8 May 2025 17:51:11 +0800 Subject: [PATCH 198/902] drm/amd/display: Move vmalloc include to header file [Why & How] Move vmalloc.h include code to header file. Reviewed-by: ChiaHsuan Chung Signed-off-by: Ray Wu Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 2 -- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 2 -- drivers/gpu/drm/amd/display/dc/os_types.h | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index 208d3651b6baf..c8e78a8d15396 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -2,8 +2,6 @@ // // Copyright 2024 Advanced Micro Devices, Inc. -#include - #include "dml2_internal_types.h" #include "dml_top.h" #include "dml2_core_dcn4_calcs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 525b7d04bf84c..a90aeecd3b502 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -24,8 +24,6 @@ * */ -#include - #include "display_mode_core.h" #include "dml2_internal_types.h" #include "dml2_utils.h" diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index f2ba76c1e0c09..782316348941b 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -31,6 +31,7 @@ #include #include #include +#include #include -- GitLab From 960d8c0fa3b55ab58caa5c135940054b4fcc26b1 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 18 May 2025 11:28:38 -0400 Subject: [PATCH 199/902] drm/amd/display: [FW Promotion] Release 0.1.12.0 Add dmub command to support LSDMA Acked-by: ChiaHsuan Chung Signed-off-by: Taimur Hassan Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 346d843b45bf4..dc4a8b83e6c62 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1516,6 +1516,11 @@ enum dmub_cmd_type { */ DMUB_CMD__FUSED_IO = 89, + /** + * Command type used for all LSDMA commands. + */ + DMUB_CMD__LSDMA = 90, + DMUB_CMD__VBIOS = 128, }; @@ -1926,6 +1931,121 @@ struct dmub_rb_cmd_fams2_flip { struct dmub_fams2_flip_info flip_info; }; +struct dmub_cmd_lsdma_data { + union { + struct lsdma_init_data { + union dmub_addr gpu_addr_base; + uint32_t ring_size; + } init_data; + struct lsdma_tiled_copy_data { + uint32_t src_addr_lo; + uint32_t src_addr_hi; + uint32_t dst_addr_lo; + uint32_t dst_addr_hi; + + uint32_t src_x : 16; + uint32_t src_y : 16; + + uint32_t src_width : 16; + uint32_t src_height : 16; + + uint32_t dst_x : 16; + uint32_t dst_y : 16; + + uint32_t dst_width : 16; + uint32_t dst_height : 16; + + uint32_t rect_x : 16; + uint32_t rect_y : 16; + + uint32_t src_swizzle_mode : 5; + uint32_t src_mip_max : 5; + uint32_t src_mip_id : 5; + uint32_t dst_mip_max : 5; + uint32_t dst_swizzle_mode : 5; + uint32_t dst_mip_id : 5; + uint32_t tmz : 1; + uint32_t dcc : 1; + + uint32_t data_format : 6; + uint32_t padding1 : 4; + uint32_t dst_element_size : 3; + uint32_t num_type : 3; + uint32_t src_element_size : 3; + uint32_t write_compress : 2; + uint32_t cache_policy_dst : 2; + uint32_t cache_policy_src : 2; + uint32_t read_compress : 2; + uint32_t src_dim : 2; + uint32_t dst_dim : 2; + uint32_t max_uncom : 1; + + uint32_t max_com : 2; + uint32_t padding : 30; + } tiled_copy_data; + struct lsdma_linear_copy_data { + uint32_t count : 30; + uint32_t cache_policy_dst : 2; + + uint32_t tmz : 1; + uint32_t cache_policy_src : 2; + uint32_t padding : 29; + + uint32_t src_lo; + uint32_t src_hi; + uint32_t dst_lo; + uint32_t dst_hi; + } linear_copy_data; + struct lsdma_reg_write_data { + uint32_t reg_addr; + uint32_t reg_data; + } reg_write_data; + struct lsdma_pio_copy_data { + union { + struct { + uint32_t byte_count : 26; + uint32_t src_loc : 1; + uint32_t dst_loc : 1; + uint32_t src_addr_inc : 1; + uint32_t dst_addr_inc : 1; + uint32_t overlap_disable : 1; + uint32_t constant_fill : 1; + } fields; + uint32_t raw; + } packet; + uint32_t src_lo; + uint32_t src_hi; + uint32_t dst_lo; + uint32_t dst_hi; + } pio_copy_data; + struct lsdma_pio_constfill_data { + union { + struct { + uint32_t byte_count : 26; + uint32_t src_loc : 1; + uint32_t dst_loc : 1; + uint32_t src_addr_inc : 1; + uint32_t dst_addr_inc : 1; + uint32_t overlap_disable : 1; + uint32_t constant_fill : 1; + } fields; + uint32_t raw; + } packet; + uint32_t dst_lo; + uint32_t dst_hi; + uint32_t data; + } pio_constfill_data; + + uint32_t all[14]; + } u; + +}; + +struct dmub_rb_cmd_lsdma { + struct dmub_cmd_header header; + struct dmub_cmd_lsdma_data lsdma_data; +}; + struct dmub_optc_state_v2 { uint32_t v_total_min; uint32_t v_total_max; @@ -4453,6 +4573,37 @@ enum dmub_cmd_abm_type { DMUB_CMD__ABM_GET_HISTOGRAM_DATA = 11, }; +/** + * LSDMA command sub-types. + */ +enum dmub_cmd_lsdma_type { + /** + * Initialize parameters for LSDMA. + * Ring buffer is mapped to the ring buffer + */ + DMUB_CMD__LSDMA_INIT_CONFIG = 0, + /** + * LSDMA copies data from source to destination linearly + */ + DMUB_CMD__LSDMA_LINEAR_COPY = 1, + /** + * Send the tiled-to-tiled copy command + */ + DMUB_CMD__LSDMA_TILED_TO_TILED_COPY = 2, + /** + * Send the poll reg write command + */ + DMUB_CMD__LSDMA_POLL_REG_WRITE = 3, + /** + * Send the pio copy command + */ + DMUB_CMD__LSDMA_PIO_COPY = 4, + /** + * Send the pio constfill command + */ + DMUB_CMD__LSDMA_PIO_CONSTFILL = 5, +}; + struct abm_ace_curve { /** * @offsets: ACE curve offsets. @@ -5973,6 +6124,11 @@ union dmub_rb_cmd { struct dmub_rb_cmd_fams2_flip fams2_flip; struct dmub_rb_cmd_fused_io fused_io; + + /** + * Definition of a DMUB_CMD__LSDMA command. + */ + struct dmub_rb_cmd_lsdma lsdma; }; /** -- GitLab From aca63ca8b84919e8cf69747aa91593655bd1f731 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Sun, 18 May 2025 12:37:53 -0500 Subject: [PATCH 200/902] drm/amd/display: Promote DAL to 3.2.335 This version brings along following fixes: - Fixes for DML21 - Support OLED SDR with AMD ABC - Indirect buffer transport for FAMS2 commands - Correct non-OLED pre_T11_delay - Optime boot-up consuming time - Add support for 2nd sharpening range - Fix on chroma planes scaling Acked-by: ChiaHsuan Chung Signed-off-by: Taimur Hassan Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6b0471f635f24..2742881394617 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.334" +#define DC_VER "3.2.335" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC -- GitLab From d42b2331e158fa6bcdc89e4c8c470dc5da20be1f Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 9 May 2025 11:18:26 -0400 Subject: [PATCH 201/902] drm/amd/display: Update DMCUB loading sequence for DCN3.5 [Why] New sequence from HW for reset and firmware reloading has been provided that aims to stabilize the reload sequence in the case the firmware is hung or has outstanding requests. [How] Update the sequence to remove the DMUIF reset and the redundant writes in the release. Reviewed-by: Ovidiu Bunea Signed-off-by: Nicholas Kazlauskas Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 72a0f078cd1a5..2884977a3dd2f 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -92,19 +92,15 @@ void dmub_dcn35_reset(struct dmub_srv *dmub) uint32_t in_reset, is_enabled, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); - if (in_reset == 0) { + if (in_reset == 0 && is_enabled != 0) { cmd.bits.status = 1; cmd.bits.command_code = DMUB_GPINT__STOP_FW; cmd.bits.param = 0; dmub->hw_funcs.set_gpint(dmub, cmd); - /** - * Timeout covers both the ACK and the wait - * for remaining work to finish. - */ - for (i = 0; i < timeout; ++i) { if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) break; @@ -130,11 +126,9 @@ void dmub_dcn35_reset(struct dmub_srv *dmub) /* Force reset in case we timed out, DMCUB is likely hung. */ } - REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); - if (is_enabled) { REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + udelay(1); REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); } @@ -160,11 +154,7 @@ void dmub_dcn35_reset_release(struct dmub_srv *dmub) LONO_SOCCLK_GATE_DISABLE, 1, LONO_DMCUBCLK_GATE_DISABLE, 1); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); - udelay(1); REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1); - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); - udelay(1); REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0); REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0); } -- GitLab From 269c1d1443d6686595ac187c247973014a1ee709 Mon Sep 17 00:00:00 2001 From: Yan Li Date: Wed, 14 May 2025 11:54:49 -0400 Subject: [PATCH 202/902] drm/amd/display: replace fast_validate with enum dc_validate_mode [Why] The boolean fast_validate is used as an input parameter in multiple functions. To support more scenarios, we are replacing it with enum dc_validate_mode. [How] The enum dc_validate_mode introduces three possible values: 1) DC_VALIDATE_MODE_AND_PROGRAMMING: Apply the mode to hardware 2) DC_VALIDATE_MODE_ONLY: Check whether the mode can be supported 3) DC_VALIDATE_MODE_AND_STATE_INDEX: Check if the mode can be supported, and determine the optimal voltage level needed to support it. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Yan Li Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++--- .../gpu/drm/amd/display/dc/core/dc_resource.c | 12 ++--- drivers/gpu/drm/amd/display/dc/dc.h | 8 +--- drivers/gpu/drm/amd/display/dc/dc_types.h | 8 ++++ .../drm/amd/display/dc/dml/calcs/dcn_calcs.c | 6 +-- .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 45 +++++++++---------- .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 12 ++--- .../drm/amd/display/dc/dml/dcn30/dcn30_fpu.c | 6 ++- .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 2 +- .../amd/display/dc/dml/dcn314/dcn314_fpu.c | 4 +- .../amd/display/dc/dml/dcn314/dcn314_fpu.h | 2 +- .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 30 +++++++------ .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.h | 2 +- .../drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 +- .../drm/amd/display/dc/dml/dcn35/dcn35_fpu.h | 2 +- .../amd/display/dc/dml/dcn351/dcn351_fpu.c | 4 +- .../amd/display/dc/dml/dcn351/dcn351_fpu.h | 2 +- .../amd/display/dc/dml2/dml21/dml21_wrapper.c | 7 +-- .../amd/display/dc/dml2/dml21/dml21_wrapper.h | 11 +++-- .../amd/display/dc/dml2/dml2_mall_phantom.c | 2 +- .../drm/amd/display/dc/dml2/dml2_wrapper.c | 9 ++-- .../drm/amd/display/dc/dml2/dml2_wrapper.h | 4 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 2 +- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 4 +- .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 2 +- .../dc/resource/dce100/dce100_resource.c | 2 +- .../dc/resource/dce110/dce110_resource.c | 2 +- .../dc/resource/dce112/dce112_resource.c | 2 +- .../dc/resource/dce112/dce112_resource.h | 2 +- .../dc/resource/dce60/dce60_resource.c | 2 +- .../dc/resource/dce80/dce80_resource.c | 2 +- .../dc/resource/dcn10/dcn10_resource.c | 4 +- .../dc/resource/dcn20/dcn20_resource.c | 8 ++-- .../dc/resource/dcn20/dcn20_resource.h | 4 +- .../dc/resource/dcn21/dcn21_resource.c | 8 ++-- .../dc/resource/dcn21/dcn21_resource.h | 2 +- .../dc/resource/dcn30/dcn30_resource.c | 22 ++++----- .../dc/resource/dcn30/dcn30_resource.h | 6 +-- .../dc/resource/dcn31/dcn31_resource.c | 18 ++++---- .../dc/resource/dcn31/dcn31_resource.h | 4 +- .../dc/resource/dcn314/dcn314_resource.c | 14 +++--- .../dc/resource/dcn314/dcn314_resource.h | 2 +- .../dc/resource/dcn315/dcn315_resource.c | 4 +- .../dc/resource/dcn316/dcn316_resource.c | 4 +- .../dc/resource/dcn32/dcn32_resource.c | 26 +++++------ .../dc/resource/dcn32/dcn32_resource.h | 4 +- .../dc/resource/dcn35/dcn35_resource.c | 6 +-- .../dc/resource/dcn351/dcn351_resource.c | 6 +-- .../dc/resource/dcn36/dcn36_resource.c | 6 +-- .../dc/resource/dcn401/dcn401_resource.c | 10 ++--- .../dc/resource/dcn401/dcn401_resource.h | 2 +- 53 files changed, 198 insertions(+), 182 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9a7c5a038e37e..78816712afbbf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7520,7 +7520,7 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc, dc_result = DC_FAIL_ATTACH_SURFACES; if (dc_result == DC_OK) - dc_result = dc_validate_global_state(dc, dc_state, true); + dc_result = dc_validate_global_state(dc, dc_state, DC_VALIDATE_MODE_ONLY); cleanup: if (dc_state) @@ -12142,7 +12142,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, drm_dbg_atomic(dev, "MST drm_dp_mst_atomic_check() failed\n"); goto fail; } - status = dc_validate_global_state(dc, dm_state->context, true); + status = dc_validate_global_state(dc, dm_state->context, DC_VALIDATE_MODE_ONLY); if (status != DC_OK) { drm_dbg_atomic(dev, "DC global validation failure: %s (%d)", dc_status_to_str(status), status); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 56d011a1323cf..284261cd372f1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2377,7 +2377,7 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params context->power_source = params->power_source; - res = dc_validate_with_context(dc, set, params->stream_count, context, false); + res = dc_validate_with_context(dc, set, params->stream_count, context, DC_VALIDATE_MODE_AND_PROGRAMMING); /* * Only update link encoder to stream assignment after bandwidth validation passed. @@ -3300,7 +3300,8 @@ static void copy_stream_update_to_stream(struct dc *dc, if (dsc_validate_context) { stream->timing.dsc_cfg = *update->dsc_config; stream->timing.flags.DSC = enable_dsc; - if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true) != DC_OK) { + if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, + DC_VALIDATE_MODE_ONLY) != DC_OK) { stream->timing.dsc_cfg = old_dsc_cfg; stream->timing.flags.DSC = old_dsc_enabled; update->dsc_config = NULL; @@ -3522,7 +3523,7 @@ static bool update_planes_and_stream_state(struct dc *dc, } if (update_type == UPDATE_TYPE_FULL) { - if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) { + if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) { BREAK_TO_DEBUGGER(); goto fail; } @@ -4628,7 +4629,8 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc, backup_and_set_minimal_pipe_split_policy(dc, base_context, policy); /* commit minimal state */ - if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false) == DC_OK) { + if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, + DC_VALIDATE_MODE_AND_PROGRAMMING) == DC_OK) { /* prevent underflow and corruption when reconfiguring pipes */ force_vsync_flip_in_minimal_transition_context(minimal_transition_context); } else { @@ -5151,7 +5153,7 @@ static bool update_planes_and_stream_v1(struct dc *dc, copy_stream_update_to_stream(dc, context, stream, stream_update); if (update_type >= UPDATE_TYPE_FULL) { - if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) { + if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) { DC_ERROR("Mode validation failed for stream update!\n"); dc_state_release(context); return false; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3da25bd8b5788..854fc51f159c1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -4053,7 +4053,7 @@ static bool add_all_planes_for_stream( * @set: An array of dc_validation_set with all the current streams reference * @set_count: Total of streams * @context: New context - * @fast_validate: Enable or disable fast validation + * @validate_mode: identify the validation mode * * This function updates the potential new stream in the context object. It * creates multiple lists for the add, remove, and unchanged streams. In @@ -4068,7 +4068,7 @@ enum dc_status dc_validate_with_context(struct dc *dc, const struct dc_validation_set set[], int set_count, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 }; struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; @@ -4242,7 +4242,7 @@ enum dc_status dc_validate_with_context(struct dc *dc, dc_state_set_stream_subvp_cursor_limit(context->streams[i], context, false); } - res = dc_validate_global_state(dc, context, fast_validate); + res = dc_validate_global_state(dc, context, validate_mode); /* calculate pixel rate divider after deciding pxiel clock & odm combine */ if ((dc->hwss.calculate_pix_rate_divider) && (res == DC_OK)) { @@ -4299,7 +4299,7 @@ static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx) * * @dc: dc struct for this driver * @new_ctx: state to be validated - * @fast_validate: set to true if only yes/no to support matters + * @validate_mode: identify the validation mode * * Checks hardware resource availability and bandwidth requirement. * @@ -4309,7 +4309,7 @@ static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx) enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx, - bool fast_validate) + enum dc_validate_mode validate_mode) { enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; @@ -4368,7 +4368,7 @@ enum dc_status dc_validate_global_state( result = resource_build_scaling_params_for_context(dc, new_ctx); if (result == DC_OK) - result = dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate); + result = dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, validate_mode); return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2742881394617..9878868ff4d2f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1804,19 +1804,15 @@ enum dc_status dc_validate_with_context(struct dc *dc, const struct dc_validation_set set[], int set_count, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); bool dc_set_generic_gpio_for_stereo(bool enable, struct gpio_service *gpio_service); -/* - * fast_validate: we return after determining if we can support the new state, - * but before we populate the programming info - */ enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx, - bool fast_validate); + enum dc_validate_mode validate_mode); bool dc_acquire_release_mpc_3dlut( struct dc *dc, bool acquire, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 794b5f30d252f..a8afbe5eaf1d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1370,4 +1370,12 @@ struct set_backlight_level_params { uint8_t aux_inst; }; +enum dc_validate_mode { + /* validate the mode and program HW */ + DC_VALIDATE_MODE_AND_PROGRAMMING = 0, + /* only validate the mode */ + DC_VALIDATE_MODE_ONLY = 1, + /* validate the mode and get the max state (voltage level) */ + DC_VALIDATE_MODE_AND_STATE_INDEX = 2, +}; #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c index f1235bf9a5965..74962791302f6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c @@ -748,7 +748,7 @@ static unsigned int get_highest_allowed_voltage_level(bool is_vmin_only_asic) bool dcn_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { /* * we want a breakdown of the various stages of validation, which the @@ -1119,7 +1119,7 @@ bool dcn_validate_bandwidth( BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (v->voltage_level != number_of_states_plus_one && !fast_validate) { + if (v->voltage_level != number_of_states_plus_one && validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) { float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second; if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65) @@ -1286,7 +1286,7 @@ bool dcn_validate_bandwidth( } } else if (v->voltage_level == number_of_states_plus_one) { BW_VAL_TRACE_SKIP(fail); - } else if (fast_validate) { + } else if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index e9fea9c2162e8..2a2eaf6adf26c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1315,7 +1315,7 @@ static void swizzle_to_dml_params( int dcn20_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int pipe_cnt, i; bool synchronized_vblank = true; @@ -1733,7 +1733,7 @@ void dcn20_calculate_wm(struct dc *dc, struct dc_state *context, int *out_pipe_cnt, int *pipe_split_from, int vlevel, - bool fast_validate) + enum dc_validate_mode validate_mode) { int pipe_cnt, i, pipe_idx; @@ -1780,10 +1780,10 @@ void dcn20_calculate_wm(struct dc *dc, struct dc_state *context, if (pipe_cnt != pipe_idx) { if (dc->res_pool->funcs->populate_dml_pipes) pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes, fast_validate); + context, pipes, validate_mode); else pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, - context, pipes, fast_validate); + context, pipes, validate_mode); } *out_pipe_cnt = pipe_cnt; @@ -2027,7 +2027,7 @@ void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st } static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context, - bool fast_validate, display_e2e_pipe_params_st *pipes) + enum dc_validate_mode validate_mode, display_e2e_pipe_params_st *pipes) { bool out = false; @@ -2040,7 +2040,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co BW_VAL_TRACE_COUNT(); - out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); + out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode); if (pipe_cnt == 0) goto validate_out; @@ -2050,12 +2050,12 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } - dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); + dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, validate_mode); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); BW_VAL_TRACE_END_WATERMARKS(); @@ -2077,7 +2077,7 @@ validate_out: } bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, - bool fast_validate, display_e2e_pipe_params_st *pipes) + enum dc_validate_mode validate_mode, display_e2e_pipe_params_st *pipes) { bool voltage_supported = false; bool full_pstate_supported = false; @@ -2095,12 +2095,11 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, /*Unsafe due to current pipe merge and split logic*/ ASSERT(context != dc->current_state); - if (fast_validate) { - return dcn20_validate_bandwidth_internal(dc, context, true, pipes); - } + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) + return dcn20_validate_bandwidth_internal(dc, context, validate_mode, pipes); // Best case, we support full UCLK switch latency - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes); + voltage_supported = dcn20_validate_bandwidth_internal(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING, pipes); full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 || @@ -2113,7 +2112,7 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us; memset(pipes, 0, dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st)); - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes); + voltage_supported = dcn20_validate_bandwidth_internal(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING, pipes); dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) { @@ -2156,14 +2155,14 @@ void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, int dcn21_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { uint32_t pipe_cnt; int i; dc_assert_fp_enabled(); - pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); for (i = 0; i < pipe_cnt; i++) { @@ -2239,7 +2238,7 @@ static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context, int *out_pipe_cnt, int *pipe_split_from, int vlevel_req, - bool fast_validate) + enum dc_validate_mode validate_mode) { int pipe_cnt, i, pipe_idx; int vlevel, vlevel_max; @@ -2281,10 +2280,10 @@ static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context, if (pipe_cnt != pipe_idx) { if (dc->res_pool->funcs->populate_dml_pipes) pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes, fast_validate); + context, pipes, validate_mode); else pipe_cnt = dcn21_populate_dml_pipes_from_context(dc, - context, pipes, fast_validate); + context, pipes, validate_mode); } *out_pipe_cnt = pipe_cnt; @@ -2319,7 +2318,7 @@ static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context, } bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, - bool fast_validate, display_e2e_pipe_params_st *pipes) + enum dc_validate_mode validate_mode, display_e2e_pipe_params_st *pipes) { bool out = false; @@ -2337,7 +2336,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, /*Unsafe due to current pipe merge and split logic*/ ASSERT(context != dc->current_state); - out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); + out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode); if (pipe_cnt == 0) goto validate_out; @@ -2347,12 +2346,12 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } - dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); + dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, validate_mode); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); BW_VAL_TRACE_END_WATERMARKS(); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h index b6c34198ddc86..aed00039ca625 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h @@ -44,14 +44,14 @@ void dcn20_calculate_dlg_params(struct dc *dc, int dcn20_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn20_calculate_wm(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int *out_pipe_cnt, int *pipe_split_from, int vlevel, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn20_cap_soc_clocks(struct _vcs_dpi_soc_bounding_box_st *bb, struct pp_smu_nv_clock_table max_clocks); void dcn20_update_bounding_box(struct dc *dc, @@ -62,7 +62,7 @@ void dcn20_update_bounding_box(struct dc *dc, void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb); bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, - bool fast_validate, display_e2e_pipe_params_st *pipes); + enum dc_validate_mode validate_mode, display_e2e_pipe_params_st *pipes); void dcn20_fpu_set_wm_ranges(int i, struct pp_smu_wm_range_sets *ranges, struct _vcs_dpi_soc_bounding_box_st *loaded_bb); @@ -75,9 +75,9 @@ void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, int dcn21_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); -bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, bool - fast_validate, display_e2e_pipe_params_st *pipes); + enum dc_validate_mode validate_mode); +bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, enum + dc_validate_mode, display_e2e_pipe_params_st *pipes); void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index 88789987bdbcb..e5f5c0663750c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -339,7 +339,8 @@ void dcn30_fpu_calculate_wm_and_dlg( * newly found dummy_latency_index */ context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; - dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false, true); + dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, + DC_VALIDATE_MODE_AND_PROGRAMMING, true); maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] != dm_dram_clock_change_unsupported; @@ -630,7 +631,8 @@ int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, while (dummy_latency_index < max_latency_table_entries) { context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us; - dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false, true); + dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, + DC_VALIDATE_MODE_AND_PROGRAMMING, true); if (context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank == dm_allow_self_refresh_and_mclk_switch) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h index d2ae43a82ba56..dfcc5d50071e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h @@ -55,5 +55,5 @@ int dcn_get_approx_det_segs_required_for_pstate( int dcn31x_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); #endif /* __DCN31_FPU_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index 5ed117e11aa2a..df9d50b9b57cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -306,7 +306,7 @@ static unsigned int get_vertical_back_porch(struct dc_crtc_timing *timing) int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -316,7 +316,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c dc_assert_fp_enabled(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h index d32c5bb99f4c9..362ac79184ea2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h @@ -35,6 +35,6 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params); int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index b0fc1fd202084..6160952245b43 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -290,7 +290,7 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = temp_clock_change_support; context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us; - dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false); + dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, DC_VALIDATE_MODE_AND_PROGRAMMING); /* for subvp + DRR case, if subvp pipes are still present we support pstate */ if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported && @@ -1479,7 +1479,7 @@ static bool dcn32_full_validate_bw_helper(struct dc *dc, /* Conditions for setting up phantom pipes for SubVP: * 1. Not force disable SubVP - * 2. Full update (i.e. !fast_validate) + * 2. Full update (i.e. DC_VALIDATE_MODE_AND_PROGRAMMING) * 3. Enough pipes are available to support SubVP (TODO: Which pipes will use VACTIVE / VBLANK / SUBVP?) * 4. Display configuration passes validation * 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch) @@ -1517,7 +1517,8 @@ static bool dcn32_full_validate_bw_helper(struct dc *dc, dc->res_pool->funcs->add_phantom_pipes(dc, context, pipes, *pipe_cnt, dc_pipe_idx); - *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false); + *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, + DC_VALIDATE_MODE_AND_PROGRAMMING); // Populate dppclk to trigger a recalculate in dml_get_voltage_level // so the phantom pipe DLG params can be assigned correctly. pipes[0].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, *pipe_cnt, 0); @@ -1560,7 +1561,8 @@ static bool dcn32_full_validate_bw_helper(struct dc *dc, dc_state_remove_phantom_streams_and_planes(dc, context); dc_state_release_phantom_streams_and_planes(dc, context); vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported; - *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false); + *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, + DC_VALIDATE_MODE_AND_PROGRAMMING); *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); /* This may adjust vlevel and maxMpcComb */ @@ -2138,7 +2140,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *vlevel_out, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; bool repopulate_pipes = false; @@ -2162,7 +2164,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, for (i = 0; i < context->stream_count; i++) resource_update_pipes_for_stream_with_slice_count(context, dc->current_state, dc->res_pool, context->streams[i], 1); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); if (!pipe_cnt) { out = true; @@ -2172,13 +2174,13 @@ bool dcn32_internal_validate_bw(struct dc *dc, dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); context->bw_ctx.dml.soc.max_vratio_pre = dcn32_determine_max_vratio_prefetch(dc, context); - if (!fast_validate) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) { if (!dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt, &repopulate_pipes)) goto validate_fail; } - if (fast_validate || + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING || (dc->debug.dml_disallow_alternate_prefetch_modes && (vlevel == context->bw_ctx.dml.soc.num_states || vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported))) { @@ -2195,7 +2197,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = dm_prefetch_support_none; - context->bw_ctx.dml.validate_max_state = fast_validate; + context->bw_ctx.dml.validate_max_state = (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING); vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); context->bw_ctx.dml.validate_max_state = false; @@ -2247,7 +2249,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, int flag_vlevel = vlevel; int i; - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); if (!dc->config.enable_windowed_mpo_odm) dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes); @@ -2343,7 +2345,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, } context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; - dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false); + dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, DC_VALIDATE_MODE_AND_PROGRAMMING); maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; if (is_subvp_p_drr) { context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; @@ -2389,7 +2391,8 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us; } - dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel_temp, false); + dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel_temp, + DC_VALIDATE_MODE_AND_PROGRAMMING); if (vlevel_temp < vlevel) { vlevel = vlevel_temp; maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; @@ -2410,7 +2413,8 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, stream_status->fpo_in_use = false; } context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us; - dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false); + dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, + DC_VALIDATE_MODE_AND_PROGRAMMING); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h index 276e90e4e0cea..273d2bd79d85b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h @@ -49,7 +49,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *vlevel_out, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 92f0a099d089a..5d73efa2f0c90 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -437,7 +437,7 @@ static unsigned int get_vertical_back_porch(struct dc_crtc_timing *timing) int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -446,7 +446,7 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, const unsigned int max_allowed_vblank_nom = 1023; dcn31_populate_dml_pipes_from_context(dc, context, pipes, - fast_validate); + validate_mode); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h index 067480fc36913..d121c5afce718 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h @@ -37,7 +37,7 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c index 17d0b4923b0cc..6f516af829564 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c @@ -470,7 +470,7 @@ static unsigned int get_vertical_back_porch(struct dc_crtc_timing *timing) int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -479,7 +479,7 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc, const unsigned int max_allowed_vblank_nom = 1023; dcn31_populate_dml_pipes_from_context(dc, context, pipes, - fast_validate); + validate_mode); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.h index f93efab9a6684..f71d9d8d07596 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.h @@ -12,7 +12,7 @@ void dcn351_update_bw_bounding_box_fpu(struct dc *dc, int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn351_decide_zstate_support(struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index c8e78a8d15396..2127078b73b0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -326,12 +326,13 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co return true; } -bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, bool fast_validate) +bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, + enum dc_validate_mode validate_mode) { bool out = false; - /* Use dml_validate_only for fast_validate path */ - if (fast_validate) + /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */ + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) out = dml21_check_mode_support(in_dc, context, dml_ctx); else out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.h index 42e715024bc91..204ff97d50fa7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.h @@ -14,6 +14,7 @@ struct dc; struct dc_state; struct dml2_configuration_options; struct dml2_context; +enum dc_validate_mode; /** * dml2_create - Creates dml21_context. @@ -39,16 +40,17 @@ void dml21_reinit(const struct dc *in_dc, struct dml2_context **dml_ctx, const s * dml21_validate - Determines if a display configuration is supported or not. * @in_dc: dc. * @context: dc_state to be validated. - * @fast_validate: Fast validate will not populate context.res_ctx. + * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX + * will not populate context.res_ctx. * * Based on fast_validate option internally would call: * - * -dml21_mode_check_and_programming - for non fast_validate option + * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option * Calculates if dc_state can be supported on the input display * configuration. If supported, generates the necessary HW * programming for the new dc_state. * - * -dml21_check_mode_support - for fast_validate option + * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option * Calculates if dc_state can be supported for the input display * config. @@ -56,7 +58,8 @@ void dml21_reinit(const struct dc *in_dc, struct dml2_context **dml_ctx, const s * separate dc_states for validation. * Return: True if mode is supported, false otherwise. */ -bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, bool fast_validate); +bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, + enum dc_validate_mode validate_mode); /* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c index 6b3b8803e0aee..a56e75cdf7123 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c @@ -868,7 +868,7 @@ bool dml2_svp_remove_all_phantom_pipes(struct dml2_context *ctx, struct dc_state /* Conditions for setting up phantom pipes for SubVP: * 1. Not force disable SubVP - * 2. Full update (i.e. !fast_validate) + * 2. Full update (i.e. DC_VALIDATE_MODE_AND_PROGRAMMING) * 3. Enough pipes are available to support SubVP (TODO: Which pipes will use VACTIVE / VBLANK / SUBVP?) * 4. Display configuration passes validation * 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index a90aeecd3b502..b8c0ece7bb224 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -721,7 +721,8 @@ static void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *d } } -bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2, bool fast_validate) +bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2, + enum dc_validate_mode validate_mode) { bool out = false; @@ -731,14 +732,14 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2 /* DML2.1 validation path */ if (dml2->architecture == dml2_architecture_21) { - out = dml21_validate(in_dc, context, dml2, fast_validate); + out = dml21_validate(in_dc, context, dml2, validate_mode); return out; } DC_FP_START(); - /* Use dml_validate_only for fast_validate path */ - if (fast_validate) + /* Use dml_validate_only for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */ + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) out = dml2_validate_only(context); else out = dml2_validate_and_build_resource(in_dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 5100f269368e7..ff52301bcfc02 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -272,7 +272,7 @@ void dml2_reinit(const struct dc *in_dc, * dml2_validate - Determines if a display configuration is supported or not. * @in_dc: dc. * @context: dc_state to be validated. - * @fast_validate: Fast validate will not populate context.res_ctx. + * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX will not populate context.res_ctx. * * DML1.0 compatible interface for validation. * @@ -295,7 +295,7 @@ void dml2_reinit(const struct dc *in_dc, bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2, - bool fast_validate); + enum dc_validate_mode validate_mode); /* * dml2_extract_dram_and_fclk_change_support - Extracts the FCLK and UCLK change support info. diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 4ea3b4ad179bf..486f7b723ceb1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -2484,7 +2484,7 @@ bool dcn20_update_bandwidth( struct dce_hwseq *hws = dc->hwseq; /* recalculate DML parameters */ - if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) + if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) return false; /* apply updated bandwidth parameters */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index ea28c75fdacec..97c3482721db6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -2383,7 +2383,7 @@ bool dcn401_update_bandwidth( struct dce_hwseq *hws = dc->hwseq; /* recalculate DML parameters */ - if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) + if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) return false; /* apply updated bandwidth parameters */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 56b0b3f59efcc..e88a016fb7a9e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -82,7 +82,7 @@ struct resource_funcs { enum dc_status (*validate_bandwidth)( struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); void (*calculate_wm_and_dlg)( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -107,7 +107,7 @@ struct resource_funcs { struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); /* * Algorithm for assigning available link encoders to links. diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index d19a595c2be40..134091d5842d0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -622,7 +622,7 @@ extern const struct dcn_ip_params dcn10_ip_defaults; bool dcn_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn_get_soc_clks( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c index 84f73fdb0f952..3a51be63f0208 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c @@ -839,7 +839,7 @@ static enum dc_status build_mapped_resource( static enum dc_status dce100_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i; bool at_least_one_pipe = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c index f3d5baac11bfd..cccde5a6f3cdf 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c @@ -963,7 +963,7 @@ static enum dc_status build_mapped_resource( static enum dc_status dce110_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool result = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c index 4225cae68c109..164ba796f64ce 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c @@ -886,7 +886,7 @@ static enum dc_status build_mapped_resource( enum dc_status dce112_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool result = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h index 6221d749246d8..3efc4c55d2d20 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h @@ -45,7 +45,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); enum dc_status dce112_add_stream_to_ctx( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c index d9ffdded5ce1e..58b59d52dc9d3 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c @@ -866,7 +866,7 @@ static void dce60_resource_destruct(struct dce110_resource_pool *pool) static enum dc_status dce60_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i; bool at_least_one_pipe = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c index bd5811f975318..3e8b0ac11d906 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c @@ -872,7 +872,7 @@ static void dce80_resource_destruct(struct dce110_resource_pool *pool) static enum dc_status dce80_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i; bool at_least_one_pipe = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c index be4ade0853e9a..652c05c354947 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c @@ -1129,12 +1129,12 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) static enum dc_status dcn10_validate_bandwidth( struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool voltage_supported; DC_FP_START(); - voltage_supported = dcn_validate_bandwidth(dc, context, fast_validate); + voltage_supported = dcn_validate_bandwidth(dc, context, validate_mode); DC_FP_END(); return voltage_supported ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index 3405be07f5e3a..067a93420a237 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -2007,7 +2007,7 @@ bool dcn20_fast_validate_bw( int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -2021,7 +2021,7 @@ bool dcn20_fast_validate_bw( dcn20_merge_pipes_for_validate(dc, context); DC_FP_START(); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); DC_FP_END(); *pipe_cnt_out = pipe_cnt; @@ -2125,7 +2125,7 @@ validate_out: } enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool voltage_supported; display_e2e_pipe_params_st *pipes; @@ -2135,7 +2135,7 @@ enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, return DC_FAIL_BANDWIDTH_VALIDATE; DC_FP_START(); - voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes); + voltage_supported = dcn20_validate_bandwidth_fp(dc, context, validate_mode, pipes); DC_FP_END(); kfree(pipes); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h index c0e062c7407dc..e997d35a8b86e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h @@ -119,7 +119,7 @@ void dcn20_set_mcif_arb_params( struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt); -enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, enum dc_validate_mode validate_mode); void dcn20_merge_pipes_for_validate( struct dc *dc, struct dc_state *context); @@ -158,7 +158,7 @@ bool dcn20_fast_validate_bw( int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - bool fast_validate); + enum dc_validate_mode validate_mode); enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream); enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c index 9ab01b65b177b..238d7f8beb7c7 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -769,7 +769,7 @@ bool dcn21_fast_validate_bw(struct dc *dc, int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -783,7 +783,7 @@ bool dcn21_fast_validate_bw(struct dc *dc, dcn20_merge_pipes_for_validate(dc, context); DC_FP_START(); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); DC_FP_END(); *pipe_cnt_out = pipe_cnt; @@ -924,7 +924,7 @@ validate_out: * dcn20_validate_bandwidth in dcn20_resource.c. */ static enum dc_status dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool voltage_supported; display_e2e_pipe_params_st *pipes; @@ -934,7 +934,7 @@ static enum dc_status dcn21_validate_bandwidth(struct dc *dc, struct dc_state *c return DC_FAIL_BANDWIDTH_VALIDATE; DC_FP_START(); - voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes); + voltage_supported = dcn21_validate_bandwidth_fp(dc, context, validate_mode, pipes); DC_FP_END(); kfree(pipes); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h index f7ecc002c2f7f..a017fd9854d14 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h @@ -51,6 +51,6 @@ bool dcn21_fast_validate_bw( int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - bool fast_validate); + enum dc_validate_mode validate_mode); #endif /* _DCN21_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index f631ae34e3200..4d4635e01eb64 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -1319,13 +1319,13 @@ static struct clock_source *dcn30_clock_source_create( int dcn30_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; DC_FP_START(); - dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { @@ -1627,7 +1627,7 @@ noinline bool dcn30_internal_validate_bw( display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *vlevel_out, - bool fast_validate, + enum dc_validate_mode validate_mode, bool allow_self_refresh_only) { bool out = false; @@ -1646,7 +1646,7 @@ noinline bool dcn30_internal_validate_bw( context->bw_ctx.dml.vba.VoltageLevel = 0; context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; dc->res_pool->funcs->update_soc_for_wm_a(dc, context); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); if (!pipe_cnt) { out = true; @@ -1655,7 +1655,7 @@ noinline bool dcn30_internal_validate_bw( dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); - if (!fast_validate || !allow_self_refresh_only) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING || !allow_self_refresh_only) { /* * DML favors voltage over p-state, but we're more interested in * supporting p-state over voltage. We can't support p-state in @@ -1669,7 +1669,7 @@ noinline bool dcn30_internal_validate_bw( vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); } if (allow_self_refresh_only && - (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || + (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING || vlevel == context->bw_ctx.dml.soc.num_states || vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { /* * If mode is unsupported or there's still no p-state support @@ -1678,7 +1678,7 @@ noinline bool dcn30_internal_validate_bw( * We don't actually support prefetch mode 2, so require that we * at least support prefetch mode 1. */ - context->bw_ctx.dml.validate_max_state = fast_validate; + context->bw_ctx.dml.validate_max_state = (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING); context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = dm_allow_self_refresh; @@ -1865,7 +1865,7 @@ noinline bool dcn30_internal_validate_bw( } if (repopulate_pipes) - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode); context->bw_ctx.dml.vba.VoltageLevel = vlevel; *vlevel_out = vlevel; *pipe_cnt_out = pipe_cnt; @@ -2037,7 +2037,7 @@ void dcn30_calculate_wm_and_dlg( enum dc_status dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; @@ -2055,7 +2055,7 @@ enum dc_status dcn30_validate_bandwidth(struct dc *dc, goto validate_fail; DC_FP_START(); - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, validate_mode, true); DC_FP_END(); if (pipe_cnt == 0) @@ -2066,7 +2066,7 @@ enum dc_status dcn30_validate_bandwidth(struct dc *dc, BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h index 689d9bdace81e..2c967fe557121 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h @@ -57,14 +57,14 @@ unsigned int dcn30_calc_max_scaled_time( unsigned int urgent_watermark); enum dc_status dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); bool dcn30_internal_validate_bw( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int *pipe_cnt_out, int *vlevel_out, - bool fast_validate, + enum dc_validate_mode validate_mode, bool allow_self_refresh_only); void dcn30_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, @@ -78,7 +78,7 @@ void dcn30_populate_dml_writeback_from_context( int dcn30_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); bool dcn30_acquire_post_bldn_3dlut( struct resource_context *res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index 7e0af5297dc42..6b6efc2e75c0d 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -1616,14 +1616,14 @@ static bool is_dual_plane(enum surface_pixel_format format) int dcn31x_populate_dml_pipes_from_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { uint32_t pipe_cnt; int i; dc_assert_fp_enabled(); - pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); for (i = 0; i < pipe_cnt; i++) { pipes[i].pipe.src.gpuvm = 1; @@ -1641,7 +1641,7 @@ int dcn31x_populate_dml_pipes_from_context(struct dc *dc, int dcn31_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -1649,7 +1649,7 @@ int dcn31_populate_dml_pipes_from_context( bool upscaled = false; DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { @@ -1760,7 +1760,7 @@ dcn31_set_mcif_arb_params(struct dc *dc, enum dc_status dcn31_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; @@ -1778,19 +1778,19 @@ enum dc_status dcn31_validate_bandwidth(struct dc *dc, goto validate_fail; DC_FP_START(); - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, validate_mode, true); DC_FP_END(); - // Disable fast_validate to set min dcfclk in calculate_wm_and_dlg + // Disable DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX to set min dcfclk in calculate_wm_and_dlg if (pipe_cnt == 0) - fast_validate = false; + validate_mode = DC_VALIDATE_MODE_AND_PROGRAMMING; if (!out) goto validate_fail; BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h index dd82815d7efec..1456bcf01ad23 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h @@ -39,7 +39,7 @@ struct dcn31_resource_pool { enum dc_status dcn31_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn31_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -48,7 +48,7 @@ void dcn31_calculate_wm_and_dlg( int dcn31_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn31_populate_dml_writeback_from_context(struct dc *dc, struct resource_context *res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index d96bc6cb73adc..e84526c515905 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -1667,12 +1667,12 @@ static struct clock_source *dcn31_clock_source_create( static int dcn314_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int pipe_cnt; DC_FP_START(); - pipe_cnt = dcn314_populate_dml_pipes_from_context_fpu(dc, context, pipes, fast_validate); + pipe_cnt = dcn314_populate_dml_pipes_from_context_fpu(dc, context, pipes, validate_mode); DC_FP_END(); return pipe_cnt; @@ -1696,7 +1696,7 @@ static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_confi enum dc_status dcn314_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; @@ -1715,19 +1715,19 @@ enum dc_status dcn314_validate_bandwidth(struct dc *dc, DC_FP_START(); // do not support self refresh only - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, validate_mode, false); DC_FP_END(); - // Disable fast_validate to set min dcfclk in calculate_wm_and_dlg + // Disable DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX to set min dcfclk in calculate_wm_and_dlg if (pipe_cnt == 0) - fast_validate = false; + validate_mode = DC_VALIDATE_MODE_AND_PROGRAMMING; if (!out) goto validate_fail; BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h index f8ba531d6342f..ac9bb7f097d5c 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h @@ -41,7 +41,7 @@ struct dcn314_resource_pool { enum dc_status dcn314_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); struct resource_pool *dcn314_create_resource_pool( const struct dc_init_data *init_data, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index 6c2bb3f63be15..ac15c7c33abfc 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1664,7 +1664,7 @@ static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) static int dcn315_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt, crb_idx, crb_pipes; struct resource_context *res_ctx = &context->res_ctx; @@ -1674,7 +1674,7 @@ static int dcn315_populate_dml_pipes_from_context( bool pixel_rate_crb = allow_pixel_rate_crb(dc, context); DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); DC_FP_END(); for (i = 0, pipe_cnt = 0, crb_pipes = 0; i < dc->res_pool->pipe_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c index 568094827212d..2b7e616225794 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c @@ -1610,7 +1610,7 @@ static bool is_dual_plane(enum surface_pixel_format format) static int dcn316_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -1618,7 +1618,7 @@ static int dcn316_populate_dml_pipes_from_context( const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB; DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index bb0dae0be5b87..a7a78a2752de2 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -1742,7 +1742,7 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, } } -static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate) +static bool dml1_validate(struct dc *dc, struct dc_state *context, enum dc_validate_mode validate_mode) { bool out = false; @@ -1767,7 +1767,7 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val goto validate_fail; DC_FP_START(); - out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); + out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, validate_mode); DC_FP_END(); if (pipe_cnt == 0) @@ -1778,7 +1778,7 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - if (fast_validate) { + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) { BW_VAL_TRACE_SKIP(fast); goto validate_out; } @@ -1809,7 +1809,7 @@ validate_out: enum dc_status dcn32_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { unsigned int i; enum dc_status status; @@ -1827,11 +1827,11 @@ enum dc_status dcn32_validate_bandwidth(struct dc *dc, if (dc->debug.using_dml2) status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; else - status = dml1_validate(dc, context, fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + status = dml1_validate(dc, context, validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; - if (!fast_validate && status == DC_OK && dc_state_is_subvp_in_use(context)) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_OK && dc_state_is_subvp_in_use(context)) { /* check new stream configuration still supports cursor if subvp used */ for (i = 0; i < context->stream_count; i++) { stream = context->streams[i]; @@ -1846,14 +1846,14 @@ enum dc_status dcn32_validate_bandwidth(struct dc *dc, }; } - if (!fast_validate && status == DC_FAIL_HW_CURSOR_SUPPORT) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_FAIL_HW_CURSOR_SUPPORT) { /* attempt to validate again with subvp disabled due to cursor */ if (dc->debug.using_dml2) status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; else - status = dml1_validate(dc, context, fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + status = dml1_validate(dc, context, validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; } return status; @@ -1862,7 +1862,7 @@ enum dc_status dcn32_validate_bandwidth(struct dc *dc, int dcn32_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate) + enum dc_validate_mode validate_mode) { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; @@ -1878,7 +1878,7 @@ int dcn32_populate_dml_pipes_from_context( int num_subvp_none = 0; int odm_slice_count; - dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, validate_mode); /* For single display subvp, look for subvp main so if we have phantom * pipe, we can set odm policy to match main pipe @@ -1960,7 +1960,7 @@ int dcn32_populate_dml_pipes_from_context( /* Only populate DML input with subvp info for full updates. * This is just a workaround -- needs a proper fix. */ - if (!fast_validate) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) { switch (dc_state_get_pipe_subvp_type(context, pipe)) { case SUBVP_MAIN: pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h index d60ed77eda80b..82f966cf4ed27 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h @@ -100,12 +100,12 @@ void dcn32_add_phantom_pipes(struct dc *dc, enum dc_status dcn32_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); int dcn32_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn32_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 72c6cf047db06..62f6c7abb9c69 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -1734,15 +1734,15 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config static enum dc_status dcn35_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate); + validate_mode); - if (fast_validate) + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; DC_FP_START(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c index 989a270f7deaa..85a96258bce85 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c @@ -1714,15 +1714,15 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config static enum dc_status dcn351_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate); + validate_mode); - if (fast_validate) + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; DC_FP_START(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c index 48e1f234185ff..e977866802bff 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c @@ -1715,15 +1715,15 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config static enum dc_status dcn35_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { bool out = false; out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate); + validate_mode); - if (fast_validate) + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; DC_FP_START(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index fbb6db1baaadf..1dce22b81c973 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1644,7 +1644,7 @@ enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_sta enum dc_status dcn401_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) + enum dc_validate_mode validate_mode) { unsigned int i; enum dc_status status = DC_OK; @@ -1662,9 +1662,9 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, if (dc->debug.using_dml2) status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; - if (!fast_validate && status == DC_OK && dc_state_is_subvp_in_use(context)) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_OK && dc_state_is_subvp_in_use(context)) { /* check new stream configuration still supports cursor if subvp used */ for (i = 0; i < context->stream_count; i++) { stream = context->streams[i]; @@ -1679,12 +1679,12 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, }; } - if (!fast_validate && status == DC_FAIL_HW_CURSOR_SUPPORT) { + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_FAIL_HW_CURSOR_SUPPORT) { /* attempt to validate again with subvp disabled due to cursor */ if (dc->debug.using_dml2) status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, - fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; } return status; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h index dc52a30991afd..2ae6831c31eff 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h @@ -24,7 +24,7 @@ enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_sta enum dc_status dcn401_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); + enum dc_validate_mode validate_mode); void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context); -- GitLab From 78d7032b08385a6bf64915b3fc11e9a4d1803302 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Mon, 26 May 2025 14:47:08 -0500 Subject: [PATCH 203/902] drm/amd/display: Promote DAL to 3.2.336 This version brings along following fixes: - Fix brightness relevant settings - Fix calling blanking stream twice - Extend dc mode validation types to support more scenarios - Update DMCUB loading sequence for DCN3.5 Acked-by: ChiaHsuan Chung Signed-off-by: Taimur Hassan Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9878868ff4d2f..4984700b5f1b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.335" +#define DC_VER "3.2.336" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC -- GitLab From 8a3514d348de87a9d5e2ac00fbac4faae0b97996 Mon Sep 17 00:00:00 2001 From: Sanjeev Yadav Date: Fri, 23 May 2025 13:14:01 -0700 Subject: [PATCH 204/902] scsi: core: ufs: Fix a hang in the error handler ufshcd_err_handling_prepare() calls ufshcd_rpm_get_sync(). The latter function can only succeed if UFSHCD_EH_IN_PROGRESS is not set because resuming involves submitting a SCSI command and ufshcd_queuecommand() returns SCSI_MLQUEUE_HOST_BUSY if UFSHCD_EH_IN_PROGRESS is set. Fix this hang by setting UFSHCD_EH_IN_PROGRESS after ufshcd_rpm_get_sync() has been called instead of before. Backtrace: __switch_to+0x174/0x338 __schedule+0x600/0x9e4 schedule+0x7c/0xe8 schedule_timeout+0xa4/0x1c8 io_schedule_timeout+0x48/0x70 wait_for_common_io+0xa8/0x160 //waiting on START_STOP wait_for_completion_io_timeout+0x10/0x20 blk_execute_rq+0xe4/0x1e4 scsi_execute_cmd+0x108/0x244 ufshcd_set_dev_pwr_mode+0xe8/0x250 __ufshcd_wl_resume+0x94/0x354 ufshcd_wl_runtime_resume+0x3c/0x174 scsi_runtime_resume+0x64/0xa4 rpm_resume+0x15c/0xa1c __pm_runtime_resume+0x4c/0x90 // Runtime resume ongoing ufshcd_err_handler+0x1a0/0xd08 process_one_work+0x174/0x808 worker_thread+0x15c/0x490 kthread+0xf4/0x1ec ret_from_fork+0x10/0x20 Signed-off-by: Sanjeev Yadav [ bvanassche: rewrote patch description ] Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver") Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20250523201409.1676055-1-bvanassche@acm.org Reviewed-by: Peter Wang Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a7513f256057b..a1d7c8660c1bf 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -6623,9 +6623,14 @@ static void ufshcd_err_handler(struct work_struct *work) up(&hba->host_sem); return; } - ufshcd_set_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_err_handling_prepare(hba); + + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_set_eh_in_progress(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + /* Complete requests that have door-bell cleared by h/w */ ufshcd_complete_requests(hba, false); spin_lock_irqsave(hba->host->host_lock, flags); -- GitLab From 531bef26d189b28bf0d694878c0e064b30990b6c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 21 May 2025 11:01:02 +0200 Subject: [PATCH 205/902] drm/xe/svm: Fix regression disallowing 64K SVM migration When changing the condition from >= SZ_64K, it was changed to <= SZ_64K. This disallows migration of 64K, which is the exact minimum allowed. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5057 Fixes: a9ac0fa455b0 ("drm/xe: Strict migration policy for atomic SVM faults") Cc: stable@vger.kernel.org Cc: Matthew Brost Cc: Himal Prasad Ghimiray Reviewed-by: Himal Prasad Ghimiray Signed-off-by: Maarten Lankhorst Link: https://lore.kernel.org/r/20250521090102.2965100-1-dev@lankhorst.se --- drivers/gpu/drm/xe/xe_svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index f27fb9b588de1..83c63fd7b4819 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -820,7 +820,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm return false; } - if (preferred_region_is_vram && range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + if (preferred_region_is_vram && range_size < SZ_64K && !supports_4K_migration(vm->xe)) { drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); return false; } -- GitLab From 7fb3a1f7a48d9512f092d2b18bd4b9361ff88e51 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:07 +0300 Subject: [PATCH 206/902] drm/i915/sbi: move intel_sbi.[ch] under display/ The LPT/WPT SBI is arguably part of south display, and it's only used by intel_pch_refclk.c anyway. Move it under display/. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/341268d633e9705bc582f1cc985dc4554e39d87d.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/{ => display}/intel_sbi.c | 0 drivers/gpu/drm/i915/{ => display}/intel_sbi.h | 0 drivers/gpu/drm/i915/i915_driver.c | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename drivers/gpu/drm/i915/{ => display}/intel_sbi.c (100%) rename drivers/gpu/drm/i915/{ => display}/intel_sbi.h (100%) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1a90eb1f180aa..333847892e189 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -40,7 +40,6 @@ i915-y += \ intel_pcode.o \ intel_region_ttm.o \ intel_runtime_pm.o \ - intel_sbi.o \ intel_step.o \ intel_uncore.o \ intel_uncore_trace.o \ @@ -288,6 +287,7 @@ i915-y += \ display/intel_pmdemand.o \ display/intel_psr.o \ display/intel_quirks.o \ + display/intel_sbi.o \ display/intel_sprite.o \ display/intel_sprite_uapi.o \ display/intel_tc.o \ diff --git a/drivers/gpu/drm/i915/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c similarity index 100% rename from drivers/gpu/drm/i915/intel_sbi.c rename to drivers/gpu/drm/i915/display/intel_sbi.c diff --git a/drivers/gpu/drm/i915/intel_sbi.h b/drivers/gpu/drm/i915/display/intel_sbi.h similarity index 100% rename from drivers/gpu/drm/i915/intel_sbi.h rename to drivers/gpu/drm/i915/display/intel_sbi.h diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 3b0bda74697d7..a77afea47202e 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -63,6 +63,7 @@ #include "display/intel_overlay.h" #include "display/intel_pch_refclk.h" #include "display/intel_pps.h" +#include "display/intel_sbi.h" #include "display/intel_sprite_uapi.h" #include "display/skl_watermark.h" @@ -109,7 +110,6 @@ #include "intel_pci_config.h" #include "intel_pcode.h" #include "intel_region_ttm.h" -#include "intel_sbi.h" #include "vlv_iosf_sb.h" #include "vlv_suspend.h" -- GitLab From a737ab4a87cb4a58b564a97bf313c8dfc15c7c53 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:08 +0300 Subject: [PATCH 207/902] drm/i915/sbi: convert intel_sbi.[ch] to struct intel_display Convert intel_sbi.[ch] to struct intel_display, as much as possible anyway, and as a consequence drop the dependency on i915_drv.h from intel_pch_refclk.c. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/9fa9f9a828a7e0e93208111566478b16838abe0d.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_pch_refclk.c | 148 +++++++++--------- drivers/gpu/drm/i915/display/intel_sbi.c | 38 +++-- drivers/gpu/drm/i915/display/intel_sbi.h | 14 +- drivers/gpu/drm/i915/i915_driver.c | 4 +- 4 files changed, 103 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 9f6102d7c7be7..43710ba7ebde8 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -3,8 +3,10 @@ * Copyright © 2021 Intel Corporation */ -#include "i915_drv.h" +#include + #include "i915_reg.h" +#include "i915_utils.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_panel.h" @@ -29,95 +31,93 @@ static void lpt_fdi_reset_mphy(struct intel_display *display) /* WaMPhyProgramming:hsw */ static void lpt_fdi_program_mphy(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; lpt_fdi_reset_mphy(display); - tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY); + tmp = intel_sbi_read(display, 0x8008, SBI_MPHY); tmp &= ~(0xFF << 24); tmp |= (0x12 << 24); - intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY); + intel_sbi_write(display, 0x8008, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2008, SBI_MPHY); tmp |= (1 << 11); - intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2008, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2108, SBI_MPHY); tmp |= (1 << 11); - intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2108, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY); + tmp = intel_sbi_read(display, 0x206C, SBI_MPHY); tmp |= (1 << 24) | (1 << 21) | (1 << 18); - intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY); + intel_sbi_write(display, 0x206C, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY); + tmp = intel_sbi_read(display, 0x216C, SBI_MPHY); tmp |= (1 << 24) | (1 << 21) | (1 << 18); - intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY); + intel_sbi_write(display, 0x216C, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2080, SBI_MPHY); tmp &= ~(7 << 13); tmp |= (5 << 13); - intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2080, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2180, SBI_MPHY); tmp &= ~(7 << 13); tmp |= (5 << 13); - intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2180, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY); + tmp = intel_sbi_read(display, 0x208C, SBI_MPHY); tmp &= ~0xFF; tmp |= 0x1C; - intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY); + intel_sbi_write(display, 0x208C, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY); + tmp = intel_sbi_read(display, 0x218C, SBI_MPHY); tmp &= ~0xFF; tmp |= 0x1C; - intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY); + intel_sbi_write(display, 0x218C, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2098, SBI_MPHY); tmp &= ~(0xFF << 16); tmp |= (0x1C << 16); - intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2098, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY); + tmp = intel_sbi_read(display, 0x2198, SBI_MPHY); tmp &= ~(0xFF << 16); tmp |= (0x1C << 16); - intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY); + intel_sbi_write(display, 0x2198, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY); + tmp = intel_sbi_read(display, 0x20C4, SBI_MPHY); tmp |= (1 << 27); - intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY); + intel_sbi_write(display, 0x20C4, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY); + tmp = intel_sbi_read(display, 0x21C4, SBI_MPHY); tmp |= (1 << 27); - intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY); + intel_sbi_write(display, 0x21C4, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY); + tmp = intel_sbi_read(display, 0x20EC, SBI_MPHY); tmp &= ~(0xF << 28); tmp |= (4 << 28); - intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY); + intel_sbi_write(display, 0x20EC, tmp, SBI_MPHY); - tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY); + tmp = intel_sbi_read(display, 0x21EC, SBI_MPHY); tmp &= ~(0xF << 28); tmp |= (4 << 28); - intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); + intel_sbi_write(display, 0x21EC, tmp, SBI_MPHY); } void lpt_disable_iclkip(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 temp; intel_de_write(display, PIXCLK_GATE, PIXCLK_GATE_GATE); - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); temp |= SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL6, temp, SBI_ICLK); - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); } struct iclkip_params { @@ -178,8 +178,6 @@ int lpt_iclkip(const struct intel_crtc_state *crtc_state) void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int clock = crtc_state->hw.adjusted_mode.crtc_clock; struct iclkip_params p; u32 temp; @@ -199,30 +197,30 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc); - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); /* Program SSCDIVINTPHASE6 */ - temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCDIVINTPHASE6, SBI_ICLK); temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; temp |= SBI_SSCDIVINTPHASE_DIVSEL(p.divsel); temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; temp |= SBI_SSCDIVINTPHASE_INCVAL(p.phaseinc); temp |= SBI_SSCDIVINTPHASE_DIR(p.phasedir); temp |= SBI_SSCDIVINTPHASE_PROPAGATE; - intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); /* Program SSCAUXDIV */ - temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCAUXDIV6, SBI_ICLK); temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); temp |= SBI_SSCAUXDIV_FINALDIV2SEL(p.auxdiv); - intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCAUXDIV6, temp, SBI_ICLK); /* Enable modulator and associated divider */ - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); temp &= ~SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL6, temp, SBI_ICLK); - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); /* Wait for initialization time */ udelay(24); @@ -232,7 +230,6 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) int lpt_get_iclkip(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct iclkip_params p; u32 temp; @@ -241,25 +238,25 @@ int lpt_get_iclkip(struct intel_display *display) iclkip_params_init(&p); - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); - temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); if (temp & SBI_SSCCTL_DISABLE) { - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); return 0; } - temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCDIVINTPHASE6, SBI_ICLK); p.divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; p.phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> SBI_SSCDIVINTPHASE_INCVAL_SHIFT; - temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); + temp = intel_sbi_read(display, SBI_SSCAUXDIV6, SBI_ICLK); p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc; @@ -275,7 +272,6 @@ int lpt_get_iclkip(struct intel_display *display) static void lpt_enable_clkout_dp(struct intel_display *display, bool with_spread, bool with_fdi) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 reg, tmp; if (drm_WARN(display->drm, with_fdi && !with_spread, @@ -285,57 +281,56 @@ static void lpt_enable_clkout_dp(struct intel_display *display, with_fdi, "LP PCH doesn't have FDI\n")) with_fdi = false; - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); tmp &= ~SBI_SSCCTL_DISABLE; tmp |= SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); udelay(24); if (with_spread) { - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); tmp &= ~SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); if (with_fdi) lpt_fdi_program_mphy(display); } reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0; - tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); + tmp = intel_sbi_read(display, reg, SBI_ICLK); tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; - intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); + intel_sbi_write(display, reg, tmp, SBI_ICLK); - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); } /* Sequence to disable CLKOUT_DP */ void lpt_disable_clkout_dp(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 reg, tmp; - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0; - tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); + tmp = intel_sbi_read(display, reg, SBI_ICLK); tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; - intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); + intel_sbi_write(display, reg, tmp, SBI_ICLK); - tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); if (!(tmp & SBI_SSCCTL_DISABLE)) { if (!(tmp & SBI_SSCCTL_PATHALT)) { tmp |= SBI_SSCCTL_PATHALT; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); udelay(32); } tmp |= SBI_SSCCTL_DISABLE; - intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); } - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); } #define BEND_IDX(steps) ((50 + (steps)) / 5) @@ -372,7 +367,6 @@ static const u16 sscdivintphase[] = { */ static void lpt_bend_clkout_dp(struct intel_display *display, int steps) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; int idx = BEND_IDX(steps); @@ -382,20 +376,20 @@ static void lpt_bend_clkout_dp(struct intel_display *display, int steps) if (drm_WARN_ON(display->drm, idx >= ARRAY_SIZE(sscdivintphase))) return; - intel_sbi_lock(dev_priv); + intel_sbi_lock(display); if (steps % 10 != 0) tmp = 0xAAAAAAAB; else tmp = 0x00000000; - intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCDITHPHASE, tmp, SBI_ICLK); - tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK); + tmp = intel_sbi_read(display, SBI_SSCDIVINTPHASE, SBI_ICLK); tmp &= 0xffff0000; tmp |= sscdivintphase[idx]; - intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); + intel_sbi_write(display, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); - intel_sbi_unlock(dev_priv); + intel_sbi_unlock(display); } #undef BEND_IDX diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index 41e85ac773dce..4b97be7da5c32 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -6,14 +6,16 @@ */ #include "i915_drv.h" -#include "intel_sbi.h" #include "i915_reg.h" +#include "intel_display_core.h" +#include "intel_sbi.h" /* SBI access */ -static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, +static int intel_sbi_rw(struct intel_display *display, u16 reg, enum intel_sbi_destination destination, u32 *val, bool is_read) { + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_uncore *uncore = &i915->uncore; u32 cmd; @@ -22,8 +24,7 @@ static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, if (intel_wait_for_register_fw(uncore, SBI_CTL_STAT, SBI_BUSY, 0, 100)) { - drm_err(&i915->drm, - "timeout waiting for SBI to become ready\n"); + drm_err(display->drm, "timeout waiting for SBI to become ready\n"); return -EBUSY; } @@ -41,13 +42,12 @@ static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, if (__intel_wait_for_register_fw(uncore, SBI_CTL_STAT, SBI_BUSY, 0, 100, 100, &cmd)) { - drm_err(&i915->drm, - "timeout waiting for SBI to complete read\n"); + drm_err(display->drm, "timeout waiting for SBI to complete read\n"); return -ETIMEDOUT; } if (cmd & SBI_RESPONSE_FAIL) { - drm_err(&i915->drm, "error during SBI read of reg %x\n", reg); + drm_err(display->drm, "error during SBI read of reg %x\n", reg); return -ENXIO; } @@ -57,38 +57,46 @@ static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, return 0; } -void intel_sbi_lock(struct drm_i915_private *i915) +void intel_sbi_lock(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + mutex_lock(&i915->sbi_lock); } -void intel_sbi_unlock(struct drm_i915_private *i915) +void intel_sbi_unlock(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + mutex_unlock(&i915->sbi_lock); } -u32 intel_sbi_read(struct drm_i915_private *i915, u16 reg, +u32 intel_sbi_read(struct intel_display *display, u16 reg, enum intel_sbi_destination destination) { u32 result = 0; - intel_sbi_rw(i915, reg, destination, &result, true); + intel_sbi_rw(display, reg, destination, &result, true); return result; } -void intel_sbi_write(struct drm_i915_private *i915, u16 reg, u32 value, +void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, enum intel_sbi_destination destination) { - intel_sbi_rw(i915, reg, destination, &value, false); + intel_sbi_rw(display, reg, destination, &value, false); } -void intel_sbi_init(struct drm_i915_private *i915) +void intel_sbi_init(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + mutex_init(&i915->sbi_lock); } -void intel_sbi_fini(struct drm_i915_private *i915) +void intel_sbi_fini(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + mutex_destroy(&i915->sbi_lock); } diff --git a/drivers/gpu/drm/i915/display/intel_sbi.h b/drivers/gpu/drm/i915/display/intel_sbi.h index 85161a4f13b8a..841f77a142a1c 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.h +++ b/drivers/gpu/drm/i915/display/intel_sbi.h @@ -8,20 +8,20 @@ #include -struct drm_i915_private; +struct intel_display; enum intel_sbi_destination { SBI_ICLK, SBI_MPHY, }; -void intel_sbi_init(struct drm_i915_private *i915); -void intel_sbi_fini(struct drm_i915_private *i915); -void intel_sbi_lock(struct drm_i915_private *i915); -void intel_sbi_unlock(struct drm_i915_private *i915); -u32 intel_sbi_read(struct drm_i915_private *i915, u16 reg, +void intel_sbi_init(struct intel_display *display); +void intel_sbi_fini(struct intel_display *display); +void intel_sbi_lock(struct intel_display *display); +void intel_sbi_unlock(struct intel_display *display); +u32 intel_sbi_read(struct intel_display *display, u16 reg, enum intel_sbi_destination destination); -void intel_sbi_write(struct drm_i915_private *i915, u16 reg, u32 value, +void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, enum intel_sbi_destination destination); #endif /* _INTEL_SBI_H_ */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index a77afea47202e..510eb3ed4b0ec 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -231,7 +231,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) spin_lock_init(&dev_priv->gpu_error.lock); - intel_sbi_init(dev_priv); + intel_sbi_init(display); vlv_iosf_sb_init(dev_priv); mutex_init(&dev_priv->sb_lock); @@ -292,7 +292,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) mutex_destroy(&dev_priv->sb_lock); vlv_iosf_sb_fini(dev_priv); - intel_sbi_fini(dev_priv); + intel_sbi_fini(display); i915_params_free(&dev_priv->params); -- GitLab From 9ab17ede10184041f9754296ab0801e9e1a064a1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:09 +0300 Subject: [PATCH 208/902] drm/i915/sbi: move sbi_lock under struct intel_display With SBI under display, also move sbi_lock to display->sbi.lock. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/838fa712fc8a691a3f9427e5f4ed551bd1c62c49.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_core.h | 5 +++++ drivers/gpu/drm/i915/display/intel_sbi.c | 18 +++++------------- drivers/gpu/drm/i915/i915_drv.h | 3 --- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 5f5dd2722d99c..32cb0e59c81ea 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -538,6 +538,11 @@ struct intel_display { u32 block_time_us; } sagv; + struct { + /* LPT/WPT IOSF sideband protection */ + struct mutex lock; + } sbi; + struct { /* * DG2: Mask of PHYs that were not calibrated by the firmware diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index 4b97be7da5c32..198a1ad280e28 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -19,7 +19,7 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, struct intel_uncore *uncore = &i915->uncore; u32 cmd; - lockdep_assert_held(&i915->sbi_lock); + lockdep_assert_held(&display->sbi.lock); if (intel_wait_for_register_fw(uncore, SBI_CTL_STAT, SBI_BUSY, 0, @@ -59,16 +59,12 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, void intel_sbi_lock(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - mutex_lock(&i915->sbi_lock); + mutex_lock(&display->sbi.lock); } void intel_sbi_unlock(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - mutex_unlock(&i915->sbi_lock); + mutex_unlock(&display->sbi.lock); } u32 intel_sbi_read(struct intel_display *display, u16 reg, @@ -89,14 +85,10 @@ void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, void intel_sbi_init(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - mutex_init(&i915->sbi_lock); + mutex_init(&display->sbi.lock); } void intel_sbi_fini(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - mutex_destroy(&i915->sbi_lock); + mutex_destroy(&display->sbi.lock); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b6c632bd522cd..455548cbd8206 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -223,9 +223,6 @@ struct drm_i915_private { bool irqs_enabled; - /* LPT/WPT IOSF sideband protection */ - struct mutex sbi_lock; - /* VLV/CHV IOSF sideband */ struct { struct mutex lock; /* protect sideband access */ -- GitLab From 07a86ee12e5a5eb4933c8cd8e450f54a0f359f61 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:10 +0300 Subject: [PATCH 209/902] drm/i915/de: rename timeout parameters timeout_ms to highlight unit The timeout parameters are in ms. Rename the parameters to highlight the unit. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/cd4c775ad323a577f612e6a942f83b22641fb798.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_de.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 54ce3e4f8fd90..823290e0cf7dd 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -107,10 +107,10 @@ intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear, u32 set) static inline int __intel_de_wait_for_register_nowl(struct intel_display *display, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout) + u32 mask, u32 value, unsigned int timeout_ms) { return intel_wait_for_register(__to_uncore(display), reg, mask, - value, timeout); + value, timeout_ms); } static inline int @@ -125,14 +125,14 @@ __intel_de_wait_for_register_atomic_nowl(struct intel_display *display, static inline int intel_de_wait(struct intel_display *display, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout) + u32 mask, u32 value, unsigned int timeout_ms) { int ret; intel_dmc_wl_get(display, reg); ret = __intel_de_wait_for_register_nowl(display, reg, mask, value, - timeout); + timeout_ms); intel_dmc_wl_put(display, reg); @@ -141,14 +141,14 @@ intel_de_wait(struct intel_display *display, i915_reg_t reg, static inline int intel_de_wait_fw(struct intel_display *display, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout) + u32 mask, u32 value, unsigned int timeout_ms) { int ret; intel_dmc_wl_get(display, reg); ret = intel_wait_for_register_fw(__to_uncore(display), reg, mask, - value, timeout); + value, timeout_ms); intel_dmc_wl_put(display, reg); @@ -176,16 +176,16 @@ intel_de_wait_custom(struct intel_display *display, i915_reg_t reg, static inline int intel_de_wait_for_set(struct intel_display *display, i915_reg_t reg, - u32 mask, unsigned int timeout) + u32 mask, unsigned int timeout_ms) { - return intel_de_wait(display, reg, mask, mask, timeout); + return intel_de_wait(display, reg, mask, mask, timeout_ms); } static inline int intel_de_wait_for_clear(struct intel_display *display, i915_reg_t reg, - u32 mask, unsigned int timeout) + u32 mask, unsigned int timeout_ms) { - return intel_de_wait(display, reg, mask, 0, timeout); + return intel_de_wait(display, reg, mask, 0, timeout_ms); } /* -- GitLab From ac3bff5d63a502380370cd894d837187b1c120a0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:11 +0300 Subject: [PATCH 210/902] drm/i915: add out_value to intel_wait_for_register_fw() and intel_de_wait_fw() Future users of intel_de_wait_fw() need the final value. Just return it for everyone using intel_wait_for_register_fw() and intel_de_wait_fw() to avoid adding or using another set of specialized functions. There aren't that many users for these anyway. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/f804b2fe85ad63389e74d82e4c97220e9275f170.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_de.h | 4 ++-- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_gmbus.c | 2 +- drivers/gpu/drm/i915/display/intel_sbi.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 2 +- drivers/gpu/drm/i915/intel_uncore.c | 6 +++--- drivers/gpu/drm/i915/intel_uncore.h | 5 +++-- drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h | 5 +++-- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 823290e0cf7dd..9ecdcf6b73e4d 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -141,14 +141,14 @@ intel_de_wait(struct intel_display *display, i915_reg_t reg, static inline int intel_de_wait_fw(struct intel_display *display, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout_ms) + u32 mask, u32 value, unsigned int timeout_ms, u32 *out_value) { int ret; intel_dmc_wl_get(display, reg); ret = intel_wait_for_register_fw(__to_uncore(display), reg, mask, - value, timeout_ms); + value, timeout_ms, out_value); intel_dmc_wl_put(display, reg); diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 552dd984ade95..0282c0b2440b1 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -428,7 +428,7 @@ static void _bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy) * use 1ms due to occasional timeouts observed with that. */ if (intel_de_wait_fw(display, BXT_PORT_CL1CM_DW0(phy), - PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1)) + PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1, NULL)) drm_err(display->drm, "timeout during PHY%d power on\n", phy); diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index d55cc77650b79..88494bd4f968a 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -414,7 +414,7 @@ gmbus_wait_idle(struct intel_display *display) add_wait_queue(&display->gmbus.wait_queue, &wait); intel_de_write_fw(display, GMBUS4(display), irq_enable); - ret = intel_de_wait_fw(display, GMBUS2(display), GMBUS_ACTIVE, 0, 10); + ret = intel_de_wait_fw(display, GMBUS2(display), GMBUS_ACTIVE, 0, 10, NULL); intel_de_write_fw(display, GMBUS4(display), 0); remove_wait_queue(&display->gmbus.wait_queue, &wait); diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index 198a1ad280e28..135f190cf653d 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -23,7 +23,7 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, if (intel_wait_for_register_fw(uncore, SBI_CTL_STAT, SBI_BUSY, 0, - 100)) { + 100, NULL)) { drm_err(display->drm, "timeout waiting for SBI to become ready\n"); return -EBUSY; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index ec33ad942115a..e848a04a80dc2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -1116,7 +1116,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) _MASKED_BIT_ENABLE(dma_flags | START_DMA)); /* Wait for DMA to finish */ - ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100); + ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100, NULL); if (ret) gt_err(gt, "DMA for %s fw failed, DMA_CTRL=%u\n", intel_uc_fw_type_repr(uc_fw->type), diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 9b2254d864917..c8e29fd72290a 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2644,7 +2644,7 @@ static void driver_initiated_flr(struct intel_uncore *uncore) * is still pending (unless the HW is totally dead), but better to be * safe in case something unexpected happens */ - ret = intel_wait_for_register_fw(uncore, GU_CNTL, DRIVERFLR, 0, flr_timeout_ms); + ret = intel_wait_for_register_fw(uncore, GU_CNTL, DRIVERFLR, 0, flr_timeout_ms, NULL); if (ret) { drm_err(&i915->drm, "Failed to wait for Driver-FLR bit to clear! %d\n", @@ -2659,7 +2659,7 @@ static void driver_initiated_flr(struct intel_uncore *uncore) /* Wait for hardware teardown to complete */ ret = intel_wait_for_register_fw(uncore, GU_CNTL, DRIVERFLR, 0, - flr_timeout_ms); + flr_timeout_ms, NULL); if (ret) { drm_err(&i915->drm, "Driver-FLR-teardown wait completion failed! %d\n", ret); return; @@ -2668,7 +2668,7 @@ static void driver_initiated_flr(struct intel_uncore *uncore) /* Wait for hardware/firmware re-init to complete */ ret = intel_wait_for_register_fw(uncore, GU_DEBUG, DRIVERFLR_STATUS, DRIVERFLR_STATUS, - flr_timeout_ms); + flr_timeout_ms, NULL); if (ret) { drm_err(&i915->drm, "Driver-FLR-reinit wait completion failed! %d\n", ret); return; diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index e395829506274..6048b99b96cb9 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -313,10 +313,11 @@ intel_wait_for_register_fw(struct intel_uncore *uncore, i915_reg_t reg, u32 mask, u32 value, - unsigned int timeout_ms) + unsigned int timeout_ms, + u32 *out_value) { return __intel_wait_for_register_fw(uncore, reg, mask, value, - 2, timeout_ms, NULL); + 2, timeout_ms, out_value); } #define IS_GSI_REG(reg) ((reg) < 0x40000) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h index 0c1e88e36a1e2..797091cf1c99d 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h @@ -110,12 +110,13 @@ static inline int intel_wait_for_register(struct intel_uncore *uncore, static inline int intel_wait_for_register_fw(struct intel_uncore *uncore, i915_reg_t i915_reg, u32 mask, - u32 value, unsigned int timeout) + u32 value, unsigned int timeout, + u32 *out_value) { struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg)); return xe_mmio_wait32(__compat_uncore_to_mmio(uncore), reg, mask, value, - timeout * USEC_PER_MSEC, NULL, false); + timeout * USEC_PER_MSEC, out_value, false); } static inline int -- GitLab From ad3cfb65aceb2732ca4f87e410fa59957f6c1adf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:12 +0300 Subject: [PATCH 211/902] drm/i915/sbi: convert to intel_de_*() Convert SBI to use the intel_de_*() interface. This allows us to drop the dependency in i915_drv.h while at it. The fast timeout for the status wait drops from 100 us to 2 us on i915, but that should be of no consequence. The slow timeout remains the same. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/146f9027f565feb827861f06c1ae218b378edd95.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sbi.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index 135f190cf653d..78fd8bd9804dd 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -5,8 +5,10 @@ * LPT/WPT IOSF sideband. */ -#include "i915_drv.h" +#include + #include "i915_reg.h" +#include "intel_de.h" #include "intel_display_core.h" #include "intel_sbi.h" @@ -15,21 +17,17 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, enum intel_sbi_destination destination, u32 *val, bool is_read) { - struct drm_i915_private *i915 = to_i915(display->drm); - struct intel_uncore *uncore = &i915->uncore; u32 cmd; lockdep_assert_held(&display->sbi.lock); - if (intel_wait_for_register_fw(uncore, - SBI_CTL_STAT, SBI_BUSY, 0, - 100, NULL)) { + if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, NULL)) { drm_err(display->drm, "timeout waiting for SBI to become ready\n"); return -EBUSY; } - intel_uncore_write_fw(uncore, SBI_ADDR, (u32)reg << 16); - intel_uncore_write_fw(uncore, SBI_DATA, is_read ? 0 : *val); + intel_de_write_fw(display, SBI_ADDR, (u32)reg << 16); + intel_de_write_fw(display, SBI_DATA, is_read ? 0 : *val); if (destination == SBI_ICLK) cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; @@ -37,11 +35,9 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; if (!is_read) cmd |= BIT(8); - intel_uncore_write_fw(uncore, SBI_CTL_STAT, cmd | SBI_BUSY); + intel_de_write_fw(display, SBI_CTL_STAT, cmd | SBI_BUSY); - if (__intel_wait_for_register_fw(uncore, - SBI_CTL_STAT, SBI_BUSY, 0, - 100, 100, &cmd)) { + if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, &cmd)) { drm_err(display->drm, "timeout waiting for SBI to complete read\n"); return -ETIMEDOUT; } @@ -52,7 +48,7 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, } if (is_read) - *val = intel_uncore_read_fw(uncore, SBI_DATA); + *val = intel_de_read_fw(display, SBI_DATA); return 0; } -- GitLab From 0b6d7dbf1813447e64a09ef3a831fa71bff43669 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:13 +0300 Subject: [PATCH 212/902] drm/i915/sbi: split out intel_sbi_regs.h Split out display/intel_sbi_regs.h from i915_reg.h. Include both the SBI interface MMIO as well as the known sideband offsets. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/c96197159e05ebcb63fcc05f0f0801624cd4fdeb.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_pch_refclk.c | 1 + drivers/gpu/drm/i915/display/intel_sbi.c | 2 +- drivers/gpu/drm/i915/display/intel_sbi_regs.h | 51 +++++++++++++++++++ drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 41 --------------- drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 1 + 6 files changed, 55 insertions(+), 42 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_sbi_regs.h diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 43710ba7ebde8..4719d270e31b7 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -12,6 +12,7 @@ #include "intel_panel.h" #include "intel_pch_refclk.h" #include "intel_sbi.h" +#include "intel_sbi_regs.h" static void lpt_fdi_reset_mphy(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index 78fd8bd9804dd..bd3c3c4447e63 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -7,10 +7,10 @@ #include -#include "i915_reg.h" #include "intel_de.h" #include "intel_display_core.h" #include "intel_sbi.h" +#include "intel_sbi_regs.h" /* SBI access */ static int intel_sbi_rw(struct intel_display *display, u16 reg, diff --git a/drivers/gpu/drm/i915/display/intel_sbi_regs.h b/drivers/gpu/drm/i915/display/intel_sbi_regs.h new file mode 100644 index 0000000000000..38963f8619a3a --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_sbi_regs.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __INTEL_SBI_REGS_H__ +#define __INTEL_SBI_REGS_H__ + +#include "i915_reg_defs.h" + +/* + * Sideband Interface (SBI) is programmed indirectly, via SBI_ADDR, which + * contains the register offset; and SBI_DATA, which contains the payload. + */ +#define SBI_ADDR _MMIO(0xC6000) +#define SBI_DATA _MMIO(0xC6004) +#define SBI_CTL_STAT _MMIO(0xC6008) +#define SBI_CTL_DEST_ICLK (0x0 << 16) +#define SBI_CTL_DEST_MPHY (0x1 << 16) +#define SBI_CTL_OP_IORD (0x2 << 8) +#define SBI_CTL_OP_IOWR (0x3 << 8) +#define SBI_CTL_OP_CRRD (0x6 << 8) +#define SBI_CTL_OP_CRWR (0x7 << 8) +#define SBI_RESPONSE_FAIL (0x1 << 1) +#define SBI_RESPONSE_SUCCESS (0x0 << 1) +#define SBI_BUSY (0x1 << 0) +#define SBI_READY (0x0 << 0) + +/* SBI offsets */ +#define SBI_SSCDIVINTPHASE 0x0200 +#define SBI_SSCDIVINTPHASE6 0x0600 +#define SBI_SSCDIVINTPHASE_DIVSEL_SHIFT 1 +#define SBI_SSCDIVINTPHASE_DIVSEL_MASK (0x7f << 1) +#define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x) << 1) +#define SBI_SSCDIVINTPHASE_INCVAL_SHIFT 8 +#define SBI_SSCDIVINTPHASE_INCVAL_MASK (0x7f << 8) +#define SBI_SSCDIVINTPHASE_INCVAL(x) ((x) << 8) +#define SBI_SSCDIVINTPHASE_DIR(x) ((x) << 15) +#define SBI_SSCDIVINTPHASE_PROPAGATE (1 << 0) +#define SBI_SSCDITHPHASE 0x0204 +#define SBI_SSCCTL 0x020c +#define SBI_SSCCTL6 0x060C +#define SBI_SSCCTL_PATHALT (1 << 3) +#define SBI_SSCCTL_DISABLE (1 << 0) +#define SBI_SSCAUXDIV6 0x0610 +#define SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT 4 +#define SBI_SSCAUXDIV_FINALDIV2SEL_MASK (1 << 4) +#define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x) << 4) +#define SBI_DBUFF0 0x2a00 +#define SBI_GEN0 0x1f00 +#define SBI_GEN0_CFG_BUFFENABLE_DISABLE (1 << 0) + +#endif /* __INTEL_SBI_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 9b001776a9608..d7322f27dab90 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -56,6 +56,7 @@ #include "display/intel_fdi_regs.h" #include "display/intel_pps_regs.h" #include "display/intel_psr_regs.h" +#include "display/intel_sbi_regs.h" #include "display/intel_sprite_regs.h" #include "display/intel_vga_regs.h" #include "display/skl_universal_plane_regs.h" diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8822c639a4f4b..85fdcc53f3683 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3590,47 +3590,6 @@ enum skl_power_gate { #define _DDI_DP_COMP_PAT_B 0x615F4 #define DDI_DP_COMP_PAT(pipe, i) _MMIO(_PIPE(pipe, _DDI_DP_COMP_PAT_A, _DDI_DP_COMP_PAT_B) + (i) * 4) -/* Sideband Interface (SBI) is programmed indirectly, via - * SBI_ADDR, which contains the register offset; and SBI_DATA, - * which contains the payload */ -#define SBI_ADDR _MMIO(0xC6000) -#define SBI_DATA _MMIO(0xC6004) -#define SBI_CTL_STAT _MMIO(0xC6008) -#define SBI_CTL_DEST_ICLK (0x0 << 16) -#define SBI_CTL_DEST_MPHY (0x1 << 16) -#define SBI_CTL_OP_IORD (0x2 << 8) -#define SBI_CTL_OP_IOWR (0x3 << 8) -#define SBI_CTL_OP_CRRD (0x6 << 8) -#define SBI_CTL_OP_CRWR (0x7 << 8) -#define SBI_RESPONSE_FAIL (0x1 << 1) -#define SBI_RESPONSE_SUCCESS (0x0 << 1) -#define SBI_BUSY (0x1 << 0) -#define SBI_READY (0x0 << 0) - -/* SBI offsets */ -#define SBI_SSCDIVINTPHASE 0x0200 -#define SBI_SSCDIVINTPHASE6 0x0600 -#define SBI_SSCDIVINTPHASE_DIVSEL_SHIFT 1 -#define SBI_SSCDIVINTPHASE_DIVSEL_MASK (0x7f << 1) -#define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x) << 1) -#define SBI_SSCDIVINTPHASE_INCVAL_SHIFT 8 -#define SBI_SSCDIVINTPHASE_INCVAL_MASK (0x7f << 8) -#define SBI_SSCDIVINTPHASE_INCVAL(x) ((x) << 8) -#define SBI_SSCDIVINTPHASE_DIR(x) ((x) << 15) -#define SBI_SSCDIVINTPHASE_PROPAGATE (1 << 0) -#define SBI_SSCDITHPHASE 0x0204 -#define SBI_SSCCTL 0x020c -#define SBI_SSCCTL6 0x060C -#define SBI_SSCCTL_PATHALT (1 << 3) -#define SBI_SSCCTL_DISABLE (1 << 0) -#define SBI_SSCAUXDIV6 0x0610 -#define SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT 4 -#define SBI_SSCAUXDIV_FINALDIV2SEL_MASK (1 << 4) -#define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x) << 4) -#define SBI_DBUFF0 0x2a00 -#define SBI_GEN0 0x1f00 -#define SBI_GEN0_CFG_BUFFENABLE_DISABLE (1 << 0) - /* LPT PIXCLK_GATE */ #define PIXCLK_GATE _MMIO(0xC6020) #define PIXCLK_GATE_UNGATE (1 << 0) diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index e83dc30e658d6..f5a98c3cafee3 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -21,6 +21,7 @@ #include "display/intel_lvds_regs.h" #include "display/intel_pfit_regs.h" #include "display/intel_psr_regs.h" +#include "display/intel_sbi_regs.h" #include "display/intel_sprite_regs.h" #include "display/intel_vga_regs.h" #include "display/skl_universal_plane_regs.h" -- GitLab From e583c27a8f595b23b0ec3eda22c522590f809ff2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 13:59:14 +0300 Subject: [PATCH 213/902] drm/i915/sbi: clean up SBI register macro definitions and usage Use REG_BIT() and friends for defining the register macros. Switch GVT to use the same macros, and drop its own copies. Reviewed-by: Luca Coelho Link: https://lore.kernel.org/r/e148e8621c6055d0441fdf6d651d4ad24be53d09.1748343520.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sbi.c | 10 ++-- drivers/gpu/drm/i915/display/intel_sbi_regs.h | 50 ++++++++++++------- drivers/gpu/drm/i915/gvt/display.h | 13 ----- drivers/gpu/drm/i915/gvt/handlers.c | 29 ++++++----- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sbi.c b/drivers/gpu/drm/i915/display/intel_sbi.c index bd3c3c4447e63..dfcff924f0ed5 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi.c +++ b/drivers/gpu/drm/i915/display/intel_sbi.c @@ -21,12 +21,12 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, lockdep_assert_held(&display->sbi.lock); - if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, NULL)) { + if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_STATUS_MASK, SBI_STATUS_READY, 100, NULL)) { drm_err(display->drm, "timeout waiting for SBI to become ready\n"); return -EBUSY; } - intel_de_write_fw(display, SBI_ADDR, (u32)reg << 16); + intel_de_write_fw(display, SBI_ADDR, SBI_ADDR_VALUE(reg)); intel_de_write_fw(display, SBI_DATA, is_read ? 0 : *val); if (destination == SBI_ICLK) @@ -34,10 +34,10 @@ static int intel_sbi_rw(struct intel_display *display, u16 reg, else cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; if (!is_read) - cmd |= BIT(8); - intel_de_write_fw(display, SBI_CTL_STAT, cmd | SBI_BUSY); + cmd |= SBI_CTL_OP_WR; + intel_de_write_fw(display, SBI_CTL_STAT, cmd | SBI_STATUS_BUSY); - if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, &cmd)) { + if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_STATUS_MASK, SBI_STATUS_READY, 100, &cmd)) { drm_err(display->drm, "timeout waiting for SBI to complete read\n"); return -ETIMEDOUT; } diff --git a/drivers/gpu/drm/i915/display/intel_sbi_regs.h b/drivers/gpu/drm/i915/display/intel_sbi_regs.h index 38963f8619a3a..6fd37574b8055 100644 --- a/drivers/gpu/drm/i915/display/intel_sbi_regs.h +++ b/drivers/gpu/drm/i915/display/intel_sbi_regs.h @@ -11,22 +11,32 @@ * contains the register offset; and SBI_DATA, which contains the payload. */ #define SBI_ADDR _MMIO(0xC6000) +#define SBI_ADDR_MASK REG_GENMASK(31, 16) +#define SBI_ADDR_VALUE(addr) REG_FIELD_PREP(SBI_ADDR_MASK, (addr)) + #define SBI_DATA _MMIO(0xC6004) + #define SBI_CTL_STAT _MMIO(0xC6008) -#define SBI_CTL_DEST_ICLK (0x0 << 16) -#define SBI_CTL_DEST_MPHY (0x1 << 16) -#define SBI_CTL_OP_IORD (0x2 << 8) -#define SBI_CTL_OP_IOWR (0x3 << 8) -#define SBI_CTL_OP_CRRD (0x6 << 8) -#define SBI_CTL_OP_CRWR (0x7 << 8) -#define SBI_RESPONSE_FAIL (0x1 << 1) -#define SBI_RESPONSE_SUCCESS (0x0 << 1) -#define SBI_BUSY (0x1 << 0) -#define SBI_READY (0x0 << 0) +#define SBI_CTL_DEST_MASK REG_GENMASK(16, 16) +#define SBI_CTL_DEST_ICLK REG_FIELD_PREP(SBI_CTL_DEST_MASK, 0) +#define SBI_CTL_DEST_MPHY REG_FIELD_PREP(SBI_CTL_DEST_MASK, 1) +#define SBI_CTL_OP_MASK REG_GENMASK(15, 8) +#define SBI_CTL_OP_IORD REG_FIELD_PREP(SBI_CTL_OP_MASK, 2) +#define SBI_CTL_OP_IOWR REG_FIELD_PREP(SBI_CTL_OP_MASK, 3) +#define SBI_CTL_OP_CRRD REG_FIELD_PREP(SBI_CTL_OP_MASK, 6) +#define SBI_CTL_OP_CRWR REG_FIELD_PREP(SBI_CTL_OP_MASK, 7) +#define SBI_CTL_OP_WR REG_BIT(8) +#define SBI_RESPONSE_MASK REG_GENMASK(2, 1) +#define SBI_RESPONSE_FAIL REG_FIELD_PREP(SBI_RESPONSE_MASK, 1) +#define SBI_RESPONSE_SUCCESS REG_FIELD_PREP(SBI_RESPONSE_MASK, 0) +#define SBI_STATUS_MASK REG_GENMASK(0, 0) +#define SBI_STATUS_BUSY REG_FIELD_PREP(SBI_STATUS_MASK, 1) +#define SBI_STATUS_READY REG_FIELD_PREP(SBI_STATUS_MASK, 0) /* SBI offsets */ -#define SBI_SSCDIVINTPHASE 0x0200 -#define SBI_SSCDIVINTPHASE6 0x0600 +#define SBI_SSCDIVINTPHASE 0x0200 + +#define SBI_SSCDIVINTPHASE6 0x0600 #define SBI_SSCDIVINTPHASE_DIVSEL_SHIFT 1 #define SBI_SSCDIVINTPHASE_DIVSEL_MASK (0x7f << 1) #define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x) << 1) @@ -35,17 +45,21 @@ #define SBI_SSCDIVINTPHASE_INCVAL(x) ((x) << 8) #define SBI_SSCDIVINTPHASE_DIR(x) ((x) << 15) #define SBI_SSCDIVINTPHASE_PROPAGATE (1 << 0) -#define SBI_SSCDITHPHASE 0x0204 -#define SBI_SSCCTL 0x020c -#define SBI_SSCCTL6 0x060C + +#define SBI_SSCDITHPHASE 0x0204 +#define SBI_SSCCTL 0x020c +#define SBI_SSCCTL6 0x060C #define SBI_SSCCTL_PATHALT (1 << 3) #define SBI_SSCCTL_DISABLE (1 << 0) -#define SBI_SSCAUXDIV6 0x0610 + +#define SBI_SSCAUXDIV6 0x0610 #define SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT 4 #define SBI_SSCAUXDIV_FINALDIV2SEL_MASK (1 << 4) #define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x) << 4) -#define SBI_DBUFF0 0x2a00 -#define SBI_GEN0 0x1f00 + +#define SBI_DBUFF0 0x2a00 + +#define SBI_GEN0 0x1f00 #define SBI_GEN0_CFG_BUFFENABLE_DISABLE (1 << 0) #endif /* __INTEL_SBI_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h index 8090bc53c7e16..bc7f05f9a2711 100644 --- a/drivers/gpu/drm/i915/gvt/display.h +++ b/drivers/gpu/drm/i915/gvt/display.h @@ -63,19 +63,6 @@ struct intel_vgpu; #define AUX_BURST_SIZE 20 -#define SBI_RESPONSE_MASK 0x3 -#define SBI_RESPONSE_SHIFT 0x1 -#define SBI_STAT_MASK 0x1 -#define SBI_STAT_SHIFT 0x0 -#define SBI_OPCODE_SHIFT 8 -#define SBI_OPCODE_MASK (0xff << SBI_OPCODE_SHIFT) -#define SBI_CMD_IORD 2 -#define SBI_CMD_IOWR 3 -#define SBI_CMD_CRRD 6 -#define SBI_CMD_CRWR 7 -#define SBI_ADDR_OFFSET_SHIFT 16 -#define SBI_ADDR_OFFSET_MASK (0xffff << SBI_ADDR_OFFSET_SHIFT) - struct intel_vgpu_sbi_register { unsigned int offset; u32 value; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index d7322f27dab90..1d2d6f851d98f 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1414,12 +1414,12 @@ static void write_virtual_sbi_register(struct intel_vgpu *vgpu, static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { - if (((vgpu_vreg_t(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> - SBI_OPCODE_SHIFT) == SBI_CMD_CRRD) { - unsigned int sbi_offset = (vgpu_vreg_t(vgpu, SBI_ADDR) & - SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; - vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu, - sbi_offset); + if ((vgpu_vreg_t(vgpu, SBI_CTL_STAT) & SBI_CTL_OP_MASK) == SBI_CTL_OP_CRRD) { + unsigned int sbi_offset; + + sbi_offset = REG_FIELD_GET(SBI_ADDR_MASK, vgpu_vreg_t(vgpu, SBI_ADDR)); + + vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu, sbi_offset); } read_vreg(vgpu, offset, p_data, bytes); return 0; @@ -1433,21 +1433,20 @@ static int sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, write_vreg(vgpu, offset, p_data, bytes); data = vgpu_vreg(vgpu, offset); - data &= ~(SBI_STAT_MASK << SBI_STAT_SHIFT); - data |= SBI_READY; + data &= ~SBI_STATUS_MASK; + data |= SBI_STATUS_READY; - data &= ~(SBI_RESPONSE_MASK << SBI_RESPONSE_SHIFT); + data &= ~SBI_RESPONSE_MASK; data |= SBI_RESPONSE_SUCCESS; vgpu_vreg(vgpu, offset) = data; - if (((vgpu_vreg_t(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> - SBI_OPCODE_SHIFT) == SBI_CMD_CRWR) { - unsigned int sbi_offset = (vgpu_vreg_t(vgpu, SBI_ADDR) & - SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; + if ((vgpu_vreg_t(vgpu, SBI_CTL_STAT) & SBI_CTL_OP_MASK) == SBI_CTL_OP_CRWR) { + unsigned int sbi_offset; + + sbi_offset = REG_FIELD_GET(SBI_ADDR_MASK, vgpu_vreg_t(vgpu, SBI_ADDR)); - write_virtual_sbi_register(vgpu, sbi_offset, - vgpu_vreg_t(vgpu, SBI_DATA)); + write_virtual_sbi_register(vgpu, sbi_offset, vgpu_vreg_t(vgpu, SBI_DATA)); } return 0; } -- GitLab From 99e80508980583b1c0150b953b64a629211c4e23 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 2 Jun 2025 09:44:12 -0700 Subject: [PATCH 214/902] drm/xe: Make VMA tile_present, tile_invalidated access rules clear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document VMA tile_invalidated access rules, use READ_ONCE / WRITE_ONCE for opportunistic checks of tile_present and tile_invalidated, move tile_invalidated state change from page fault handler to PT code under the correct locks, and add lockdep asserts to TLB invalidation paths. v2: - Assert VM dma-resv lock rather than BO in zap PTEs v3: - Back to BO's dma-resv lock, adjust documentation v4: - Add WRITE_ONCE in xe_vm_invalidate_vma (Thomas) - Change lockdep assert for userptr in xe_vm_invalidate_vma (CI) - Take userptr notifier lock in read mode in xe_vm_userptr_pin before calling xe_vm_invalidate_vma (CI) v5: - Fix typos (Thomas) Signed-off-by: Matthew Brost Reviewed-by: Thomas Hellström Link: https://lore.kernel.org/r/20250602164412.1912293-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 11 +++++++---- drivers/gpu/drm/xe/xe_pt.c | 16 +++++++++++++--- drivers/gpu/drm/xe/xe_vm.c | 19 +++++++++++++++---- drivers/gpu/drm/xe/xe_vm_types.h | 11 +++++++++-- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index e0e68eda82bd8..e2d975b2fddbd 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -69,8 +69,12 @@ static bool access_is_atomic(enum access_type access_type) static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma) { - return BIT(tile->id) & vma->tile_present && - !(BIT(tile->id) & vma->tile_invalidated); + /* + * Advisory only check whether the VMA currently has a valid mapping, + * READ_ONCE pairs with WRITE_ONCE in xe_pt.c + */ + return BIT(tile->id) & READ_ONCE(vma->tile_present) && + !(BIT(tile->id) & READ_ONCE(vma->tile_invalidated)); } @@ -122,7 +126,7 @@ static int handle_vma_pagefault(struct xe_gt *gt, struct xe_vma *vma, trace_xe_vma_pagefault(vma); - /* Check if VMA is valid */ + /* Check if VMA is valid, opportunistic check only */ if (vma_is_valid(tile, vma) && !atomic) return 0; @@ -159,7 +163,6 @@ retry_userptr: dma_fence_wait(fence, false); dma_fence_put(fence); - vma->tile_invalidated &= ~BIT(tile->id); unlock_dma_resv: drm_exec_fini(&exec); diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index c9c41fbe125c6..f39d5cc9f411e 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -907,6 +907,11 @@ bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma) struct xe_pt *pt = xe_vma_vm(vma)->pt_root[tile->id]; u8 pt_mask = (vma->tile_present & ~vma->tile_invalidated); + if (xe_vma_bo(vma)) + xe_bo_assert_held(xe_vma_bo(vma)); + else if (xe_vma_is_userptr(vma)) + lockdep_assert_held(&xe_vma_vm(vma)->userptr.notifier_lock); + if (!(pt_mask & BIT(tile->id))) return false; @@ -2191,10 +2196,15 @@ static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile, DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_BOOKKEEP); } - vma->tile_present |= BIT(tile->id); - vma->tile_staged &= ~BIT(tile->id); + /* All WRITE_ONCE pair with READ_ONCE in xe_gt_pagefault.c */ + WRITE_ONCE(vma->tile_present, vma->tile_present | BIT(tile->id)); if (invalidate_on_bind) - vma->tile_invalidated |= BIT(tile->id); + WRITE_ONCE(vma->tile_invalidated, + vma->tile_invalidated | BIT(tile->id)); + else + WRITE_ONCE(vma->tile_invalidated, + vma->tile_invalidated & ~BIT(tile->id)); + vma->tile_staged &= ~BIT(tile->id); if (xe_vma_is_userptr(vma)) { lockdep_assert_held_read(&vm->userptr.notifier_lock); to_userptr_vma(vma)->userptr.initial_bind = true; diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 7140d8856bad0..18f967ce1f1a6 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -732,7 +732,9 @@ int xe_vm_userptr_pin(struct xe_vm *vm) DMA_RESV_USAGE_BOOKKEEP, false, MAX_SCHEDULE_TIMEOUT); + down_read(&vm->userptr.notifier_lock); err = xe_vm_invalidate_vma(&uvma->vma); + up_read(&vm->userptr.notifier_lock); xe_vm_unlock(vm); if (err) break; @@ -3853,6 +3855,7 @@ void xe_vm_unlock(struct xe_vm *vm) int xe_vm_invalidate_vma(struct xe_vma *vma) { struct xe_device *xe = xe_vma_vm(vma)->xe; + struct xe_vm *vm = xe_vma_vm(vma); struct xe_tile *tile; struct xe_gt_tlb_invalidation_fence fence[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE]; @@ -3864,17 +3867,24 @@ int xe_vm_invalidate_vma(struct xe_vma *vma) xe_assert(xe, !xe_vma_is_cpu_addr_mirror(vma)); trace_xe_vma_invalidate(vma); - vm_dbg(&xe_vma_vm(vma)->xe->drm, + vm_dbg(&vm->xe->drm, "INVALIDATE: addr=0x%016llx, range=0x%016llx", xe_vma_start(vma), xe_vma_size(vma)); - /* Check that we don't race with page-table updates */ + /* + * Check that we don't race with page-table updates, tile_invalidated + * update is safe + */ if (IS_ENABLED(CONFIG_PROVE_LOCKING)) { if (xe_vma_is_userptr(vma)) { + lockdep_assert(lockdep_is_held_type(&vm->userptr.notifier_lock, 0) || + (lockdep_is_held_type(&vm->userptr.notifier_lock, 1) && + lockdep_is_held(&xe_vm_resv(vm)->lock.base))); + WARN_ON_ONCE(!mmu_interval_check_retry (&to_userptr_vma(vma)->userptr.notifier, to_userptr_vma(vma)->userptr.notifier_seq)); - WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)), + WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(vm), DMA_RESV_USAGE_BOOKKEEP)); } else { @@ -3914,7 +3924,8 @@ wait: for (id = 0; id < fence_id; ++id) xe_gt_tlb_invalidation_fence_wait(&fence[id]); - vma->tile_invalidated = vma->tile_mask; + /* WRITE_ONCE pair with READ_ONCE in xe_gt_pagefault.c */ + WRITE_ONCE(vma->tile_invalidated, vma->tile_mask); return ret; } diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 0e1318a15c9e8..bed6088e1bb3a 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -100,14 +100,21 @@ struct xe_vma { struct work_struct destroy_work; }; - /** @tile_invalidated: VMA has been invalidated */ + /** + * @tile_invalidated: Tile mask of binding are invalidated for this VMA. + * protected by BO's resv and for userptrs, vm->userptr.notifier_lock in + * write mode for writing or vm->userptr.notifier_lock in read mode and + * the vm->resv. For stable reading, BO's resv or userptr + * vm->userptr.notifier_lock in read mode is required. Can be + * opportunistically read with READ_ONCE outside of locks. + */ u8 tile_invalidated; /** @tile_mask: Tile mask of where to create binding for this VMA */ u8 tile_mask; /** - * @tile_present: GT mask of binding are present for this VMA. + * @tile_present: Tile mask of binding are present for this VMA. * protected by vm->lock, vm->resv and for userptrs, * vm->userptr.notifier_lock for writing. Needs either for reading, * but if reading is done under the vm->lock only, it needs to be held -- GitLab From 9ab671afacc14449500d9da1633a8389a2a18b83 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:21 +0300 Subject: [PATCH 215/902] drm/i915/bw: pass struct dram_info pointer around Have just one place to figure out the pointer to struct dram_info, and pass that around. This simplifies future changes. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/1752b4987ff39a685c28cebae1be4ce326b67c7b.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bw.c | 44 ++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index a5dd2932b852d..6c537635b120c 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -218,11 +218,10 @@ intel_read_qgv_point_info(struct intel_display *display, } static int icl_get_qgv_points(struct intel_display *display, + const struct dram_info *dram_info, struct intel_qgv_info *qi, bool is_y_tile) { - struct drm_i915_private *i915 = to_i915(display->drm); - const struct dram_info *dram_info = &i915->dram_info; int i, ret; qi->num_points = dram_info->num_qgv_points; @@ -418,19 +417,20 @@ static const struct intel_sa_info xe3lpd_sa_info = { .derating = 10, }; -static int icl_get_bw_info(struct intel_display *display, const struct intel_sa_info *sa) +static int icl_get_bw_info(struct intel_display *display, + const struct dram_info *dram_info, + const struct intel_sa_info *sa) { - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_qgv_info qi = {}; bool is_y_tile = true; /* assume y tile may be used */ - int num_channels = max_t(u8, 1, i915->dram_info.num_channels); + int num_channels = max_t(u8, 1, dram_info->num_channels); int ipqdepth, ipqdepthpch = 16; int dclk_max; int maxdebw; int num_groups = ARRAY_SIZE(display->bw.max); int i, ret; - ret = icl_get_qgv_points(display, &qi, is_y_tile); + ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); @@ -488,11 +488,11 @@ static int icl_get_bw_info(struct intel_display *display, const struct intel_sa_ return 0; } -static int tgl_get_bw_info(struct intel_display *display, const struct intel_sa_info *sa) +static int tgl_get_bw_info(struct intel_display *display, + const struct dram_info *dram_info, + const struct intel_sa_info *sa) { - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_qgv_info qi = {}; - const struct dram_info *dram_info = &i915->dram_info; bool is_y_tile = true; /* assume y tile may be used */ int num_channels = max_t(u8, 1, dram_info->num_channels); int ipqdepth, ipqdepthpch = 16; @@ -502,7 +502,7 @@ static int tgl_get_bw_info(struct intel_display *display, const struct intel_sa_ int num_groups = ARRAY_SIZE(display->bw.max); int i, ret; - ret = icl_get_qgv_points(display, &qi, is_y_tile); + ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); @@ -632,15 +632,15 @@ static void dg2_get_bw_info(struct intel_display *display) } static int xe2_hpd_get_bw_info(struct intel_display *display, + const struct dram_info *dram_info, const struct intel_sa_info *sa) { - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_qgv_info qi = {}; - int num_channels = i915->dram_info.num_channels; + int num_channels = dram_info->num_channels; int peakbw, maxdebw; int ret, i; - ret = icl_get_qgv_points(display, &qi, true); + ret = icl_get_qgv_points(display, dram_info, &qi, true); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); @@ -769,26 +769,26 @@ void intel_bw_init_hw(struct intel_display *display) return; if (DISPLAY_VER(display) >= 30) - tgl_get_bw_info(display, &xe3lpd_sa_info); + tgl_get_bw_info(display, dram_info, &xe3lpd_sa_info); else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx && dram_info->type == INTEL_DRAM_GDDR_ECC) - xe2_hpd_get_bw_info(display, &xe2_hpd_ecc_sa_info); + xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_ecc_sa_info); else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx) - xe2_hpd_get_bw_info(display, &xe2_hpd_sa_info); + xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_sa_info); else if (DISPLAY_VER(display) >= 14) - tgl_get_bw_info(display, &mtl_sa_info); + tgl_get_bw_info(display, dram_info, &mtl_sa_info); else if (display->platform.dg2) dg2_get_bw_info(display); else if (display->platform.alderlake_p) - tgl_get_bw_info(display, &adlp_sa_info); + tgl_get_bw_info(display, dram_info, &adlp_sa_info); else if (display->platform.alderlake_s) - tgl_get_bw_info(display, &adls_sa_info); + tgl_get_bw_info(display, dram_info, &adls_sa_info); else if (display->platform.rocketlake) - tgl_get_bw_info(display, &rkl_sa_info); + tgl_get_bw_info(display, dram_info, &rkl_sa_info); else if (DISPLAY_VER(display) == 12) - tgl_get_bw_info(display, &tgl_sa_info); + tgl_get_bw_info(display, dram_info, &tgl_sa_info); else if (DISPLAY_VER(display) == 11) - icl_get_bw_info(display, &icl_sa_info); + icl_get_bw_info(display, dram_info, &icl_sa_info); } static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state) -- GitLab From 612abe44f70f17dfad6830acd987f9696689869b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:22 +0300 Subject: [PATCH 216/902] drm/i915/dram: add accessor for struct dram_info and use it Add a function to get the (const) pointer to struct dram_info, and use that to obtain the pointer instead of poking at i915->dram_info directly. Clean up a couple of local variables while at it. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/4174edf649e2f6805dab6fd6ce2ec10f4e5f2498.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bw.c | 5 +++-- .../gpu/drm/i915/display/intel_display_power.c | 9 ++++----- drivers/gpu/drm/i915/display/skl_watermark.c | 15 ++++++++------- drivers/gpu/drm/i915/soc/intel_dram.c | 7 +++++++ drivers/gpu/drm/i915/soc/intel_dram.h | 3 +++ 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 6c537635b120c..97aef729f7d4c 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -5,6 +5,7 @@ #include +#include "soc/intel_dram.h" #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" @@ -13,9 +14,9 @@ #include "intel_cdclk.h" #include "intel_display_core.h" #include "intel_display_types.h" -#include "skl_watermark.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" +#include "skl_watermark.h" /* Parameters for Qclk Geyserville (QGV) */ struct intel_qgv_point { @@ -763,7 +764,7 @@ static unsigned int icl_qgv_bw(struct intel_display *display, void intel_bw_init_hw(struct intel_display *display) { - const struct dram_info *dram_info = &to_i915(display->drm)->dram_info; + const struct dram_info *dram_info = intel_dram_info(display->drm); if (!HAS_DISPLAY(display)) return; diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index d7f5d3dbb8a10..8e8c3a2f401bb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5,6 +5,7 @@ #include +#include "soc/intel_dram.h" #include "i915_drv.h" #include "i915_irq.h" #include "i915_reg.h" @@ -1604,9 +1605,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = { static void tgl_bw_buddy_init(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - enum intel_dram_type type = dev_priv->dram_info.type; - u8 num_channels = dev_priv->dram_info.num_channels; + const struct dram_info *dram_info = intel_dram_info(display->drm); const struct buddy_page_mask *table; unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask; int config, i; @@ -1623,8 +1622,8 @@ static void tgl_bw_buddy_init(struct intel_display *display) table = tgl_buddy_page_masks; for (config = 0; table[config].page_mask != 0; config++) - if (table[config].num_channels == num_channels && - table[config].type == type) + if (table[config].num_channels == dram_info->num_channels && + table[config].type == dram_info->type) break; if (table[config].page_mask == 0) { diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 8080f777910a7..f5600f4b77721 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -7,6 +7,7 @@ #include +#include "soc/intel_dram.h" #include "i915_drv.h" #include "i915_reg.h" #include "i9xx_wm.h" @@ -3184,8 +3185,6 @@ void skl_watermark_ipc_update(struct intel_display *display) static bool skl_watermark_ipc_can_enable(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - /* Display WA #0477 WaDisableIPC: skl */ if (display->platform.skylake) return false; @@ -3193,8 +3192,11 @@ static bool skl_watermark_ipc_can_enable(struct intel_display *display) /* Display WA #1141: SKL:all KBL:all CFL */ if (display->platform.kabylake || display->platform.coffeelake || - display->platform.cometlake) - return i915->dram_info.symmetric_memory; + display->platform.cometlake) { + const struct dram_info *dram_info = intel_dram_info(display->drm); + + return dram_info->symmetric_memory; + } return true; } @@ -3213,8 +3215,7 @@ static void adjust_wm_latency(struct intel_display *display, u16 wm[], int num_levels, int read_latency) { - struct drm_i915_private *i915 = to_i915(display->drm); - bool wm_lv_0_adjust_needed = i915->dram_info.wm_lv_0_adjust_needed; + const struct dram_info *dram_info = intel_dram_info(display->drm); int i, level; /* @@ -3250,7 +3251,7 @@ adjust_wm_latency(struct intel_display *display, * any underrun. If not able to get Dimm info assume 16GB dimm * to avoid any underrun. */ - if (wm_lv_0_adjust_needed) + if (dram_info->wm_lv_0_adjust_needed) wm[0] += 1; } diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 9f806ce0eb9ef..76c225fd6c705 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -750,6 +750,13 @@ void intel_dram_detect(struct drm_i915_private *i915) str_yes_no(dram_info->wm_lv_0_adjust_needed)); } +const struct dram_info *intel_dram_info(struct drm_device *drm) +{ + struct drm_i915_private *i915 = to_i915(drm); + + return &i915->dram_info; +} + static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) { static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index a10136eda6741..17a20cd2c6d5a 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -7,9 +7,12 @@ #define __INTEL_DRAM_H__ struct drm_i915_private; +struct drm_device; +struct dram_info; void intel_dram_edram_detect(struct drm_i915_private *i915); void intel_dram_detect(struct drm_i915_private *i915); unsigned int i9xx_fsb_freq(struct drm_i915_private *i915); +const struct dram_info *intel_dram_info(struct drm_device *drm); #endif /* __INTEL_DRAM_H__ */ -- GitLab From ca37e99ec96dd344c3c2e8b06a33fbcd2b47f4bb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:23 +0300 Subject: [PATCH 217/902] drm/i915/wm: DG2 doesn't have dram info to look up wm_lv_0_adjust_needed There's no dram info on DG2 that we could use. The struct dram_info is all zero on it, but be explicit about this. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/a866641bff364dcfcaaabaa1d53c4a8cfa94ff3f.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index f5600f4b77721..817939f6d4ddf 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3251,7 +3251,7 @@ adjust_wm_latency(struct intel_display *display, * any underrun. If not able to get Dimm info assume 16GB dimm * to avoid any underrun. */ - if (dram_info->wm_lv_0_adjust_needed) + if (!display->platform.dg2 && dram_info->wm_lv_0_adjust_needed) wm[0] += 1; } -- GitLab From bd0cffe9ebcb6874ab56eced77e604057a70850d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:24 +0300 Subject: [PATCH 218/902] drm/i915/dram: pass struct dram_info pointer around Figure out the struct dram_info pointer in one place, and pass that around to be filled in, instead of all places poking at i915->dram_info directly. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/8ac6b308b210cf4a429d5abfb9bf32737dcab51f.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/soc/intel_dram.c | 40 ++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 76c225fd6c705..f42dcdb74d40c 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -383,9 +383,8 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0, } static int -skl_dram_get_channels_info(struct drm_i915_private *i915) +skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info) { - struct dram_info *dram_info = &i915->dram_info; struct dram_channel_info ch0 = {}, ch1 = {}; u32 val; int ret; @@ -446,14 +445,13 @@ skl_get_dram_type(struct drm_i915_private *i915) } static int -skl_get_dram_info(struct drm_i915_private *i915) +skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) { - struct dram_info *dram_info = &i915->dram_info; int ret; dram_info->type = skl_get_dram_type(i915); - ret = skl_dram_get_channels_info(i915); + ret = skl_dram_get_channels_info(i915, dram_info); if (ret) return ret; @@ -538,9 +536,8 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); } -static int bxt_get_dram_info(struct drm_i915_private *i915) +static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) { - struct dram_info *dram_info = &i915->dram_info; u32 val; u8 valid_ranks = 0; int i; @@ -585,9 +582,9 @@ static int bxt_get_dram_info(struct drm_i915_private *i915) return 0; } -static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv) +static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, + struct dram_info *dram_info) { - struct dram_info *dram_info = &dev_priv->dram_info; u32 val = 0; int ret; @@ -647,27 +644,26 @@ static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv) return 0; } -static int gen11_get_dram_info(struct drm_i915_private *i915) +static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) { - int ret = skl_get_dram_info(i915); + int ret = skl_get_dram_info(i915, dram_info); if (ret) return ret; - return icl_pcode_read_mem_global_info(i915); + return icl_pcode_read_mem_global_info(i915, dram_info); } -static int gen12_get_dram_info(struct drm_i915_private *i915) +static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) { - i915->dram_info.wm_lv_0_adjust_needed = false; + dram_info->wm_lv_0_adjust_needed = false; - return icl_pcode_read_mem_global_info(i915); + return icl_pcode_read_mem_global_info(i915, dram_info); } -static int xelpdp_get_dram_info(struct drm_i915_private *i915) +static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) { u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); - struct dram_info *dram_info = &i915->dram_info; switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { case 0: @@ -726,15 +722,15 @@ void intel_dram_detect(struct drm_i915_private *i915) dram_info->wm_lv_0_adjust_needed = !IS_BROXTON(i915) && !IS_GEMINILAKE(i915); if (DISPLAY_VER(i915) >= 14) - ret = xelpdp_get_dram_info(i915); + ret = xelpdp_get_dram_info(i915, dram_info); else if (GRAPHICS_VER(i915) >= 12) - ret = gen12_get_dram_info(i915); + ret = gen12_get_dram_info(i915, dram_info); else if (GRAPHICS_VER(i915) >= 11) - ret = gen11_get_dram_info(i915); + ret = gen11_get_dram_info(i915, dram_info); else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915)) - ret = bxt_get_dram_info(i915); + ret = bxt_get_dram_info(i915, dram_info); else - ret = skl_get_dram_info(i915); + ret = skl_get_dram_info(i915, dram_info); drm_dbg_kms(&i915->drm, "DRAM type: %s\n", intel_dram_type_str(dram_info->type)); -- GitLab From 836864ac60c53be427caad83ae78ef56aab8b815 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:25 +0300 Subject: [PATCH 219/902] drm/i915/dram: add return value and handling to intel_dram_detect() We'll want to start returning errors from intel_dram_detect(). As the first step, add the return value and error handling, even if we still only return 0. Do no functional changes, but leave a comment about whether we should bail out on dram detection failures. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/be2c31c459fb95d8161b719d499403eea5ec17b7.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_driver.c | 4 +++- drivers/gpu/drm/i915/soc/intel_dram.c | 9 ++++++--- drivers/gpu/drm/i915/soc/intel_dram.h | 2 +- drivers/gpu/drm/xe/display/xe_display.c | 4 +++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 510eb3ed4b0ec..c6263c6d33845 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -568,7 +568,9 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - intel_dram_detect(dev_priv); + ret = intel_dram_detect(dev_priv); + if (ret) + goto err_opregion; intel_bw_init_hw(display); diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index f42dcdb74d40c..e7fa938c98cfe 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -704,7 +704,7 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info return 0; } -void intel_dram_detect(struct drm_i915_private *i915) +int intel_dram_detect(struct drm_i915_private *i915) { struct dram_info *dram_info = &i915->dram_info; int ret; @@ -713,7 +713,7 @@ void intel_dram_detect(struct drm_i915_private *i915) detect_mem_freq(i915); if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) - return; + return 0; /* * Assume level 0 watermark latency adjustment is needed until proven @@ -735,8 +735,9 @@ void intel_dram_detect(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "DRAM type: %s\n", intel_dram_type_str(dram_info->type)); + /* TODO: Do we want to abort probe on dram detection failures? */ if (ret) - return; + return 0; drm_dbg_kms(&i915->drm, "Num qgv points %u\n", dram_info->num_qgv_points); @@ -744,6 +745,8 @@ void intel_dram_detect(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n", str_yes_no(dram_info->wm_lv_0_adjust_needed)); + + return 0; } const struct dram_info *intel_dram_info(struct drm_device *drm) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 17a20cd2c6d5a..25fe60b2b1178 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -11,7 +11,7 @@ struct drm_device; struct dram_info; void intel_dram_edram_detect(struct drm_i915_private *i915); -void intel_dram_detect(struct drm_i915_private *i915); +int intel_dram_detect(struct drm_i915_private *i915); unsigned int i9xx_fsb_freq(struct drm_i915_private *i915); const struct dram_info *intel_dram_info(struct drm_device *drm); diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 3f92bf51813e5..eafe2f093a6cf 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -122,7 +122,9 @@ int xe_display_init_early(struct xe_device *xe) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - intel_dram_detect(xe); + err = intel_dram_detect(xe); + if (err) + goto err_opregion; intel_bw_init_hw(display); -- GitLab From e117100acb6d2dd90da01a88616a3b9261b0e99a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 May 2025 12:25:26 +0300 Subject: [PATCH 220/902] drm/i915/dram: allocate struct dram_info dynamically Allocate struct drm_info dynamically, and convert the struct drm_i915_private and struct xe_device dram_info member into a const pointer. Move the struct definition to intel_dram.h, and keep it opaque to everyone not needing it. This also removes the duplication of the struct definition. Reviewed-by: Vinod Govindapillai Link: https://lore.kernel.org/r/73625095157346ea0e8614108c9b369208e5df66.1748337870.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 21 ++------------------- drivers/gpu/drm/i915/soc/intel_dram.c | 17 +++++++++++++++-- drivers/gpu/drm/i915/soc/intel_dram.h | 23 ++++++++++++++++++++++- drivers/gpu/drm/xe/xe_device_types.h | 21 ++------------------- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 455548cbd8206..5e4c49f0d5d4c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -60,6 +60,7 @@ #include "intel_step.h" #include "intel_uncore.h" +struct dram_info; struct drm_i915_clock_gating_funcs; struct intel_display; struct intel_pxp; @@ -282,25 +283,7 @@ struct drm_i915_private { u32 suspend_count; struct vlv_s0ix_state *vlv_s0ix_state; - struct dram_info { - bool wm_lv_0_adjust_needed; - u8 num_channels; - bool symmetric_memory; - enum intel_dram_type { - INTEL_DRAM_UNKNOWN, - INTEL_DRAM_DDR3, - INTEL_DRAM_DDR4, - INTEL_DRAM_LPDDR3, - INTEL_DRAM_LPDDR4, - INTEL_DRAM_DDR5, - INTEL_DRAM_LPDDR5, - INTEL_DRAM_GDDR, - INTEL_DRAM_GDDR_ECC, - __INTEL_DRAM_TYPE_MAX, - } type; - u8 num_qgv_points; - u8 num_psf_gv_points; - } dram_info; + const struct dram_info *dram_info; struct intel_runtime_pm runtime_pm; diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index e7fa938c98cfe..59032c939d0f4 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -5,6 +5,8 @@ #include +#include + #include "../display/intel_display_core.h" /* FIXME */ #include "i915_drv.h" @@ -706,7 +708,7 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info int intel_dram_detect(struct drm_i915_private *i915) { - struct dram_info *dram_info = &i915->dram_info; + struct dram_info *dram_info; int ret; detect_fsb_freq(i915); @@ -715,6 +717,12 @@ int intel_dram_detect(struct drm_i915_private *i915) if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) return 0; + dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL); + if (!dram_info) + return -ENOMEM; + + i915->dram_info = dram_info; + /* * Assume level 0 watermark latency adjustment is needed until proven * otherwise, this w/a is not needed by bxt/glk. @@ -749,11 +757,16 @@ int intel_dram_detect(struct drm_i915_private *i915) return 0; } +/* + * Returns NULL for platforms that don't have dram info. Avoid overzealous NULL + * checks, and prefer not dereferencing on platforms that shouldn't look at dram + * info, to catch accidental and incorrect dram info checks. + */ const struct dram_info *intel_dram_info(struct drm_device *drm) { struct drm_i915_private *i915 = to_i915(drm); - return &i915->dram_info; + return i915->dram_info; } static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 25fe60b2b1178..2a696e03aad49 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -6,9 +6,30 @@ #ifndef __INTEL_DRAM_H__ #define __INTEL_DRAM_H__ +#include + struct drm_i915_private; struct drm_device; -struct dram_info; + +struct dram_info { + bool wm_lv_0_adjust_needed; + u8 num_channels; + bool symmetric_memory; + enum intel_dram_type { + INTEL_DRAM_UNKNOWN, + INTEL_DRAM_DDR3, + INTEL_DRAM_DDR4, + INTEL_DRAM_LPDDR3, + INTEL_DRAM_LPDDR4, + INTEL_DRAM_DDR5, + INTEL_DRAM_LPDDR5, + INTEL_DRAM_GDDR, + INTEL_DRAM_GDDR_ECC, + __INTEL_DRAM_TYPE_MAX, + } type; + u8 num_qgv_points; + u8 num_psf_gv_points; +}; void intel_dram_edram_detect(struct drm_i915_private *i915); int intel_dram_detect(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 5c56f0d96e32e..bbbf9e0f2cadd 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -30,6 +30,7 @@ #define TEST_VM_OPS_ERROR #endif +struct dram_info; struct intel_display; struct xe_ggtt; struct xe_pat_ops; @@ -585,25 +586,7 @@ struct xe_device { */ struct intel_display *display; - struct dram_info { - bool wm_lv_0_adjust_needed; - u8 num_channels; - bool symmetric_memory; - enum intel_dram_type { - INTEL_DRAM_UNKNOWN, - INTEL_DRAM_DDR3, - INTEL_DRAM_DDR4, - INTEL_DRAM_LPDDR3, - INTEL_DRAM_LPDDR4, - INTEL_DRAM_DDR5, - INTEL_DRAM_LPDDR5, - INTEL_DRAM_GDDR, - INTEL_DRAM_GDDR_ECC, - __INTEL_DRAM_TYPE_MAX, - } type; - u8 num_qgv_points; - u8 num_psf_gv_points; - } dram_info; + const struct dram_info *dram_info; /* * edram size in MB. -- GitLab From 9d9fca62dc49d96f97045b6d8e7402a95f8cf92a Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 3 Jun 2025 18:42:14 +0100 Subject: [PATCH 221/902] drm/xe/guc_submit: add back fix Daniele noticed that the fix in commit 2d2be279f1ca ("drm/xe: fix UAF around queue destruction") looks to have been unintentionally removed as part of handling a conflict in some past merge commit. Add it back. Fixes: ac44ff7cec33 ("Merge tag 'drm-xe-fixes-2024-10-10' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes") Reported-by: Daniele Ceraolo Spurio Signed-off-by: Matthew Auld Cc: Matthew Brost Cc: # v6.12+ Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250603174213.1543579-2-matthew.auld@intel.com --- drivers/gpu/drm/xe/xe_guc_submit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 80f748baad3f3..2b61d017eeca8 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -229,6 +229,17 @@ static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q) static void guc_submit_fini(struct drm_device *drm, void *arg) { struct xe_guc *guc = arg; + struct xe_device *xe = guc_to_xe(guc); + struct xe_gt *gt = guc_to_gt(guc); + int ret; + + ret = wait_event_timeout(guc->submission_state.fini_wq, + xa_empty(&guc->submission_state.exec_queue_lookup), + HZ * 5); + + drain_workqueue(xe->destroy_wq); + + xe_gt_assert(gt, ret); xa_destroy(&guc->submission_state.exec_queue_lookup); } -- GitLab From c206a27eb72f13d345d51818152e8707d4563b51 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 20 May 2025 11:26:58 +0300 Subject: [PATCH 222/902] drm/i915/dkl: return if tc_port is invalid in dkl_phy_set_hip_idx() In dkl_phy_set_hip_idx(), we may try to shift a value negatively, whose behavior is undefined. This can happen because we define TC_PORT_NONE to -1, so theoretically tc_port could be -1. We will then use tc_port to shift to the correct address of the specified port, but if it's negative, anything can happen. If this happens or tc_port exceeds I915_MAX_TC_PORTS, it's safer to return with a warning than risk an invalid write. Signed-off-by: Luca Coelho Reviewed-by: Mika Kahola Signed-off-by: Mika Kahola Link: https://lore.kernel.org/r/20250520082917.1302665-2-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/intel_dkl_phy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c index dad7192132ad9..35e919eae3691 100644 --- a/drivers/gpu/drm/i915/display/intel_dkl_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c @@ -25,7 +25,9 @@ dkl_phy_set_hip_idx(struct intel_display *display, struct intel_dkl_phy_reg reg) { enum tc_port tc_port = DKL_REG_TC_PORT(reg); - drm_WARN_ON(display->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS); + if (drm_WARN_ON(display->drm, + tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS)) + return; intel_de_write(display, HIP_INDEX_REG(tc_port), -- GitLab From babe098c5fb4e401127cb1e18256aa4db0f89571 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 20 May 2025 11:26:59 +0300 Subject: [PATCH 223/902] drm/i915: remove unused arg in skl_scaler_get_filter_select() We always pass 0 in the set argument of skl_scaler_get_filter_select() calls, so the argument is unnecessary. Remove it. Signed-off-by: Luca Coelho Reviewed-by: Gustavo Sousa Signed-off-by: Mika Kahola Link: https://lore.kernel.org/r/20250520082917.1302665-3-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index c855426544cf2..9cbfddb8556a3 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -695,15 +695,14 @@ static void glk_program_nearest_filter_coefs(struct intel_display *display, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0); } -static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set) +static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter) { - if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) { + if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) return (PS_FILTER_PROGRAMMED | - PS_Y_VERT_FILTER_SELECT(set) | - PS_Y_HORZ_FILTER_SELECT(set) | - PS_UV_VERT_FILTER_SELECT(set) | - PS_UV_HORZ_FILTER_SELECT(set)); - } + PS_Y_VERT_FILTER_SELECT(0) | + PS_Y_HORZ_FILTER_SELECT(0) | + PS_UV_VERT_FILTER_SELECT(0) | + PS_UV_HORZ_FILTER_SELECT(0)); return PS_FILTER_MEDIUM; } @@ -761,7 +760,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) id = scaler_state->scaler_id; ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | - skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0); + skl_scaler_get_filter_select(crtc_state->hw.scaling_filter); trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); @@ -827,7 +826,7 @@ skl_program_plane_scaler(struct intel_dsb *dsb, } ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode | - skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0); + skl_scaler_get_filter_select(plane_state->hw.scaling_filter); trace_intel_plane_scaler_update_arm(plane, scaler_id, crtc_x, crtc_y, crtc_w, crtc_h); -- GitLab From 7247efca0dcbc8ac6147db9200ed1549c0662465 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 20 May 2025 12:53:53 +0300 Subject: [PATCH 224/902] drm/i915: use drm_modeset_lock_assert_held() in intel_connector_get_pipe() In the intel_connector_get_pipe() function, we check if connection_mutex is held and generate our own WARN_ON if that's the case. Instead of generating a non-standard warning for a mutex issue, we should use the standard lockdep framework. Change the function to use drm_modeset_lock_assert_held() instead. Signed-off-by: Luca Coelho Reviewed-by: Jani Nikula Signed-off-by: Mika Kahola Link: https://lore.kernel.org/r/20250520095408.1310440-1-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/intel_connector.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index 6c81c9f2fd09a..9a61c972dce94 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -209,8 +209,7 @@ enum pipe intel_connector_get_pipe(struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); - drm_WARN_ON(display->drm, - !drm_modeset_is_locked(&display->drm->mode_config.connection_mutex)); + drm_modeset_lock_assert_held(&display->drm->mode_config.connection_mutex); if (!connector->base.state->crtc) return INVALID_PIPE; -- GitLab From 6678791ee3da0b78c28fe7d77814097f53cbb8df Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 3 Jun 2025 08:08:21 +0100 Subject: [PATCH 225/902] KVM: arm64: Add assignment-specific sysreg accessor Assigning a value to a system register doesn't do what it is supposed to be doing if that register is one that has RESx bits. The main problem is that we use __vcpu_sys_reg(), which can be used both as a lvalue and rvalue. When used as a lvalue, the bit masking occurs *before* the new value is assigned, meaning that we (1) do pointless work on the old cvalue, and (2) potentially assign an invalid value as we fail to apply the masks to it. Fix this by providing a new __vcpu_assign_sys_reg() that does what it says on the tin, and sanitises the *new* value instead of the old one. This comes with a significant amount of churn. Reviewed-by: Miguel Luis Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250603070824.1192795-2-maz@kernel.org Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/kvm_host.h | 11 ++++++ arch/arm64/kvm/arch_timer.c | 16 ++++---- arch/arm64/kvm/hyp/exception.c | 4 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 4 +- arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 6 +-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 4 +- arch/arm64/kvm/hyp/vhe/switch.c | 4 +- arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 44 +++++++++++----------- arch/arm64/kvm/pmu-emul.c | 14 +++---- arch/arm64/kvm/sys_regs.c | 38 ++++++++++--------- arch/arm64/kvm/sys_regs.h | 4 +- arch/arm64/kvm/vgic/vgic-v3-nested.c | 10 ++--- 12 files changed, 86 insertions(+), 73 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d941abc6b5eef..3b84ad91116b4 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1107,6 +1107,17 @@ static inline u64 *___ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r)) u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64); + +#define __vcpu_assign_sys_reg(v, r, val) \ + do { \ + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ + u64 __v = (val); \ + if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + \ + ctxt_sys_reg(ctxt, (r)) = __v; \ + } while (0) + #define __vcpu_sys_reg(v,r) \ (*({ \ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 5133dcbfe9f76..5a67a6d4d95b7 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -108,16 +108,16 @@ static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTV_CTL_EL0) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTV_CTL_EL0, ctl); break; case TIMER_PTIMER: - __vcpu_sys_reg(vcpu, CNTP_CTL_EL0) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTP_CTL_EL0, ctl); break; case TIMER_HVTIMER: - __vcpu_sys_reg(vcpu, CNTHV_CTL_EL2) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTHV_CTL_EL2, ctl); break; case TIMER_HPTIMER: - __vcpu_sys_reg(vcpu, CNTHP_CTL_EL2) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTHP_CTL_EL2, ctl); break; default: WARN_ON(1); @@ -130,16 +130,16 @@ static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0) = cval; + __vcpu_assign_sys_reg(vcpu, CNTV_CVAL_EL0, cval); break; case TIMER_PTIMER: - __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = cval; + __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, cval); break; case TIMER_HVTIMER: - __vcpu_sys_reg(vcpu, CNTHV_CVAL_EL2) = cval; + __vcpu_assign_sys_reg(vcpu, CNTHV_CVAL_EL2, cval); break; case TIMER_HPTIMER: - __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = cval; + __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, cval); break; default: WARN_ON(1); diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c index 424a5107cddb5..6a2a899a344e6 100644 --- a/arch/arm64/kvm/hyp/exception.c +++ b/arch/arm64/kvm/hyp/exception.c @@ -37,7 +37,7 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) if (unlikely(vcpu_has_nv(vcpu))) vcpu_write_sys_reg(vcpu, val, reg); else if (!__vcpu_write_sys_reg_to_cpu(val, reg)) - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); } static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, @@ -51,7 +51,7 @@ static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, } else if (has_vhe()) { write_sysreg_el1(val, SYS_SPSR); } else { - __vcpu_sys_reg(vcpu, SPSR_EL1) = val; + __vcpu_assign_sys_reg(vcpu, SPSR_EL1, val); } } diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index eef310cdbdbd5..aa5b561b92182 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -45,7 +45,7 @@ static inline void __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) if (!vcpu_el1_is_32bit(vcpu)) return; - __vcpu_sys_reg(vcpu, FPEXC32_EL2) = read_sysreg(fpexc32_el2); + __vcpu_assign_sys_reg(vcpu, FPEXC32_EL2, read_sysreg(fpexc32_el2)); } static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) @@ -457,7 +457,7 @@ static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) */ if (vcpu_has_sve(vcpu)) { zcr_el1 = read_sysreg_el1(SYS_ZCR); - __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1; + __vcpu_assign_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu), zcr_el1); /* * The guest's state is always saved using the guest's max VL. diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index b9cff893bbe0b..4d0dbea4c56f7 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -307,11 +307,11 @@ static inline void __sysreg32_save_state(struct kvm_vcpu *vcpu) vcpu->arch.ctxt.spsr_irq = read_sysreg(spsr_irq); vcpu->arch.ctxt.spsr_fiq = read_sysreg(spsr_fiq); - __vcpu_sys_reg(vcpu, DACR32_EL2) = read_sysreg(dacr32_el2); - __vcpu_sys_reg(vcpu, IFSR32_EL2) = read_sysreg(ifsr32_el2); + __vcpu_assign_sys_reg(vcpu, DACR32_EL2, read_sysreg(dacr32_el2)); + __vcpu_assign_sys_reg(vcpu, IFSR32_EL2, read_sysreg(ifsr32_el2)); if (has_vhe() || kvm_debug_regs_in_use(vcpu)) - __vcpu_sys_reg(vcpu, DBGVCR32_EL2) = read_sysreg(dbgvcr32_el2); + __vcpu_assign_sys_reg(vcpu, DBGVCR32_EL2, read_sysreg(dbgvcr32_el2)); } static inline void __sysreg32_restore_state(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 8e8848de4d470..e9198e56e784b 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -26,7 +26,7 @@ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt); static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) { - __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); + __vcpu_assign_sys_reg(vcpu, ZCR_EL1, read_sysreg_el1(SYS_ZCR)); /* * On saving/restoring guest sve state, always use the maximum VL for * the guest. The layout of the data when saving the sve state depends @@ -79,7 +79,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm)); if (has_fpmr) - __vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR); + __vcpu_assign_sys_reg(vcpu, FPMR, read_sysreg_s(SYS_FPMR)); if (system_supports_sve()) __hyp_sve_restore_host(); diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index c9b330dc20669..09df2b42bc1b7 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -223,9 +223,9 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) */ val = read_sysreg_el0(SYS_CNTP_CVAL); if (map.direct_ptimer == vcpu_ptimer(vcpu)) - __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = val; + __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, val); if (map.direct_ptimer == vcpu_hptimer(vcpu)) - __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = val; + __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, val); offset = read_sysreg_s(SYS_CNTPOFF_EL2); diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c index 3814b0b2c937f..34c7bf7fe9def 100644 --- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -18,17 +18,17 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) { /* These registers are common with EL1 */ - __vcpu_sys_reg(vcpu, PAR_EL1) = read_sysreg(par_el1); - __vcpu_sys_reg(vcpu, TPIDR_EL1) = read_sysreg(tpidr_el1); - - __vcpu_sys_reg(vcpu, ESR_EL2) = read_sysreg_el1(SYS_ESR); - __vcpu_sys_reg(vcpu, AFSR0_EL2) = read_sysreg_el1(SYS_AFSR0); - __vcpu_sys_reg(vcpu, AFSR1_EL2) = read_sysreg_el1(SYS_AFSR1); - __vcpu_sys_reg(vcpu, FAR_EL2) = read_sysreg_el1(SYS_FAR); - __vcpu_sys_reg(vcpu, MAIR_EL2) = read_sysreg_el1(SYS_MAIR); - __vcpu_sys_reg(vcpu, VBAR_EL2) = read_sysreg_el1(SYS_VBAR); - __vcpu_sys_reg(vcpu, CONTEXTIDR_EL2) = read_sysreg_el1(SYS_CONTEXTIDR); - __vcpu_sys_reg(vcpu, AMAIR_EL2) = read_sysreg_el1(SYS_AMAIR); + __vcpu_assign_sys_reg(vcpu, PAR_EL1, read_sysreg(par_el1)); + __vcpu_assign_sys_reg(vcpu, TPIDR_EL1, read_sysreg(tpidr_el1)); + + __vcpu_assign_sys_reg(vcpu, ESR_EL2, read_sysreg_el1(SYS_ESR)); + __vcpu_assign_sys_reg(vcpu, AFSR0_EL2, read_sysreg_el1(SYS_AFSR0)); + __vcpu_assign_sys_reg(vcpu, AFSR1_EL2, read_sysreg_el1(SYS_AFSR1)); + __vcpu_assign_sys_reg(vcpu, FAR_EL2, read_sysreg_el1(SYS_FAR)); + __vcpu_assign_sys_reg(vcpu, MAIR_EL2, read_sysreg_el1(SYS_MAIR)); + __vcpu_assign_sys_reg(vcpu, VBAR_EL2, read_sysreg_el1(SYS_VBAR)); + __vcpu_assign_sys_reg(vcpu, CONTEXTIDR_EL2, read_sysreg_el1(SYS_CONTEXTIDR)); + __vcpu_assign_sys_reg(vcpu, AMAIR_EL2, read_sysreg_el1(SYS_AMAIR)); /* * In VHE mode those registers are compatible between EL1 and EL2, @@ -46,21 +46,21 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) * are always trapped, ensuring that the in-memory * copy is always up-to-date. A small blessing... */ - __vcpu_sys_reg(vcpu, SCTLR_EL2) = read_sysreg_el1(SYS_SCTLR); - __vcpu_sys_reg(vcpu, TTBR0_EL2) = read_sysreg_el1(SYS_TTBR0); - __vcpu_sys_reg(vcpu, TTBR1_EL2) = read_sysreg_el1(SYS_TTBR1); - __vcpu_sys_reg(vcpu, TCR_EL2) = read_sysreg_el1(SYS_TCR); + __vcpu_assign_sys_reg(vcpu, SCTLR_EL2, read_sysreg_el1(SYS_SCTLR)); + __vcpu_assign_sys_reg(vcpu, TTBR0_EL2, read_sysreg_el1(SYS_TTBR0)); + __vcpu_assign_sys_reg(vcpu, TTBR1_EL2, read_sysreg_el1(SYS_TTBR1)); + __vcpu_assign_sys_reg(vcpu, TCR_EL2, read_sysreg_el1(SYS_TCR)); if (ctxt_has_tcrx(&vcpu->arch.ctxt)) { - __vcpu_sys_reg(vcpu, TCR2_EL2) = read_sysreg_el1(SYS_TCR2); + __vcpu_assign_sys_reg(vcpu, TCR2_EL2, read_sysreg_el1(SYS_TCR2)); if (ctxt_has_s1pie(&vcpu->arch.ctxt)) { - __vcpu_sys_reg(vcpu, PIRE0_EL2) = read_sysreg_el1(SYS_PIRE0); - __vcpu_sys_reg(vcpu, PIR_EL2) = read_sysreg_el1(SYS_PIR); + __vcpu_assign_sys_reg(vcpu, PIRE0_EL2, read_sysreg_el1(SYS_PIRE0)); + __vcpu_assign_sys_reg(vcpu, PIR_EL2, read_sysreg_el1(SYS_PIR)); } if (ctxt_has_s1poe(&vcpu->arch.ctxt)) - __vcpu_sys_reg(vcpu, POR_EL2) = read_sysreg_el1(SYS_POR); + __vcpu_assign_sys_reg(vcpu, POR_EL2, read_sysreg_el1(SYS_POR)); } /* @@ -74,9 +74,9 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) __vcpu_sys_reg(vcpu, CNTHCTL_EL2) |= val; } - __vcpu_sys_reg(vcpu, SP_EL2) = read_sysreg(sp_el1); - __vcpu_sys_reg(vcpu, ELR_EL2) = read_sysreg_el1(SYS_ELR); - __vcpu_sys_reg(vcpu, SPSR_EL2) = read_sysreg_el1(SYS_SPSR); + __vcpu_assign_sys_reg(vcpu, SP_EL2, read_sysreg(sp_el1)); + __vcpu_assign_sys_reg(vcpu, ELR_EL2, read_sysreg_el1(SYS_ELR)); + __vcpu_assign_sys_reg(vcpu, SPSR_EL2, read_sysreg_el1(SYS_SPSR)); } static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 25c29107f13fd..4f0ae8073f788 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -178,7 +178,7 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force) val |= lower_32_bits(val); } - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); /* Recreate the perf event to reflect the updated sample_period */ kvm_pmu_create_perf_event(pmc); @@ -204,7 +204,7 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) { kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx)); - __vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val; + __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(select_idx), val); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); } @@ -239,7 +239,7 @@ static void kvm_pmu_stop_counter(struct kvm_pmc *pmc) reg = counter_index_to_reg(pmc->idx); - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); kvm_pmu_release_perf_event(pmc); } @@ -503,7 +503,7 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu, reg = __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) + 1; if (!kvm_pmc_is_64bit(pmc)) reg = lower_32_bits(reg); - __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) = reg; + __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(i), reg); /* No overflow? move on */ if (kvm_pmc_has_64bit_overflow(pmc) ? reg : lower_32_bits(reg)) @@ -602,7 +602,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); /* The reset bits don't indicate any state, and shouldn't be saved. */ - __vcpu_sys_reg(vcpu, PMCR_EL0) = val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P); + __vcpu_assign_sys_reg(vcpu, PMCR_EL0, (val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P))); if (val & ARMV8_PMU_PMCR_C) kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0); @@ -779,7 +779,7 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, u64 reg; reg = counter_index_to_evtreg(pmc->idx); - __vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm); + __vcpu_assign_sys_reg(vcpu, reg, (data & kvm_pmu_evtyper_mask(vcpu->kvm))); kvm_pmu_create_perf_event(pmc); } @@ -1038,7 +1038,7 @@ static void kvm_arm_set_nr_counters(struct kvm *kvm, unsigned int nr) u64 val = __vcpu_sys_reg(vcpu, MDCR_EL2); val &= ~MDCR_EL2_HPMN; val |= FIELD_PREP(MDCR_EL2_HPMN, kvm->arch.nr_pmu_counters); - __vcpu_sys_reg(vcpu, MDCR_EL2) = val; + __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); } } } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 707c651aff031..93d0ca7ed9365 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -228,7 +228,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) * to reverse-translate virtual EL2 system registers for a * non-VHE guest hypervisor. */ - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); switch (reg) { case CNTHCTL_EL2: @@ -263,7 +263,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) return; memory_write: - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); } /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */ @@ -605,7 +605,7 @@ static int set_oslsr_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, if ((val ^ rd->val) & ~OSLSR_EL1_OSLK) return -EINVAL; - __vcpu_sys_reg(vcpu, rd->reg) = val; + __vcpu_assign_sys_reg(vcpu, rd->reg, val); return 0; } @@ -835,7 +835,7 @@ static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) * The value of PMCR.N field is included when the * vCPU register is read via kvm_vcpu_read_pmcr(). */ - __vcpu_sys_reg(vcpu, r->reg) = pmcr; + __vcpu_assign_sys_reg(vcpu, r->reg, pmcr); return __vcpu_sys_reg(vcpu, r->reg); } @@ -907,7 +907,7 @@ static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return false; if (p->is_write) - __vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval; + __vcpu_assign_sys_reg(vcpu, PMSELR_EL0, p->regval); else /* return PMSELR.SEL field */ p->regval = __vcpu_sys_reg(vcpu, PMSELR_EL0) @@ -1076,7 +1076,7 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va { u64 mask = kvm_pmu_accessible_counter_mask(vcpu); - __vcpu_sys_reg(vcpu, r->reg) = val & mask; + __vcpu_assign_sys_reg(vcpu, r->reg, val & mask); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); return 0; @@ -1185,8 +1185,8 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (!vcpu_mode_priv(vcpu)) return undef_access(vcpu, p, r); - __vcpu_sys_reg(vcpu, PMUSERENR_EL0) = - p->regval & ARMV8_PMU_USERENR_MASK; + __vcpu_assign_sys_reg(vcpu, PMUSERENR_EL0, + (p->regval & ARMV8_PMU_USERENR_MASK)); } else { p->regval = __vcpu_sys_reg(vcpu, PMUSERENR_EL0) & ARMV8_PMU_USERENR_MASK; @@ -1237,7 +1237,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, if (!kvm_supports_32bit_el0()) val |= ARMV8_PMU_PMCR_LC; - __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); return 0; @@ -2207,7 +2207,7 @@ static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) if (kvm_has_mte(vcpu->kvm)) clidr |= 2ULL << CLIDR_TTYPE_SHIFT(loc); - __vcpu_sys_reg(vcpu, r->reg) = clidr; + __vcpu_assign_sys_reg(vcpu, r->reg, clidr); return __vcpu_sys_reg(vcpu, r->reg); } @@ -2221,7 +2221,7 @@ static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, if ((val & CLIDR_EL1_RES0) || (!(ctr_el0 & CTR_EL0_IDC) && idc)) return -EINVAL; - __vcpu_sys_reg(vcpu, rd->reg) = val; + __vcpu_assign_sys_reg(vcpu, rd->reg, val); return 0; } @@ -2398,7 +2398,7 @@ static bool access_sp_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, SP_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, SP_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, SP_EL1); @@ -2422,7 +2422,7 @@ static bool access_spsr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, SPSR_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, SPSR_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, SPSR_EL1); @@ -2434,7 +2434,7 @@ static bool access_cntkctl_el12(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, CNTKCTL_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, CNTKCTL_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, CNTKCTL_EL1); @@ -2448,7 +2448,9 @@ static u64 reset_hcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) val |= HCR_E2H; - return __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); + + return __vcpu_sys_reg(vcpu, r->reg); } static unsigned int __el2_visibility(const struct kvm_vcpu *vcpu, @@ -2619,7 +2621,7 @@ static bool access_mdcr(struct kvm_vcpu *vcpu, u64_replace_bits(val, hpmn, MDCR_EL2_HPMN); } - __vcpu_sys_reg(vcpu, MDCR_EL2) = val; + __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); /* * Request a reload of the PMU to enable/disable the counters @@ -2748,7 +2750,7 @@ static int set_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - __vcpu_sys_reg(vcpu, r->reg) = vcpu->kvm->arch.nr_pmu_counters; + __vcpu_assign_sys_reg(vcpu, r->reg, vcpu->kvm->arch.nr_pmu_counters); return vcpu->kvm->arch.nr_pmu_counters; } @@ -5006,7 +5008,7 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, if (r->set_user) { ret = (r->set_user)(vcpu, r, val); } else { - __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); ret = 0; } diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index cc6338d387663..ef97d9fc67cc5 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -137,7 +137,7 @@ static inline u64 reset_unknown(struct kvm_vcpu *vcpu, { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); - __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL; + __vcpu_assign_sys_reg(vcpu, r->reg, 0x1de7ec7edbadc0deULL); return __vcpu_sys_reg(vcpu, r->reg); } @@ -145,7 +145,7 @@ static inline u64 reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); - __vcpu_sys_reg(vcpu, r->reg) = r->val; + __vcpu_assign_sys_reg(vcpu, r->reg, r->val); return __vcpu_sys_reg(vcpu, r->reg); } diff --git a/arch/arm64/kvm/vgic/vgic-v3-nested.c b/arch/arm64/kvm/vgic/vgic-v3-nested.c index 4f6954c306747..d22a8ad7bcc51 100644 --- a/arch/arm64/kvm/vgic/vgic-v3-nested.c +++ b/arch/arm64/kvm/vgic/vgic-v3-nested.c @@ -356,12 +356,12 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) val = __vcpu_sys_reg(vcpu, ICH_HCR_EL2); val &= ~ICH_HCR_EL2_EOIcount_MASK; val |= (s_cpu_if->vgic_hcr & ICH_HCR_EL2_EOIcount_MASK); - __vcpu_sys_reg(vcpu, ICH_HCR_EL2) = val; - __vcpu_sys_reg(vcpu, ICH_VMCR_EL2) = s_cpu_if->vgic_vmcr; + __vcpu_assign_sys_reg(vcpu, ICH_HCR_EL2, val); + __vcpu_assign_sys_reg(vcpu, ICH_VMCR_EL2, s_cpu_if->vgic_vmcr); for (i = 0; i < 4; i++) { - __vcpu_sys_reg(vcpu, ICH_AP0RN(i)) = s_cpu_if->vgic_ap0r[i]; - __vcpu_sys_reg(vcpu, ICH_AP1RN(i)) = s_cpu_if->vgic_ap1r[i]; + __vcpu_assign_sys_reg(vcpu, ICH_AP0RN(i), s_cpu_if->vgic_ap0r[i]); + __vcpu_assign_sys_reg(vcpu, ICH_AP1RN(i), s_cpu_if->vgic_ap1r[i]); } for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) { @@ -370,7 +370,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) val &= ~ICH_LR_STATE; val |= s_cpu_if->vgic_lr[i] & ICH_LR_STATE; - __vcpu_sys_reg(vcpu, ICH_LRN(i)) = val; + __vcpu_assign_sys_reg(vcpu, ICH_LRN(i), val); s_cpu_if->vgic_lr[i] = 0; } -- GitLab From 8800b7c4bbede3cd40831726d3f98e8080baf4df Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 3 Jun 2025 08:08:22 +0100 Subject: [PATCH 226/902] KVM: arm64: Add RMW specific sysreg accessor In a number of cases, we perform a Read-Modify-Write operation on a system register, meaning that we would apply the RESx masks twice. Instead, provide a new accessor that performs this RMW operation, allowing the masks to be applied exactly once per operation. Reviewed-by: Miguel Luis Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250603070824.1192795-3-maz@kernel.org Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/kvm_host.h | 11 +++++++++++ arch/arm64/kvm/debug.c | 4 ++-- arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 4 ++-- arch/arm64/kvm/nested.c | 2 +- arch/arm64/kvm/pmu-emul.c | 10 +++++----- arch/arm64/kvm/sys_regs.c | 22 +++++++++++----------- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3b84ad91116b4..8b8c649f225b0 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1118,6 +1118,17 @@ u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64); ctxt_sys_reg(ctxt, (r)) = __v; \ } while (0) +#define __vcpu_rmw_sys_reg(v, r, op, val) \ + do { \ + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ + u64 __v = ctxt_sys_reg(ctxt, (r)); \ + __v op (val); \ + if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + \ + ctxt_sys_reg(ctxt, (r)) = __v; \ + } while (0) + #define __vcpu_sys_reg(v,r) \ (*({ \ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 0e4c805e7e891..1a7dab333f557 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -216,9 +216,9 @@ void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu) void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val) { if (val & OSLAR_EL1_OSLK) - __vcpu_sys_reg(vcpu, OSLSR_EL1) |= OSLSR_EL1_OSLK; + __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, |=, OSLSR_EL1_OSLK); else - __vcpu_sys_reg(vcpu, OSLSR_EL1) &= ~OSLSR_EL1_OSLK; + __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, &=, ~OSLSR_EL1_OSLK); preempt_disable(); kvm_arch_vcpu_put(vcpu); diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c index 34c7bf7fe9def..73e4bc7fde9e4 100644 --- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -70,8 +70,8 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) */ val = read_sysreg_el1(SYS_CNTKCTL); val &= CNTKCTL_VALID_BITS; - __vcpu_sys_reg(vcpu, CNTHCTL_EL2) &= ~CNTKCTL_VALID_BITS; - __vcpu_sys_reg(vcpu, CNTHCTL_EL2) |= val; + __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, &=, ~CNTKCTL_VALID_BITS); + __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, |=, val); } __vcpu_assign_sys_reg(vcpu, SP_EL2, read_sysreg(sp_el1)); diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 4a53e4147fb01..5b191f4dc5668 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1757,7 +1757,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu) out: for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++) - (void)__vcpu_sys_reg(vcpu, sr); + __vcpu_rmw_sys_reg(vcpu, sr, |=, 0); return 0; } diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 4f0ae8073f788..b03dbda7f1ab9 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -510,7 +510,7 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu, continue; /* Mark overflow */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(i)); if (kvm_pmu_counter_can_chain(pmc)) kvm_pmu_counter_increment(vcpu, BIT(i + 1), @@ -556,7 +556,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, perf_event->attr.sample_period = period; perf_event->hw.sample_period = period; - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(idx)); if (kvm_pmu_counter_can_chain(pmc)) kvm_pmu_counter_increment(vcpu, BIT(idx + 1), @@ -914,9 +914,9 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu) { u64 mask = kvm_pmu_implemented_counter_mask(vcpu); - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask; - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask; - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask; + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, mask); + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, mask); + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, mask); kvm_pmu_reprogram_counter_mask(vcpu, mask); } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 93d0ca7ed9365..e89d345e42d09 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -791,7 +791,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) mask |= GENMASK(n - 1, 0); reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= mask; + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, mask); return __vcpu_sys_reg(vcpu, r->reg); } @@ -799,7 +799,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0); + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, GENMASK(31, 0)); return __vcpu_sys_reg(vcpu, r->reg); } @@ -811,7 +811,7 @@ static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) return 0; reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= kvm_pmu_evtyper_mask(vcpu->kvm); + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, kvm_pmu_evtyper_mask(vcpu->kvm)); return __vcpu_sys_reg(vcpu, r->reg); } @@ -819,7 +819,7 @@ static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= PMSELR_EL0_SEL_MASK; + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, PMSELR_EL0_SEL_MASK); return __vcpu_sys_reg(vcpu, r->reg); } @@ -1103,10 +1103,10 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p, val = p->regval & mask; if (r->Op2 & 0x1) /* accessing PMCNTENSET_EL0 */ - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val; + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, |=, val); else /* accessing PMCNTENCLR_EL0 */ - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val; + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, ~val); kvm_pmu_reprogram_counter_mask(vcpu, val); } else { @@ -1129,10 +1129,10 @@ static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (r->Op2 & 0x1) /* accessing PMINTENSET_EL1 */ - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val; + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, |=, val); else /* accessing PMINTENCLR_EL1 */ - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val; + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, ~val); } else { p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1); } @@ -1151,10 +1151,10 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (p->is_write) { if (r->CRm & 0x2) /* accessing PMOVSSET_EL0 */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= (p->regval & mask); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, (p->regval & mask)); else /* accessing PMOVSCLR_EL0 */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, ~(p->regval & mask)); } else { p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0); } @@ -4786,7 +4786,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) r->reset(vcpu, r); if (r->reg >= __SANITISED_REG_START__ && r->reg < NR_SYS_REGS) - (void)__vcpu_sys_reg(vcpu, r->reg); + __vcpu_rmw_sys_reg(vcpu, r->reg, |=, 0); } set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags); -- GitLab From b61fae4ee120f337b8700dff43b2fd639f3bf6a5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 3 Jun 2025 08:08:23 +0100 Subject: [PATCH 227/902] KVM: arm64: Don't use __vcpu_sys_reg() to get the address of a sysreg We are about to prevent the use of __vcpu_sys_reg() as a lvalue, and getting the address of a rvalue is not a thing. Update the couple of places where we do this to use the __ctxt_sys_reg() accessor, which return the address of a register. Reviewed-by: Miguel Luis Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250603070824.1192795-4-maz@kernel.org Signed-off-by: Marc Zyngier --- arch/arm64/kvm/arch_timer.c | 2 +- arch/arm64/kvm/fpsimd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 5a67a6d4d95b7..c6b4fb4c8e08f 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -1036,7 +1036,7 @@ void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) if (vcpu_has_nv(vcpu)) { struct arch_timer_offset *offs = &vcpu_vtimer(vcpu)->offset; - offs->vcpu_offset = &__vcpu_sys_reg(vcpu, CNTVOFF_EL2); + offs->vcpu_offset = __ctxt_sys_reg(&vcpu->arch.ctxt, CNTVOFF_EL2); offs->vm_offset = &vcpu->kvm->arch.timer_data.poffset; } diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 7f6e43d256915..8f6c8f57c6b9c 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -103,8 +103,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fp_state.sve_state = vcpu->arch.sve_state; fp_state.sve_vl = vcpu->arch.sve_max_vl; fp_state.sme_state = NULL; - fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR); - fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR); + fp_state.svcr = __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); + fp_state.fpmr = __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); fp_state.fp_type = &vcpu->arch.fp_type; if (vcpu_has_sve(vcpu)) -- GitLab From b5fa1f91e11fdf74ad4e2ac6dae246a57cbd2d95 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 3 Jun 2025 08:08:24 +0100 Subject: [PATCH 228/902] KVM: arm64: Make __vcpu_sys_reg() a pure rvalue operand Now that we don't have any use of __vcpu_sys_reg() as a lvalue, remove the in-place update, and directly return the sanitised value. Reviewed-by: Miguel Luis Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250603070824.1192795-5-maz@kernel.org Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/kvm_host.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 8b8c649f225b0..382b382d14dac 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1130,13 +1130,13 @@ u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64); } while (0) #define __vcpu_sys_reg(v,r) \ - (*({ \ + ({ \ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ - u64 *__r = __ctxt_sys_reg(ctxt, (r)); \ + u64 __v = ctxt_sys_reg(ctxt, (r)); \ if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ - *__r = kvm_vcpu_apply_reg_masks((v), (r), *__r);\ - __r; \ - })) + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + __v; \ + }) u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg); void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg); -- GitLab From 9a9864fd09c7e52440c05e70609bf5ee8da425d0 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 5 Jun 2025 12:36:10 +0200 Subject: [PATCH 229/902] KVM: arm64: selftests: Fix help text for arch_timer_edge_cases Fix the help text for arch_timer_edge_cases to show the correct option for setting the wait time. Signed-off-by: Sebastian Ott Link: https://lore.kernel.org/r/20250605103613.14544-2-sebott@redhat.com Signed-off-by: Marc Zyngier --- tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c index a36a7e2db434b..c4716e0c1438e 100644 --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c @@ -986,7 +986,7 @@ static void test_print_help(char *name) pr_info("\t-b: Test both physical and virtual timers (default: true)\n"); pr_info("\t-l: Delta (in ms) used for long wait time test (default: %u)\n", LONG_WAIT_TEST_MS); - pr_info("\t-l: Delta (in ms) used for wait times (default: %u)\n", + pr_info("\t-w: Delta (in ms) used for wait times (default: %u)\n", WAIT_TEST_MS); pr_info("\t-p: Test physical timer (default: true)\n"); pr_info("\t-v: Test virtual timer (default: true)\n"); -- GitLab From 050632ae6571d0f148fa0d4b90b6409a12645461 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 5 Jun 2025 12:36:11 +0200 Subject: [PATCH 230/902] KVM: arm64: selftests: Fix thread migration in arch_timer_edge_cases arch_timer_edge_cases tries to migrate itself across host cpus. Before the first test, it migrates to cpu 0 by setting up an affinity mask with only bit 0 set. After that it looks for the next possible cpu in the current affinity mask which still has only bit 0 set. So there is no migration at all. Fix this by reading the default mask at start and use this to find the next cpu in each iteration. Signed-off-by: Sebastian Ott Link: https://lore.kernel.org/r/20250605103613.14544-3-sebott@redhat.com Signed-off-by: Marc Zyngier --- tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c index c4716e0c1438e..a813b4c6c8172 100644 --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c @@ -849,17 +849,17 @@ static void guest_code(enum arch_timer timer) GUEST_DONE(); } +static cpu_set_t default_cpuset; + static uint32_t next_pcpu(void) { uint32_t max = get_nprocs(); uint32_t cur = sched_getcpu(); uint32_t next = cur; - cpu_set_t cpuset; + cpu_set_t cpuset = default_cpuset; TEST_ASSERT(max > 1, "Need at least two physical cpus"); - sched_getaffinity(0, sizeof(cpuset), &cpuset); - do { next = (next + 1) % CPU_SETSIZE; } while (!CPU_ISSET(next, &cpuset)); @@ -1046,6 +1046,8 @@ int main(int argc, char *argv[]) if (!parse_args(argc, argv)) exit(KSFT_SKIP); + sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset); + if (test_args.test_virtual) { test_vm_create(&vm, &vcpu, VIRTUAL); test_run(vm, vcpu); -- GitLab From 05ce38d489dbc96eb1dd700b287f949cb8cc0610 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 5 Jun 2025 12:36:12 +0200 Subject: [PATCH 231/902] KVM: arm64: selftests: Fix xVAL init in arch_timer_edge_cases arch_timer_edge_cases hits the following assertion in < 10% of the test runs: ==== Test Assertion Failure ==== arm64/arch_timer_edge_cases.c:490: timer_get_cntct(timer) >= DEF_CNT + (timer_get_cntfrq() * (uint64_t)(delta_2_ms) / 1000) pid=17110 tid=17110 errno=4 - Interrupted system call 1 0x0000000000404ec7: test_run at arch_timer_edge_cases.c:945 2 0x0000000000401fa3: main at arch_timer_edge_cases.c:1074 3 0x0000ffffa774b587: ?? ??:0 4 0x0000ffffa774b65f: ?? ??:0 5 0x000000000040206f: _start at ??:? timer_get_cntct(timer) >= DEF_CNT + msec_to_cycles(delta_2_ms) Enabling the timer without proper xval initialization in set_tval_irq() resulted in an early interrupt during timer reprogramming. Make sure to set the xval before setting the enable bit. Signed-off-by: Sebastian Ott Link: https://lore.kernel.org/r/20250605103613.14544-4-sebott@redhat.com Signed-off-by: Marc Zyngier --- tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c index a813b4c6c8172..be8bbedc933b3 100644 --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c @@ -191,8 +191,8 @@ static void set_tval_irq(enum arch_timer timer, uint64_t tval_cycles, { atomic_set(&shared_data.handled, 0); atomic_set(&shared_data.spurious, 0); - timer_set_ctl(timer, ctl); timer_set_tval(timer, tval_cycles); + timer_set_ctl(timer, ctl); } static void set_xval_irq(enum arch_timer timer, uint64_t xval, uint32_t ctl, -- GitLab From fad4cf944839da7f5c3376243aa353295c88f588 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 5 Jun 2025 12:36:13 +0200 Subject: [PATCH 232/902] KVM: arm64: selftests: Determine effective counter width in arch_timer_edge_cases arch_timer_edge_cases uses ~0 as the maximum counter value, however there's no architectural guarantee that this is valid. Figure out the effective counter width based on the effective frequency like it's done by the kernel. This also serves as a workaround for AC03_CPU_14 that led to the following assertion failure on ampere-one machines: ==== Test Assertion Failure ==== arm64/arch_timer_edge_cases.c:169: timer_condition == istatus pid=11236 tid=11236 errno=4 - Interrupted system call 1 0x0000000000404ce7: test_run at arch_timer_edge_cases.c:938 2 0x0000000000401ebb: main at arch_timer_edge_cases.c:1053 3 0x0000ffff9fa8625b: ?? ??:0 4 0x0000ffff9fa8633b: ?? ??:0 5 0x0000000000401fef: _start at ??:? 0x1 != 0x0 (timer_condition != istatus) Note that the following subtest only worked since the counter initialized with CVAL_MAX would instantly overflow (which is no longer the case): test_set_cnt_after_cval_no_irq(timer, 0, DEF_CNT, CVAL_MAX, sm); To fix this we could swap CVAL_MAX for 0 here but since that is already done by test_move_counters_behind_timers() let's remove that subtest. Link: https://lore.kernel.org/kvmarm/ac1de1d2-ef2b-d439-dc48-8615e121b07b@redhat.com Link: https://amperecomputing.com/assets/AmpereOne_Developer_ER_v0_80_20240823_28945022f4.pdf Signed-off-by: Sebastian Ott Link: https://lore.kernel.org/r/20250605103613.14544-5-sebott@redhat.com Signed-off-by: Marc Zyngier --- .../kvm/arm64/arch_timer_edge_cases.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c index be8bbedc933b3..b4d22b3ab7cc0 100644 --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c @@ -22,7 +22,8 @@ #include "gic.h" #include "vgic.h" -static const uint64_t CVAL_MAX = ~0ULL; +/* Depends on counter width. */ +static uint64_t CVAL_MAX; /* tval is a signed 32-bit int. */ static const int32_t TVAL_MAX = INT32_MAX; static const int32_t TVAL_MIN = INT32_MIN; @@ -30,8 +31,8 @@ static const int32_t TVAL_MIN = INT32_MIN; /* After how much time we say there is no IRQ. */ static const uint32_t TIMEOUT_NO_IRQ_US = 50000; -/* A nice counter value to use as the starting one for most tests. */ -static const uint64_t DEF_CNT = (CVAL_MAX / 2); +/* Counter value to use as the starting one for most tests. Set to CVAL_MAX/2 */ +static uint64_t DEF_CNT; /* Number of runs. */ static const uint32_t NR_TEST_ITERS_DEF = 5; @@ -732,12 +733,6 @@ static void test_move_counters_ahead_of_timers(enum arch_timer timer) test_set_cnt_after_tval(timer, 0, tval, (uint64_t) tval + 1, wm); } - - for (i = 0; i < ARRAY_SIZE(sleep_method); i++) { - sleep_method_t sm = sleep_method[i]; - - test_set_cnt_after_cval_no_irq(timer, 0, DEF_CNT, CVAL_MAX, sm); - } } /* @@ -975,6 +970,8 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu, test_init_timer_irq(*vm, *vcpu); vgic_v3_setup(*vm, 1, 64); sync_global_to_guest(*vm, test_args); + sync_global_to_guest(*vm, CVAL_MAX); + sync_global_to_guest(*vm, DEF_CNT); } static void test_print_help(char *name) @@ -1035,6 +1032,17 @@ static bool parse_args(int argc, char *argv[]) return false; } +static void set_counter_defaults(void) +{ + const uint64_t MIN_ROLLOVER_SECS = 40ULL * 365 * 24 * 3600; + uint64_t freq = read_sysreg(CNTFRQ_EL0); + uint64_t width = ilog2(MIN_ROLLOVER_SECS * freq); + + width = clamp(width, 56, 64); + CVAL_MAX = GENMASK_ULL(width - 1, 0); + DEF_CNT = CVAL_MAX / 2; +} + int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; @@ -1047,6 +1055,7 @@ int main(int argc, char *argv[]) exit(KSFT_SKIP); sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset); + set_counter_defaults(); if (test_args.test_virtual) { test_vm_create(&vm, &vcpu, VIRTUAL); -- GitLab From 308a3a8ce8ea41b26c46169f3263e50f5997c28e Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 31 May 2025 18:24:58 +0300 Subject: [PATCH 233/902] Bluetooth: hci_core: fix list_for_each_entry_rcu usage Releasing + re-acquiring RCU lock inside list_for_each_entry_rcu() loop body is not correct. Fix by taking the update-side hdev->lock instead. Fixes: c7eaf80bfb0c ("Bluetooth: Fix hci_link_tx_to RCU lock usage") Signed-off-by: Pauli Virtanen Reviewed-by: Paul Menzel Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3b49828160b73..04845ff3ad57d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3417,23 +3417,18 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) bt_dev_err(hdev, "link tx timeout"); - rcu_read_lock(); + hci_dev_lock(hdev); /* Kill stalled connections */ - list_for_each_entry_rcu(c, &h->list, list) { + list_for_each_entry(c, &h->list, list) { if (c->type == type && c->sent) { bt_dev_err(hdev, "killing stalled connection %pMR", &c->dst); - /* hci_disconnect might sleep, so, we have to release - * the RCU read lock before calling it. - */ - rcu_read_unlock(); hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); - rcu_read_lock(); } } - rcu_read_unlock(); + hci_dev_unlock(hdev); } static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, -- GitLab From daabd276985055250528da97e9ce6d277d7009c2 Mon Sep 17 00:00:00 2001 From: Kiran K Date: Tue, 3 Jun 2025 15:34:38 +0530 Subject: [PATCH 234/902] Bluetooth: btintel_pcie: Fix driver not posting maximum rx buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver was posting only 6 rx buffers, despite the maximum rx buffers being defined as 16. Having fewer RX buffers caused firmware exceptions in HID use cases when events arrived in bursts. Exception seen on android 6.12 kernel. E Bluetooth: hci0: Received hw exception interrupt E Bluetooth: hci0: Received gp1 mailbox interrupt D Bluetooth: hci0: 00000000: ff 3e 87 80 03 01 01 01 03 01 0c 0d 02 1c 10 0e D Bluetooth: hci0: 00000010: 01 00 05 14 66 b0 28 b0 c0 b0 28 b0 ac af 28 b0 D Bluetooth: hci0: 00000020: 14 f1 28 b0 00 00 00 00 fa 04 00 00 00 00 40 10 D Bluetooth: hci0: 00000030: 08 00 00 00 7a 7a 7a 7a 47 00 fb a0 10 00 00 00 D Bluetooth: hci0: 00000000: 10 01 0a E Bluetooth: hci0: ---- Dump of debug registers — E Bluetooth: hci0: boot stage: 0xe0fb0047 E Bluetooth: hci0: ipc status: 0x00000004 E Bluetooth: hci0: ipc control: 0x00000000 E Bluetooth: hci0: ipc sleep control: 0x00000000 E Bluetooth: hci0: mbox_1: 0x00badbad E Bluetooth: hci0: mbox_2: 0x0000101c E Bluetooth: hci0: mbox_3: 0x00000008 E Bluetooth: hci0: mbox_4: 0x7a7a7a7a Signed-off-by: Chandrashekar Devegowda Signed-off-by: Kiran K Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btintel_pcie.c | 3 ++- drivers/bluetooth/btintel_pcie.h | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 50fe17f1e1d18..2c7731803c9fe 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -396,8 +396,9 @@ static int btintel_pcie_submit_rx(struct btintel_pcie_data *data) static int btintel_pcie_start_rx(struct btintel_pcie_data *data) { int i, ret; + struct rxq *rxq = &data->rxq; - for (i = 0; i < BTINTEL_PCIE_RX_MAX_QUEUE; i++) { + for (i = 0; i < rxq->count; i++) { ret = btintel_pcie_submit_rx(data); if (ret) return ret; diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h index 21b964b15c1c9..5ddd6d7d8d456 100644 --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -177,9 +177,6 @@ enum { /* Doorbell vector for TFD */ #define BTINTEL_PCIE_TX_DB_VEC 0 -/* Number of pending RX requests for downlink */ -#define BTINTEL_PCIE_RX_MAX_QUEUE 6 - /* Doorbell vector for FRBD */ #define BTINTEL_PCIE_RX_DB_VEC 513 -- GitLab From 2dd711102ce69ae41f65d09c012441227d4aa983 Mon Sep 17 00:00:00 2001 From: Chandrashekar Devegowda Date: Tue, 3 Jun 2025 15:34:39 +0530 Subject: [PATCH 235/902] Bluetooth: btintel_pcie: Increase the tx and rx descriptor count This change addresses latency issues observed in HID use cases where events arrive in bursts. By increasing the Rx descriptor count to 64, the firmware can handle bursty data more effectively, reducing latency and preventing buffer overflows. Signed-off-by: Chandrashekar Devegowda Signed-off-by: Kiran K Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btintel_pcie.c | 24 ++++++++++++------------ drivers/bluetooth/btintel_pcie.h | 7 +++++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 2c7731803c9fe..03f13de4a723e 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -1783,8 +1783,8 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) * + size of index * Number of queues(2) * type of index array(4) * + size of context information */ - total = (sizeof(struct tfd) + sizeof(struct urbd0) + sizeof(struct frbd) - + sizeof(struct urbd1)) * BTINTEL_DESCS_COUNT; + total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT; + total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT; /* Add the sum of size of index array and size of ci struct */ total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info); @@ -1809,36 +1809,36 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) data->dma_v_addr = v_addr; /* Setup descriptor count */ - data->txq.count = BTINTEL_DESCS_COUNT; - data->rxq.count = BTINTEL_DESCS_COUNT; + data->txq.count = BTINTEL_PCIE_TX_DESCS_COUNT; + data->rxq.count = BTINTEL_PCIE_RX_DESCS_COUNT; /* Setup tfds */ data->txq.tfds_p_addr = p_addr; data->txq.tfds = v_addr; - p_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup urbd0 */ data->txq.urbd0s_p_addr = p_addr; data->txq.urbd0s = v_addr; - p_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup FRBD*/ data->rxq.frbds_p_addr = p_addr; data->rxq.frbds = v_addr; - p_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup urbd1 */ data->rxq.urbd1s_p_addr = p_addr; data->rxq.urbd1s = v_addr; - p_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup data buffers for txq */ err = btintel_pcie_setup_txq_bufs(data, &data->txq); diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h index 5ddd6d7d8d456..7dad4523236c9 100644 --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -154,8 +154,11 @@ enum msix_mbox_int_causes { /* Default interrupt timeout in msec */ #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000 -/* The number of descriptors in TX/RX queues */ -#define BTINTEL_DESCS_COUNT 16 +/* The number of descriptors in TX queues */ +#define BTINTEL_PCIE_TX_DESCS_COUNT 32 + +/* The number of descriptors in RX queues */ +#define BTINTEL_PCIE_RX_DESCS_COUNT 64 /* Number of Queue for TX and RX * It indicates the index of the IA(Index Array) -- GitLab From bf2ffc4d14db29cab781549912d2dc69127f4d3e Mon Sep 17 00:00:00 2001 From: Chandrashekar Devegowda Date: Tue, 3 Jun 2025 15:34:40 +0530 Subject: [PATCH 236/902] Bluetooth: btintel_pcie: Reduce driver buffer posting to prevent race condition Modify the driver to post 3 fewer buffers than the maximum rx buffers (64) allowed for the firmware. This change mitigates a hardware issue causing a race condition in the firmware, improving stability and data handling. Signed-off-by: Chandrashekar Devegowda Signed-off-by: Kiran K Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btintel_pcie.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 03f13de4a723e..563165c5efae3 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -398,7 +398,11 @@ static int btintel_pcie_start_rx(struct btintel_pcie_data *data) int i, ret; struct rxq *rxq = &data->rxq; - for (i = 0; i < rxq->count; i++) { + /* Post (BTINTEL_PCIE_RX_DESCS_COUNT - 3) buffers to overcome the + * hardware issues leading to race condition at the firmware. + */ + + for (i = 0; i < rxq->count - 3; i++) { ret = btintel_pcie_submit_rx(data); if (ret) return ret; -- GitLab From e6ed54e86aae9e4f7286ce8d5c73780f91b48d1c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 3 Jun 2025 16:12:39 -0400 Subject: [PATCH 237/902] Bluetooth: MGMT: Fix UAF on mgmt_remove_adv_monitor_complete This reworks MGMT_OP_REMOVE_ADV_MONITOR to not use mgmt_pending_add to avoid crashes like bellow: ================================================================== BUG: KASAN: slab-use-after-free in mgmt_remove_adv_monitor_complete+0xe5/0x540 net/bluetooth/mgmt.c:5406 Read of size 8 at addr ffff88801c53f318 by task kworker/u5:5/5341 CPU: 0 UID: 0 PID: 5341 Comm: kworker/u5:5 Not tainted 6.15.0-syzkaller-10402-g4cb6c8af8591 #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:408 [inline] print_report+0xd2/0x2b0 mm/kasan/report.c:521 kasan_report+0x118/0x150 mm/kasan/report.c:634 mgmt_remove_adv_monitor_complete+0xe5/0x540 net/bluetooth/mgmt.c:5406 hci_cmd_sync_work+0x261/0x3a0 net/bluetooth/hci_sync.c:334 process_one_work kernel/workqueue.c:3238 [inline] process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3321 worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402 kthread+0x711/0x8a0 kernel/kthread.c:464 ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 Allocated by task 5987: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4358 kmalloc_noprof include/linux/slab.h:905 [inline] kzalloc_noprof include/linux/slab.h:1039 [inline] mgmt_pending_new+0x65/0x240 net/bluetooth/mgmt_util.c:252 mgmt_pending_add+0x34/0x120 net/bluetooth/mgmt_util.c:279 remove_adv_monitor+0x103/0x1b0 net/bluetooth/mgmt.c:5454 hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 sock_sendmsg_nosec net/socket.c:712 [inline] __sock_sendmsg+0x219/0x270 net/socket.c:727 sock_write_iter+0x258/0x330 net/socket.c:1131 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x548/0xa90 fs/read_write.c:686 ksys_write+0x145/0x250 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 5989: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2380 [inline] slab_free mm/slub.c:4642 [inline] kfree+0x18e/0x440 mm/slub.c:4841 mgmt_pending_foreach+0xc9/0x120 net/bluetooth/mgmt_util.c:242 mgmt_index_removed+0x10d/0x2f0 net/bluetooth/mgmt.c:9366 hci_sock_bind+0xbe9/0x1000 net/bluetooth/hci_sock.c:1314 __sys_bind_socket net/socket.c:1810 [inline] __sys_bind+0x2c3/0x3e0 net/socket.c:1841 __do_sys_bind net/socket.c:1846 [inline] __se_sys_bind net/socket.c:1844 [inline] __x64_sys_bind+0x7a/0x90 net/socket.c:1844 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f Fixes: 66bd095ab5d4 ("Bluetooth: advmon offload MSFT remove monitor") Closes: https://syzkaller.appspot.com/bug?extid=feb0dc579bbe30a13190 Reported-by: syzbot+feb0dc579bbe30a13190@syzkaller.appspotmail.com Tested-by: syzbot+feb0dc579bbe30a13190@syzkaller.appspotmail.com Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_core.c | 4 +--- net/bluetooth/mgmt.c | 37 ++++++++++---------------------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2b261e74e2c4c..93fcb659f0d46 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -2400,7 +2400,6 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance); void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, u8 instance); -void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle); int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip); void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, bdaddr_t *bdaddr, u8 addr_type); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 04845ff3ad57d..aeda2e4557d5f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1877,10 +1877,8 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor) if (monitor->handle) idr_remove(&hdev->adv_monitors_idr, monitor->handle); - if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) { + if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) hdev->adv_monitors_cnt--; - mgmt_adv_monitor_removed(hdev, monitor->handle); - } kfree(monitor); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 14a9462fced5e..feaeec2423ae8 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5108,24 +5108,14 @@ static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev, mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk); } -void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle) +static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev, + u16 handle) { struct mgmt_ev_adv_monitor_removed ev; - struct mgmt_pending_cmd *cmd; - struct sock *sk_skip = NULL; - struct mgmt_cp_remove_adv_monitor *cp; - - cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev); - if (cmd) { - cp = cmd->param; - - if (cp->monitor_handle) - sk_skip = cmd->sk; - } ev.monitor_handle = cpu_to_le16(handle); - mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk_skip); + mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk); } static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev, @@ -5227,8 +5217,7 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev, if (pending_find(MGMT_OP_SET_LE, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) || - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) { + pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { status = MGMT_STATUS_BUSY; goto unlock; } @@ -5398,8 +5387,7 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd = data; struct mgmt_cp_remove_adv_monitor *cp; - if (status == -ECANCELED || - cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) + if (status == -ECANCELED) return; hci_dev_lock(hdev); @@ -5408,12 +5396,14 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, rp.monitor_handle = cp->monitor_handle; - if (!status) + if (!status) { + mgmt_adv_monitor_removed(cmd->sk, hdev, cp->monitor_handle); hci_update_passive_scan(hdev); + } mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), &rp, sizeof(rp)); - mgmt_pending_remove(cmd); + mgmt_pending_free(cmd); hci_dev_unlock(hdev); bt_dev_dbg(hdev, "remove monitor %d complete, status %d", @@ -5423,10 +5413,6 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, static int mgmt_remove_adv_monitor_sync(struct hci_dev *hdev, void *data) { struct mgmt_pending_cmd *cmd = data; - - if (cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) - return -ECANCELED; - struct mgmt_cp_remove_adv_monitor *cp = cmd->param; u16 handle = __le16_to_cpu(cp->monitor_handle); @@ -5445,14 +5431,13 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev, hci_dev_lock(hdev); if (pending_find(MGMT_OP_SET_LE, hdev) || - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { status = MGMT_STATUS_BUSY; goto unlock; } - cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); + cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); if (!cmd) { status = MGMT_STATUS_NO_RESOURCES; goto unlock; @@ -5462,7 +5447,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev, mgmt_remove_adv_monitor_complete); if (err) { - mgmt_pending_remove(cmd); + mgmt_pending_free(cmd); if (err == -ENOMEM) status = MGMT_STATUS_NO_RESOURCES; -- GitLab From 6fe26f694c824b8a4dbf50c635bee1302e3f099c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 20 May 2025 15:42:21 -0400 Subject: [PATCH 238/902] Bluetooth: MGMT: Protect mgmt_pending list with its own lock This uses a mutex to protect from concurrent access of mgmt_pending list which can cause crashes like: ================================================================== BUG: KASAN: slab-use-after-free in hci_sock_get_channel+0x60/0x68 net/bluetooth/hci_sock.c:91 Read of size 2 at addr ffff0000c48885b2 by task syz.4.334/7318 CPU: 0 UID: 0 PID: 7318 Comm: syz.4.334 Not tainted 6.15.0-rc7-syzkaller-g187899f4124a #0 PREEMPT Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025 Call trace: show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:466 (C) __dump_stack+0x30/0x40 lib/dump_stack.c:94 dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120 print_address_description+0xa8/0x254 mm/kasan/report.c:408 print_report+0x68/0x84 mm/kasan/report.c:521 kasan_report+0xb0/0x110 mm/kasan/report.c:634 __asan_report_load2_noabort+0x20/0x2c mm/kasan/report_generic.c:379 hci_sock_get_channel+0x60/0x68 net/bluetooth/hci_sock.c:91 mgmt_pending_find+0x7c/0x140 net/bluetooth/mgmt_util.c:223 pending_find net/bluetooth/mgmt.c:947 [inline] remove_adv_monitor+0x44/0x1a4 net/bluetooth/mgmt.c:5445 hci_mgmt_cmd+0x780/0xc00 net/bluetooth/hci_sock.c:1712 hci_sock_sendmsg+0x544/0xbb0 net/bluetooth/hci_sock.c:1832 sock_sendmsg_nosec net/socket.c:712 [inline] __sock_sendmsg net/socket.c:727 [inline] sock_write_iter+0x25c/0x378 net/socket.c:1131 new_sync_write fs/read_write.c:591 [inline] vfs_write+0x62c/0x97c fs/read_write.c:684 ksys_write+0x120/0x210 fs/read_write.c:736 __do_sys_write fs/read_write.c:747 [inline] __se_sys_write fs/read_write.c:744 [inline] __arm64_sys_write+0x7c/0x90 fs/read_write.c:744 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151 el0_svc+0x58/0x17c arch/arm64/kernel/entry-common.c:767 el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:786 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600 Allocated by task 7037: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_alloc_info+0x44/0x54 mm/kasan/generic.c:562 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x9c/0xb4 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __do_kmalloc_node mm/slub.c:4327 [inline] __kmalloc_noprof+0x2fc/0x4c8 mm/slub.c:4339 kmalloc_noprof include/linux/slab.h:909 [inline] sk_prot_alloc+0xc4/0x1f0 net/core/sock.c:2198 sk_alloc+0x44/0x3ac net/core/sock.c:2254 bt_sock_alloc+0x4c/0x300 net/bluetooth/af_bluetooth.c:148 hci_sock_create+0xa8/0x194 net/bluetooth/hci_sock.c:2202 bt_sock_create+0x14c/0x24c net/bluetooth/af_bluetooth.c:132 __sock_create+0x43c/0x91c net/socket.c:1541 sock_create net/socket.c:1599 [inline] __sys_socket_create net/socket.c:1636 [inline] __sys_socket+0xd4/0x1c0 net/socket.c:1683 __do_sys_socket net/socket.c:1697 [inline] __se_sys_socket net/socket.c:1695 [inline] __arm64_sys_socket+0x7c/0x94 net/socket.c:1695 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151 el0_svc+0x58/0x17c arch/arm64/kernel/entry-common.c:767 el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:786 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600 Freed by task 6607: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:576 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x68/0x88 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2380 [inline] slab_free mm/slub.c:4642 [inline] kfree+0x17c/0x474 mm/slub.c:4841 sk_prot_free net/core/sock.c:2237 [inline] __sk_destruct+0x4f4/0x760 net/core/sock.c:2332 sk_destruct net/core/sock.c:2360 [inline] __sk_free+0x320/0x430 net/core/sock.c:2371 sk_free+0x60/0xc8 net/core/sock.c:2382 sock_put include/net/sock.h:1944 [inline] mgmt_pending_free+0x88/0x118 net/bluetooth/mgmt_util.c:290 mgmt_pending_remove+0xec/0x104 net/bluetooth/mgmt_util.c:298 mgmt_set_powered_complete+0x418/0x5cc net/bluetooth/mgmt.c:1355 hci_cmd_sync_work+0x204/0x33c net/bluetooth/hci_sync.c:334 process_one_work+0x7e8/0x156c kernel/workqueue.c:3238 process_scheduled_works kernel/workqueue.c:3319 [inline] worker_thread+0x958/0xed8 kernel/workqueue.c:3400 kthread+0x5fc/0x75c kernel/kthread.c:464 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:847 Fixes: a380b6cff1a2 ("Bluetooth: Add generic mgmt helper API") Closes: https://syzkaller.appspot.com/bug?extid=0a7039d5d9986ff4ecec Closes: https://syzkaller.appspot.com/bug?extid=cc0cc52e7f43dc9e6df1 Reported-by: syzbot+0a7039d5d9986ff4ecec@syzkaller.appspotmail.com Tested-by: syzbot+0a7039d5d9986ff4ecec@syzkaller.appspotmail.com Tested-by: syzbot+cc0cc52e7f43dc9e6df1@syzkaller.appspotmail.com Signed-off-by: Dmitry Antipov Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 1 + net/bluetooth/mgmt.c | 101 +++++++++++++++---------------- net/bluetooth/mgmt_util.c | 32 ++++++++-- net/bluetooth/mgmt_util.h | 4 +- 5 files changed, 80 insertions(+), 59 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 93fcb659f0d46..f7b1a9eb9543f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -546,6 +546,7 @@ struct hci_dev { struct hci_conn_hash conn_hash; struct list_head mesh_pending; + struct mutex mgmt_pending_lock; struct list_head mgmt_pending; struct list_head reject_list; struct list_head accept_list; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aeda2e4557d5f..487c045a7ba8a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2485,6 +2485,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv) mutex_init(&hdev->lock); mutex_init(&hdev->req_lock); + mutex_init(&hdev->mgmt_pending_lock); ida_init(&hdev->unset_handle_ida); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index feaeec2423ae8..de7adb9a47f97 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1447,22 +1447,17 @@ static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data) send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); - list_del(&cmd->list); - if (match->sk == NULL) { match->sk = cmd->sk; sock_hold(match->sk); } - - mgmt_pending_free(cmd); } static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data) { u8 *status = data; - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status); - mgmt_pending_remove(cmd); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, *status); } static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) @@ -1476,8 +1471,6 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) if (cmd->cmd_complete) { cmd->cmd_complete(cmd, match->mgmt_status); - mgmt_pending_remove(cmd); - return; } @@ -1486,13 +1479,13 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) { - return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, + return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, cmd->param, cmd->param_len); } static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) { - return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, + return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, cmd->param, sizeof(struct mgmt_addr_info)); } @@ -1532,7 +1525,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); goto done; } @@ -1707,7 +1700,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); goto done; } @@ -1943,8 +1936,8 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) new_settings(hdev, NULL); } - mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, - &mgmt_err); + mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, + cmd_status_rsp, &mgmt_err); return; } @@ -1954,7 +1947,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED); } - mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match); if (changed) new_settings(hdev, match.sk); @@ -2074,12 +2067,12 @@ static void set_le_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); if (status) { - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, - &status); + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp, + &status); return; } - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match); new_settings(hdev, match.sk); @@ -2138,7 +2131,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) struct sock *sk = cmd->sk; if (status) { - mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, + mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, cmd_status_rsp, &status); return; } @@ -2638,7 +2631,7 @@ static void mgmt_class_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), hdev->dev_class, 3); mgmt_pending_free(cmd); @@ -3427,7 +3420,7 @@ static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status) bacpy(&rp.addr.bdaddr, &conn->dst); rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); - err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, + err = mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_PAIR_DEVICE, status, &rp, sizeof(rp)); /* So we don't get further callbacks for this connection */ @@ -5186,7 +5179,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, hci_update_passive_scan(hdev); } - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(status), &rp, sizeof(rp)); mgmt_pending_remove(cmd); @@ -5401,7 +5394,7 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, hci_update_passive_scan(hdev); } - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(status), &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -5777,7 +5770,7 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev)) return; - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), cmd->param, 1); mgmt_pending_remove(cmd); @@ -5998,7 +5991,7 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), cmd->param, 1); mgmt_pending_remove(cmd); @@ -6223,7 +6216,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) u8 status = mgmt_status(err); if (status) { - mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, cmd_status_rsp, &status); return; } @@ -6233,7 +6226,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) else hci_dev_clear_flag(hdev, HCI_ADVERTISING); - mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp, &match); new_settings(hdev, match.sk); @@ -6577,7 +6570,7 @@ static void set_bredr_complete(struct hci_dev *hdev, void *data, int err) */ hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); } else { send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev); new_settings(hdev, cmd->sk); @@ -6714,7 +6707,7 @@ static void set_secure_conn_complete(struct hci_dev *hdev, void *data, int err) if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); goto done; } @@ -7161,7 +7154,7 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) rp.max_tx_power = HCI_TX_POWER_INVALID; } - mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -7321,7 +7314,7 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) } complete: - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -8571,10 +8564,10 @@ static void add_advertising_complete(struct hci_dev *hdev, void *data, int err) rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); add_adv_complete(hdev, cmd->sk, cp->instance, err); @@ -8762,10 +8755,10 @@ static void add_ext_adv_params_complete(struct hci_dev *hdev, void *data, hci_remove_adv_instance(hdev, cp->instance); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); } else { - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); } @@ -8912,10 +8905,10 @@ static void add_ext_adv_data_complete(struct hci_dev *hdev, void *data, int err) rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -9074,10 +9067,10 @@ static void remove_advertising_complete(struct hci_dev *hdev, void *data, rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -9349,7 +9342,7 @@ void mgmt_index_removed(struct hci_dev *hdev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) return; - mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); + mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, @@ -9387,7 +9380,8 @@ void mgmt_power_on(struct hci_dev *hdev, int err) hci_update_passive_scan(hdev); } - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, + &match); new_settings(hdev, match.sk); @@ -9402,7 +9396,8 @@ void __mgmt_power_off(struct hci_dev *hdev) struct cmd_lookup match = { NULL, hdev }; u8 zero_cod[] = { 0, 0, 0 }; - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, + &match); /* If the power off is because of hdev unregistration let * use the appropriate INVALID_INDEX status. Otherwise use @@ -9416,7 +9411,7 @@ void __mgmt_power_off(struct hci_dev *hdev) else match.mgmt_status = MGMT_STATUS_NOT_POWERED; - mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); + mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) { mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, @@ -9657,7 +9652,6 @@ static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data) device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk); cmd->cmd_complete(cmd, 0); - mgmt_pending_remove(cmd); } bool mgmt_powering_down(struct hci_dev *hdev) @@ -9713,8 +9707,8 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, struct mgmt_cp_disconnect *cp; struct mgmt_pending_cmd *cmd; - mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, - hdev); + mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, true, + unpair_device_rsp, hdev); cmd = pending_find(MGMT_OP_DISCONNECT, hdev); if (!cmd) @@ -9907,7 +9901,7 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) if (status) { u8 mgmt_err = mgmt_status(status); - mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, + mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, cmd_status_rsp, &mgmt_err); return; } @@ -9917,8 +9911,8 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) else changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY); - mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, - &match); + mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, + settings_rsp, &match); if (changed) new_settings(hdev, match.sk); @@ -9942,9 +9936,12 @@ void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, { struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; - mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); - mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); - mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); + mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, false, sk_lookup, + &match); + mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, false, sk_lookup, + &match); + mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, false, sk_lookup, + &match); if (!status) { mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, diff --git a/net/bluetooth/mgmt_util.c b/net/bluetooth/mgmt_util.c index 3713ff490c65d..a88a07da39473 100644 --- a/net/bluetooth/mgmt_util.c +++ b/net/bluetooth/mgmt_util.c @@ -217,30 +217,47 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, struct hci_dev *hdev) { - struct mgmt_pending_cmd *cmd; + struct mgmt_pending_cmd *cmd, *tmp; + + mutex_lock(&hdev->mgmt_pending_lock); - list_for_each_entry(cmd, &hdev->mgmt_pending, list) { + list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { if (hci_sock_get_channel(cmd->sk) != channel) continue; - if (cmd->opcode == opcode) + + if (cmd->opcode == opcode) { + mutex_unlock(&hdev->mgmt_pending_lock); return cmd; + } } + mutex_unlock(&hdev->mgmt_pending_lock); + return NULL; } -void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, +void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, void (*cb)(struct mgmt_pending_cmd *cmd, void *data), void *data) { struct mgmt_pending_cmd *cmd, *tmp; + mutex_lock(&hdev->mgmt_pending_lock); + list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { if (opcode > 0 && cmd->opcode != opcode) continue; + if (remove) + list_del(&cmd->list); + cb(cmd, data); + + if (remove) + mgmt_pending_free(cmd); } + + mutex_unlock(&hdev->mgmt_pending_lock); } struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, @@ -254,7 +271,7 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, return NULL; cmd->opcode = opcode; - cmd->index = hdev->id; + cmd->hdev = hdev; cmd->param = kmemdup(data, len, GFP_KERNEL); if (!cmd->param) { @@ -280,7 +297,9 @@ struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, if (!cmd) return NULL; + mutex_lock(&hdev->mgmt_pending_lock); list_add_tail(&cmd->list, &hdev->mgmt_pending); + mutex_unlock(&hdev->mgmt_pending_lock); return cmd; } @@ -294,7 +313,10 @@ void mgmt_pending_free(struct mgmt_pending_cmd *cmd) void mgmt_pending_remove(struct mgmt_pending_cmd *cmd) { + mutex_lock(&cmd->hdev->mgmt_pending_lock); list_del(&cmd->list); + mutex_unlock(&cmd->hdev->mgmt_pending_lock); + mgmt_pending_free(cmd); } diff --git a/net/bluetooth/mgmt_util.h b/net/bluetooth/mgmt_util.h index f2ba994ab1d84..024e51dd69375 100644 --- a/net/bluetooth/mgmt_util.h +++ b/net/bluetooth/mgmt_util.h @@ -33,7 +33,7 @@ struct mgmt_mesh_tx { struct mgmt_pending_cmd { struct list_head list; u16 opcode; - int index; + struct hci_dev *hdev; void *param; size_t param_len; struct sock *sk; @@ -54,7 +54,7 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, struct hci_dev *hdev); -void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, +void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, void (*cb)(struct mgmt_pending_cmd *cmd, void *data), void *data); struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, -- GitLab From 8d8431298f698c43405ed48867a22d8a4b96d4bf Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Thu, 5 Jun 2025 15:38:12 +0530 Subject: [PATCH 239/902] drm/xe/xe3: Disable null query for anyhit shader Set DIS_NULL_QUERY bit of RT_CTRL register to disable null query for anyhit shader for Xe3 IP. Reviewed-by: Gustavo Sousa Reviewed-by: Tejas Upadhyay Reviewed-by: Matt Roper Signed-off-by: Nitin Gote Link: https://lore.kernel.org/r/20250605100812.2547808-1-nitin.r.gote@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_tuning.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index 49ddbda7cdef6..828b45b24c23a 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -98,6 +98,11 @@ static const struct xe_rtp_entry_sr engine_tunings[] = { ENGINE_CLASS(RENDER)), XE_RTP_ACTIONS(SET(SAMPLER_MODE, INDIRECT_STATE_BASE_ADDR_OVERRIDE)) }, + { XE_RTP_NAME("Tuning: Disable NULL query for Anyhit Shader"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, XE_RTP_END_VERSION_UNDEFINED), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(RT_CTRL, DIS_NULL_QUERY)) + }, }; static const struct xe_rtp_entry_sr lrc_tunings[] = { -- GitLab From 692eb9f8a5b71d852e873375d20cf5da7a046ea6 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 2 Jun 2025 21:49:14 +0200 Subject: [PATCH 240/902] net: dsa: b53: fix untagged traffic sent via cpu tagged with VID 0 When Linux sends out untagged traffic from a port, it will enter the CPU port without any VLAN tag, even if the port is a member of a vlan filtering bridge with a PVID egress untagged VLAN. This makes the CPU port's PVID take effect, and the PVID's VLAN table entry controls if the packet will be tagged on egress. Since commit 45e9d59d3950 ("net: dsa: b53: do not allow to configure VLAN 0") we remove bridged ports from VLAN 0 when joining or leaving a VLAN aware bridge. But we also clear the untagged bit, causing untagged traffic from the controller to become tagged with VID 0 (and priority 0). Fix this by not touching the untagged map of VLAN 0. Additionally, always keep the CPU port as a member, as the untag map is only effective as long as there is at least one member, and we would remove it when bridging all ports and leaving no standalone ports. Since Linux (and the switch) treats VLAN 0 tagged traffic like untagged, the actual impact of this is rather low, but this also prevented earlier detection of the issue. Fixes: 45e9d59d3950 ("net: dsa: b53: do not allow to configure VLAN 0") Signed-off-by: Jonas Gorski Reviewed-by: Florian Fainelli Reviewed-by: Vladimir Oltean Link: https://patch.msgid.link/20250602194914.1011890-1-jonas.gorski@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_common.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 862bdccb74397..dc2f4adac9bc9 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -2034,9 +2034,6 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, b53_get_vlan_entry(dev, pvid, vl); vl->members &= ~BIT(port); - if (vl->members == BIT(cpu_port)) - vl->members &= ~BIT(cpu_port); - vl->untag = vl->members; b53_set_vlan_entry(dev, pvid, vl); } @@ -2115,8 +2112,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge) } b53_get_vlan_entry(dev, pvid, vl); - vl->members |= BIT(port) | BIT(cpu_port); - vl->untag |= BIT(port) | BIT(cpu_port); + vl->members |= BIT(port); b53_set_vlan_entry(dev, pvid, vl); } } -- GitLab From 87f7ce260a3c838b49e1dc1ceedf1006795157a2 Mon Sep 17 00:00:00 2001 From: Jeongjun Park Date: Wed, 21 May 2025 01:07:17 +0900 Subject: [PATCH 241/902] ptp: remove ptp->n_vclocks check logic in ptp_vclock_in_use() There is no disagreement that we should check both ptp->is_virtual_clock and ptp->n_vclocks to check if the ptp virtual clock is in use. However, when we acquire ptp->n_vclocks_mux to read ptp->n_vclocks in ptp_vclock_in_use(), we observe a recursive lock in the call trace starting from n_vclocks_store(). ============================================ WARNING: possible recursive locking detected 6.15.0-rc6 #1 Not tainted -------------------------------------------- syz.0.1540/13807 is trying to acquire lock: ffff888035a24868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at: ptp_vclock_in_use drivers/ptp/ptp_private.h:103 [inline] ffff888035a24868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at: ptp_clock_unregister+0x21/0x250 drivers/ptp/ptp_clock.c:415 but task is already holding lock: ffff888030704868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at: n_vclocks_store+0xf1/0x6d0 drivers/ptp/ptp_sysfs.c:215 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&ptp->n_vclocks_mux); lock(&ptp->n_vclocks_mux); *** DEADLOCK *** .... ============================================ The best way to solve this is to remove the logic that checks ptp->n_vclocks in ptp_vclock_in_use(). The reason why this is appropriate is that any path that uses ptp->n_vclocks must unconditionally check if ptp->n_vclocks is greater than 0 before unregistering vclocks, and all functions are already written this way. And in the function that uses ptp->n_vclocks, we already get ptp->n_vclocks_mux before unregistering vclocks. Therefore, we need to remove the redundant check for ptp->n_vclocks in ptp_vclock_in_use() to prevent recursive locking. Fixes: 73f37068d540 ("ptp: support ptp physical/virtual clocks conversion") Signed-off-by: Jeongjun Park Acked-by: Richard Cochran Link: https://patch.msgid.link/20250520160717.7350-1-aha310510@gmail.com Signed-off-by: Jakub Kicinski --- drivers/ptp/ptp_private.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index 18934e28469ee..528d86a33f37d 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -98,17 +98,7 @@ static inline int queue_cnt(const struct timestamp_event_queue *q) /* Check if ptp virtual clock is in use */ static inline bool ptp_vclock_in_use(struct ptp_clock *ptp) { - bool in_use = false; - - if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) - return true; - - if (!ptp->is_virtual_clock && ptp->n_vclocks) - in_use = true; - - mutex_unlock(&ptp->n_vclocks_mux); - - return in_use; + return !ptp->is_virtual_clock; } /* Check if ptp clock shall be free running */ -- GitLab From 82cbd06f327f3c2ccdee990bd356c9303ae168f9 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Thu, 5 Jun 2025 14:08:36 +0800 Subject: [PATCH 242/902] net: enetc: fix the netc-lib driver build dependency The kernel robot reported the following errors when the netc-lib driver was compiled as a loadable module and the enetc-core driver was built-in. ld.lld: error: undefined symbol: ntmp_init_cbdr referenced by enetc_cbdr.c:88 (drivers/net/ethernet/freescale/enetc/enetc_cbdr.c:88) ld.lld: error: undefined symbol: ntmp_free_cbdr referenced by enetc_cbdr.c:96 (drivers/net/ethernet/freescale/enetc/enetc_cbdr.c:96) Simply changing "tristate" to "bool" can fix this issue, but considering that the netc-lib driver needs to support being compiled as a loadable module and LS1028 does not need the netc-lib driver. Therefore, we add a boolean symbol 'NXP_NTMP' to enable 'NXP_NETC_LIB' as needed. And when adding NETC switch driver support in the future, there is no need to modify the dependency, just select "NXP_NTMP" and "NXP_NETC_LIB" at the same time. Reported-by: Arnd Bergmann Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202505220734.x6TF6oHR-lkp@intel.com/ Fixes: 4701073c3deb ("net: enetc: add initial netc-lib driver to support NTMP") Suggested-by: Arnd Bergmann Signed-off-by: Wei Fang Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index e917132d37149..54b0f0a5a6bb1 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config FSL_ENETC_CORE tristate + select NXP_NETC_LIB if NXP_NTMP help This module supports common functionality between the PF and VF drivers for the NXP ENETC controller. @@ -22,6 +23,9 @@ config NXP_NETC_LIB Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc flower and debugfs interfaces and so on. +config NXP_NTMP + bool + config FSL_ENETC tristate "ENETC PF driver" depends on PCI_MSI @@ -45,7 +49,7 @@ config NXP_ENETC4 select FSL_ENETC_CORE select FSL_ENETC_MDIO select NXP_ENETC_PF_COMMON - select NXP_NETC_LIB + select NXP_NTMP select PHYLINK select DIMLIB help -- GitLab From 11fcf368506d347088e613edf6cd2604d70c454f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 6 Jun 2025 10:23:57 +0200 Subject: [PATCH 243/902] uapi: bitops: use UAPI-safe variant of BITS_PER_LONG again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1e7933a575ed ("uapi: Revert "bitops: avoid integer overflow in GENMASK(_ULL)"") did not take in account that the usage of BITS_PER_LONG in __GENMASK() was changed to __BITS_PER_LONG for UAPI-safety in commit 3c7a8e190bc5 ("uapi: introduce uapi-friendly macros for GENMASK"). BITS_PER_LONG can not be used in UAPI headers as it derives from the kernel configuration and not from the current compiler invocation. When building compat userspace code or a compat vDSO its value will be incorrect. Switch back to __BITS_PER_LONG. Fixes: 1e7933a575ed ("uapi: Revert "bitops: avoid integer overflow in GENMASK(_ULL)"") Cc: stable@vger.kernel.org Signed-off-by: Thomas Weißschuh Signed-off-by: Yury Norov [NVIDIA] --- include/uapi/linux/bits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/bits.h b/include/uapi/linux/bits.h index 682b406e10679..a04afef9efca4 100644 --- a/include/uapi/linux/bits.h +++ b/include/uapi/linux/bits.h @@ -4,9 +4,9 @@ #ifndef _UAPI_LINUX_BITS_H #define _UAPI_LINUX_BITS_H -#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (BITS_PER_LONG - 1 - (h)))) +#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (__BITS_PER_LONG - 1 - (h)))) -#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) +#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (__BITS_PER_LONG_LONG - 1 - (h)))) #define __GENMASK_U128(h, l) \ ((_BIT128((h)) << 1) - (_BIT128(l))) -- GitLab From 10a2bc580796c0b3162e9be1445c03c3ce49a2d1 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 3 Jun 2025 16:54:34 -0700 Subject: [PATCH 244/902] drm/xe/uc: Prepare uc_fw_version for storing the VF ABI version The VF ABI version has a branch field, so to store it inside the uc_fw_version we need to add a new branch variable to the latter. Existing code needs to be updated to handle the fact that we have the new field. v2: split out to its own patch (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250603235432.720833-7-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_guc_engine_activity.c | 2 +- drivers/gpu/drm/xe/xe_uc_fw_types.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_engine_activity.c b/drivers/gpu/drm/xe/xe_guc_engine_activity.c index 0fb48f8f05d84..92e1f9f41b8c5 100644 --- a/drivers/gpu/drm/xe/xe_guc_engine_activity.c +++ b/drivers/gpu/drm/xe/xe_guc_engine_activity.c @@ -124,7 +124,7 @@ static void free_engine_activity_buffers(struct engine_activity_buffer *buffer) static bool is_engine_activity_supported(struct xe_guc *guc) { struct xe_uc_fw_version *version = &guc->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY]; - struct xe_uc_fw_version required = { 1, 14, 1 }; + struct xe_uc_fw_version required = { .major = 1, .minor = 14, .patch = 1 }; struct xe_gt *gt = guc_to_gt(guc); if (IS_SRIOV_VF(gt_to_xe(gt))) { diff --git a/drivers/gpu/drm/xe/xe_uc_fw_types.h b/drivers/gpu/drm/xe/xe_uc_fw_types.h index ad3b35a0e6ebc..9140260150195 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw_types.h +++ b/drivers/gpu/drm/xe/xe_uc_fw_types.h @@ -65,6 +65,8 @@ enum xe_uc_fw_type { * struct xe_uc_fw_version - Version for XE micro controller firmware */ struct xe_uc_fw_version { + /** @branch: branch version of the FW (not always available) */ + u16 branch; /** @major: major version of the FW */ u16 major; /** @minor: minor version of the FW */ -- GitLab From 90f4d3f7562a3ce5a5706a4753a0b7b292dc7ec3 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 3 Jun 2025 16:54:35 -0700 Subject: [PATCH 245/902] drm/xe/vf: Boostrap all GTs immediately after MMIO init Currently we perform the bootstrap for the primary GT early on during device init, while the media GT bootstrap happens when we try and fetch the hwconfig table. For consistency, move the bootstrap of the media GT happen at the same time as the primary GT, so that all the subsequent code can rely on both GTs being in the same state. v2: Also drop config query from min_guc_load since we now do it early (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250603235432.720833-8-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_device.c | 11 ++++++----- drivers/gpu/drm/xe/xe_guc.c | 8 -------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index d4b6e623aa48b..7d9a31868ea99 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -802,18 +802,19 @@ int xe_device_probe(struct xe_device *xe) * be performed. */ xe_gt_mmio_init(gt); - } - for_each_tile(tile, xe, id) { if (IS_SRIOV_VF(xe)) { - xe_guc_comm_init_early(&tile->primary_gt->uc.guc); - err = xe_gt_sriov_vf_bootstrap(tile->primary_gt); + xe_guc_comm_init_early(>->uc.guc); + err = xe_gt_sriov_vf_bootstrap(gt); if (err) return err; - err = xe_gt_sriov_vf_query_config(tile->primary_gt); + err = xe_gt_sriov_vf_query_config(gt); if (err) return err; } + } + + for_each_tile(tile, xe, id) { err = xe_ggtt_init_early(tile->mem.ggtt); if (err) return err; diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index 52453845d1bd3..209e5d53c290c 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -1102,14 +1102,6 @@ static int vf_guc_min_load_for_hwconfig(struct xe_guc *guc) struct xe_gt *gt = guc_to_gt(guc); int ret; - ret = xe_gt_sriov_vf_bootstrap(gt); - if (ret) - return ret; - - ret = xe_gt_sriov_vf_query_config(gt); - if (ret) - return ret; - ret = xe_guc_hwconfig_init(guc); if (ret) return ret; -- GitLab From 3ef462f0031f745ce5a98394b7134499c37ef11d Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 3 Jun 2025 16:54:36 -0700 Subject: [PATCH 246/902] drm/xe/vf: Use uc_fw_version to store the negotiated GuC ABI Instead of using a VF-specific type, we can use the common uc_fw_version structure. This also means that we can use the available macros to compare ABI versions. While at it, exit early from the bootstrap if this is not the first time we're doing it and the version hasn't changed, so we don't end up logging it multiple times. Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Lukasz Laguna Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250603235432.720833-9-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 137 ++++++++++++---------- drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h | 17 +-- 2 files changed, 78 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 792523cfa6e67..632ae6b33d3d8 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -82,17 +82,17 @@ int xe_gt_sriov_vf_reset(struct xe_gt *gt) } static int guc_action_match_version(struct xe_guc *guc, - u32 wanted_branch, u32 wanted_major, u32 wanted_minor, - u32 *branch, u32 *major, u32 *minor, u32 *patch) + struct xe_uc_fw_version *wanted, + struct xe_uc_fw_version *found) { u32 request[VF2GUC_MATCH_VERSION_REQUEST_MSG_LEN] = { FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_MATCH_VERSION), - FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_BRANCH, wanted_branch) | - FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MAJOR, wanted_major) | - FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MINOR, wanted_minor), + FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_BRANCH, wanted->branch) | + FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MAJOR, wanted->major) | + FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MINOR, wanted->minor), }; u32 response[GUC_MAX_MMIO_MSG_LEN]; int ret; @@ -106,120 +106,135 @@ static int guc_action_match_version(struct xe_guc *guc, if (unlikely(FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_0_MBZ, response[0]))) return -EPROTO; - *branch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_BRANCH, response[1]); - *major = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MAJOR, response[1]); - *minor = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MINOR, response[1]); - *patch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_PATCH, response[1]); + memset(found, 0, sizeof(struct xe_uc_fw_version)); + found->branch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_BRANCH, response[1]); + found->major = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MAJOR, response[1]); + found->minor = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MINOR, response[1]); + found->patch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_PATCH, response[1]); return 0; } -static void vf_minimum_guc_version(struct xe_gt *gt, u32 *branch, u32 *major, u32 *minor) +static int guc_action_match_version_any(struct xe_guc *guc, + struct xe_uc_fw_version *found) +{ + struct xe_uc_fw_version wanted = { + .branch = GUC_VERSION_BRANCH_ANY, + .major = GUC_VERSION_MAJOR_ANY, + .minor = GUC_VERSION_MINOR_ANY, + .patch = 0 + }; + + return guc_action_match_version(guc, &wanted, found); +} + +static void vf_minimum_guc_version(struct xe_gt *gt, struct xe_uc_fw_version *ver) { struct xe_device *xe = gt_to_xe(gt); + memset(ver, 0, sizeof(struct xe_uc_fw_version)); + switch (xe->info.platform) { case XE_TIGERLAKE ... XE_PVC: /* 1.1 this is current baseline for Xe driver */ - *branch = 0; - *major = 1; - *minor = 1; + ver->branch = 0; + ver->major = 1; + ver->minor = 1; break; default: /* 1.2 has support for the GMD_ID KLV */ - *branch = 0; - *major = 1; - *minor = 2; + ver->branch = 0; + ver->major = 1; + ver->minor = 2; break; } } -static void vf_wanted_guc_version(struct xe_gt *gt, u32 *branch, u32 *major, u32 *minor) +static void vf_wanted_guc_version(struct xe_gt *gt, struct xe_uc_fw_version *ver) { /* for now it's the same as minimum */ - return vf_minimum_guc_version(gt, branch, major, minor); + return vf_minimum_guc_version(gt, ver); } static int vf_handshake_with_guc(struct xe_gt *gt) { - struct xe_gt_sriov_vf_guc_version *guc_version = >->sriov.vf.guc_version; + struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; + struct xe_uc_fw_version wanted = {0}; struct xe_guc *guc = >->uc.guc; - u32 wanted_branch, wanted_major, wanted_minor; - u32 branch, major, minor, patch; + bool old = false; int err; xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); /* select wanted version - prefer previous (if any) */ if (guc_version->major || guc_version->minor) { - wanted_branch = guc_version->branch; - wanted_major = guc_version->major; - wanted_minor = guc_version->minor; + wanted = *guc_version; + old = true; } else { - vf_wanted_guc_version(gt, &wanted_branch, &wanted_major, &wanted_minor); - xe_gt_assert(gt, wanted_major != GUC_VERSION_MAJOR_ANY); + vf_wanted_guc_version(gt, &wanted); + xe_gt_assert(gt, wanted.major != GUC_VERSION_MAJOR_ANY); } - err = guc_action_match_version(guc, wanted_branch, wanted_major, wanted_minor, - &branch, &major, &minor, &patch); + err = guc_action_match_version(guc, &wanted, guc_version); if (unlikely(err)) goto fail; - /* we don't support interface version change */ - if ((guc_version->major || guc_version->minor) && - (guc_version->branch != branch || guc_version->major != major || - guc_version->minor != minor)) { - xe_gt_sriov_err(gt, "New GuC interface version detected: %u.%u.%u.%u\n", - branch, major, minor, patch); - xe_gt_sriov_info(gt, "Previously used version was: %u.%u.%u.%u\n", - guc_version->branch, guc_version->major, - guc_version->minor, guc_version->patch); - err = -EREMCHG; - goto fail; + if (old) { + /* we don't support interface version change */ + if (MAKE_GUC_VER_STRUCT(*guc_version) != MAKE_GUC_VER_STRUCT(wanted)) { + xe_gt_sriov_err(gt, "New GuC interface version detected: %u.%u.%u.%u\n", + guc_version->branch, guc_version->major, + guc_version->minor, guc_version->patch); + xe_gt_sriov_info(gt, "Previously used version was: %u.%u.%u.%u\n", + wanted.branch, wanted.major, + wanted.minor, wanted.patch); + err = -EREMCHG; + goto fail; + } else { + /* version is unchanged, no need to re-verify it */ + return 0; + } } /* illegal */ - if (major > wanted_major) { + if (guc_version->major > wanted.major) { err = -EPROTO; goto unsupported; } /* there's no fallback on major version. */ - if (major != wanted_major) { + if (guc_version->major != wanted.major) { err = -ENOPKG; goto unsupported; } /* check against minimum version supported by us */ - vf_minimum_guc_version(gt, &wanted_branch, &wanted_major, &wanted_minor); - xe_gt_assert(gt, major != GUC_VERSION_MAJOR_ANY); - if (major < wanted_major || (major == wanted_major && minor < wanted_minor)) { + vf_minimum_guc_version(gt, &wanted); + xe_gt_assert(gt, wanted.major != GUC_VERSION_MAJOR_ANY); + if (MAKE_GUC_VER_STRUCT(*guc_version) < MAKE_GUC_VER_STRUCT(wanted)) { err = -ENOKEY; goto unsupported; } xe_gt_sriov_dbg(gt, "using GuC interface version %u.%u.%u.%u\n", - branch, major, minor, patch); + guc_version->branch, guc_version->major, + guc_version->minor, guc_version->patch); - guc_version->branch = branch; - guc_version->major = major; - guc_version->minor = minor; - guc_version->patch = patch; return 0; unsupported: xe_gt_sriov_err(gt, "Unsupported GuC version %u.%u.%u.%u (%pe)\n", - branch, major, minor, patch, ERR_PTR(err)); + guc_version->branch, guc_version->major, + guc_version->minor, guc_version->patch, + ERR_PTR(err)); fail: xe_gt_sriov_err(gt, "Unable to confirm GuC version %u.%u (%pe)\n", - wanted_major, wanted_minor, ERR_PTR(err)); + wanted.major, wanted.minor, ERR_PTR(err)); /* try again with *any* just to query which version is supported */ - if (!guc_action_match_version(guc, GUC_VERSION_BRANCH_ANY, - GUC_VERSION_MAJOR_ANY, GUC_VERSION_MINOR_ANY, - &branch, &major, &minor, &patch)) + if (!guc_action_match_version_any(guc, &wanted)) xe_gt_sriov_notice(gt, "GuC reports interface version %u.%u.%u.%u\n", - branch, major, minor, patch); + wanted.branch, wanted.major, wanted.minor, wanted.patch); return err; } @@ -1032,19 +1047,19 @@ void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) */ void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) { - struct xe_gt_sriov_vf_guc_version *guc_version = >->sriov.vf.guc_version; + struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; struct xe_gt_sriov_vf_relay_version *pf_version = >->sriov.vf.pf_version; - u32 branch, major, minor; + struct xe_uc_fw_version ver; xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); drm_printf(p, "GuC ABI:\n"); - vf_minimum_guc_version(gt, &branch, &major, &minor); - drm_printf(p, "\tbase:\t%u.%u.%u.*\n", branch, major, minor); + vf_minimum_guc_version(gt, &ver); + drm_printf(p, "\tbase:\t%u.%u.%u.*\n", ver.branch, ver.major, ver.minor); - vf_wanted_guc_version(gt, &branch, &major, &minor); - drm_printf(p, "\twanted:\t%u.%u.%u.*\n", branch, major, minor); + vf_wanted_guc_version(gt, &ver); + drm_printf(p, "\twanted:\t%u.%u.%u.*\n", ver.branch, ver.major, ver.minor); drm_printf(p, "\thandshake:\t%u.%u.%u.%u\n", guc_version->branch, guc_version->major, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h index 5ccbdf8d08b64..d614acbe0b5f0 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h @@ -7,20 +7,7 @@ #define _XE_GT_SRIOV_VF_TYPES_H_ #include - -/** - * struct xe_gt_sriov_vf_guc_version - GuC ABI version details. - */ -struct xe_gt_sriov_vf_guc_version { - /** @branch: branch version. */ - u8 branch; - /** @major: major version. */ - u8 major; - /** @minor: minor version. */ - u8 minor; - /** @patch: patch version. */ - u8 patch; -}; +#include "xe_uc_fw_types.h" /** * struct xe_gt_sriov_vf_relay_version - PF ABI version details. @@ -74,7 +61,7 @@ struct xe_gt_sriov_vf_runtime { */ struct xe_gt_sriov_vf { /** @guc_version: negotiated GuC ABI version. */ - struct xe_gt_sriov_vf_guc_version guc_version; + struct xe_uc_fw_version guc_version; /** @self_config: resource configurations. */ struct xe_gt_sriov_vf_selfconfig self_config; /** @pf_version: negotiated VF/PF ABI version. */ -- GitLab From ade147391433f516532d0a6ba7e49a775cb3694f Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 3 Jun 2025 16:54:37 -0700 Subject: [PATCH 247/902] drm/xe/vf: Store the GuC FW info in guc->fw The GuC compatibility version that we read from the CSS header in native/PF and the GuC VF version that we get when a VF handshakes with the GuC are the same version number, so we should store it into the same structure. This makes all the checks based on the compatibility version automatically work for VFs without having to copy the value over. For completion, also copy the wanted version and set the path to a known string to indicate that the FW is PF-loaded. This way all the info will be coherent when dumped from debugfs. v2: several code cleanups and style changes (Michal), rebase on bootstrap changes. v3: s/min/wanted/, clarify that handshake must happen before we can get the VF versions (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Lukasz Laguna Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250603235432.720833-10-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 31 +++++++++++++++++-- drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 4 +++ drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h | 2 ++ drivers/gpu/drm/xe/xe_uc_fw.c | 37 ++++++++++++++++++----- 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 632ae6b33d3d8..9b2fc9db55b8c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -173,6 +173,9 @@ static int vf_handshake_with_guc(struct xe_gt *gt) } else { vf_wanted_guc_version(gt, &wanted); xe_gt_assert(gt, wanted.major != GUC_VERSION_MAJOR_ANY); + + /* First time we handshake, so record the minimum wanted */ + gt->sriov.vf.wanted_guc_version = wanted; } err = guc_action_match_version(guc, &wanted, guc_version); @@ -265,6 +268,29 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) return 0; } +/** + * xe_gt_sriov_vf_guc_versions - Minimum required and found GuC ABI versions + * @gt: the &xe_gt + * @wanted: pointer to the xe_uc_fw_version to be filled with the wanted version + * @found: pointer to the xe_uc_fw_version to be filled with the found version + * + * This function is for VF use only and it can only be used after successful + * version handshake with the GuC. + */ +void xe_gt_sriov_vf_guc_versions(struct xe_gt *gt, + struct xe_uc_fw_version *wanted, + struct xe_uc_fw_version *found) +{ + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, gt->sriov.vf.guc_version.major); + + if (wanted) + *wanted = gt->sriov.vf.wanted_guc_version; + + if (found) + *found = gt->sriov.vf.guc_version; +} + static int guc_action_vf_notify_resfix_done(struct xe_guc *guc) { u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = { @@ -1048,6 +1074,7 @@ void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) { struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; + struct xe_uc_fw_version *wanted = >->sriov.vf.wanted_guc_version; struct xe_gt_sriov_vf_relay_version *pf_version = >->sriov.vf.pf_version; struct xe_uc_fw_version ver; @@ -1058,8 +1085,8 @@ void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) vf_minimum_guc_version(gt, &ver); drm_printf(p, "\tbase:\t%u.%u.%u.*\n", ver.branch, ver.major, ver.minor); - vf_wanted_guc_version(gt, &ver); - drm_printf(p, "\twanted:\t%u.%u.%u.*\n", ver.branch, ver.major, ver.minor); + drm_printf(p, "\twanted:\t%u.%u.%u.*\n", + wanted->branch, wanted->major, wanted->minor); drm_printf(p, "\thandshake:\t%u.%u.%u.%u\n", guc_version->branch, guc_version->major, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index 6250fe774d89a..e0357f341a2d8 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -11,9 +11,13 @@ struct drm_printer; struct xe_gt; struct xe_reg; +struct xe_uc_fw_version; int xe_gt_sriov_vf_reset(struct xe_gt *gt); int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt); +void xe_gt_sriov_vf_guc_versions(struct xe_gt *gt, + struct xe_uc_fw_version *wanted, + struct xe_uc_fw_version *found); int xe_gt_sriov_vf_query_config(struct xe_gt *gt); int xe_gt_sriov_vf_connect(struct xe_gt *gt); int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h index d614acbe0b5f0..ef041679e9d4c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h @@ -60,6 +60,8 @@ struct xe_gt_sriov_vf_runtime { * struct xe_gt_sriov_vf - GT level VF virtualization data. */ struct xe_gt_sriov_vf { + /** @wanted_guc_version: minimum wanted GuC ABI version. */ + struct xe_uc_fw_version wanted_guc_version; /** @guc_version: negotiated GuC ABI version. */ struct xe_uc_fw_version guc_version; /** @self_config: resource configurations. */ diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c index 2741849bbf4df..e572563b8c75e 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.c +++ b/drivers/gpu/drm/xe/xe_uc_fw.c @@ -16,6 +16,7 @@ #include "xe_gsc.h" #include "xe_gt.h" #include "xe_gt_printk.h" +#include "xe_gt_sriov_vf.h" #include "xe_guc.h" #include "xe_map.h" #include "xe_mmio.h" @@ -662,6 +663,33 @@ do { \ ver_->major, ver_->minor, ver_->patch); \ } while (0) +static void uc_fw_vf_override(struct xe_uc_fw *uc_fw) +{ + struct xe_uc_fw_version *compat = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY]; + struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted; + + /* Only GuC/HuC are supported */ + if (uc_fw->type != XE_UC_FW_TYPE_GUC && uc_fw->type != XE_UC_FW_TYPE_HUC) + uc_fw->path = NULL; + + /* VF will support only firmwares that driver can autoselect */ + xe_uc_fw_change_status(uc_fw, uc_fw->path ? + XE_UC_FIRMWARE_PRELOADED : + XE_UC_FIRMWARE_NOT_SUPPORTED); + + if (!xe_uc_fw_is_supported(uc_fw)) + return; + + /* PF is doing the loading, so we don't need a path on the VF */ + uc_fw->path = "Loaded by PF"; + + /* The GuC versions are set up during the VF bootstrap */ + if (uc_fw->type == XE_UC_FW_TYPE_GUC) { + uc_fw->versions.wanted_type = XE_UC_FW_VER_COMPATIBILITY; + xe_gt_sriov_vf_guc_versions(uc_fw_to_gt(uc_fw), wanted, compat); + } +} + static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmware_p) { struct xe_device *xe = uc_fw_to_xe(uc_fw); @@ -681,14 +709,7 @@ static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmwar uc_fw_auto_select(xe, uc_fw); if (IS_SRIOV_VF(xe)) { - /* Only GuC/HuC are supported */ - if (uc_fw->type != XE_UC_FW_TYPE_GUC && - uc_fw->type != XE_UC_FW_TYPE_HUC) - uc_fw->path = NULL; - /* VF will support only firmwares that driver can autoselect */ - xe_uc_fw_change_status(uc_fw, uc_fw->path ? - XE_UC_FIRMWARE_PRELOADED : - XE_UC_FIRMWARE_NOT_SUPPORTED); + uc_fw_vf_override(uc_fw); return 0; } -- GitLab From c0f691388992c708436ab5f6e810865be6ddf5c6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 5 Jun 2025 17:04:11 +0200 Subject: [PATCH 248/902] intel_idle: Use subsys_initcall_sync() for initialization It is not necessary to wait until the device_initcall() stage with intel_idle initialization. All of its dependencies are met after all subsys_initcall()s have run, so subsys_initcall_sync() can be used for initializing it. It is also better to ensure that intel_idle will always initialize before the ACPI processor driver that uses module_init() for its initialization. Signed-off-by: Rafael J. Wysocki Tested-by: Artem Bityutskiy Link: https://patch.msgid.link/2994397.e9J7NaK4W3@rjwysocki.net --- drivers/idle/intel_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 8ccb483204fa4..64ac4da080940 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -2518,7 +2518,7 @@ init_driver_fail: return retval; } -device_initcall(intel_idle_init); +subsys_initcall_sync(intel_idle_init); /* * We are not really modular, but we used to support that. Meaning we also -- GitLab From 678bb4d6254895fbb1cb30d62871cb58c92dd95b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2025 16:21:02 +1000 Subject: [PATCH 249/902] drm/xe: don't store the xe device pointer inside xe_ttm_tt This device pointer is nearly always available without storing an extra copy for each tt in the system. Just noticed this while reading over the xe shrinker code. Signed-off-by: Dave Airlie Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://lore.kernel.org/r/20250605062103.1234620-1-airlied@gmail.com --- drivers/gpu/drm/xe/tests/xe_bo.c | 4 +-- drivers/gpu/drm/xe/xe_bo.c | 59 ++++++++++++++++---------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 378dcd0fb4149..77ca1ab527ec9 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -514,9 +514,9 @@ static int shrink_test_run_device(struct xe_device *xe) * other way around, they may not be subject to swapping... */ if (alloced < purgeable) { - xe_ttm_tt_account_subtract(&xe_tt->ttm); + xe_ttm_tt_account_subtract(xe, &xe_tt->ttm); xe_tt->purgeable = true; - xe_ttm_tt_account_add(&xe_tt->ttm); + xe_ttm_tt_account_add(xe, &xe_tt->ttm); bo->ttm.priority = 0; spin_lock(&bo->ttm.bdev->lru_lock); ttm_bo_move_to_lru_tail(&bo->ttm); diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 61d208c852814..f35a7786a56fb 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -336,15 +336,13 @@ static void xe_evict_flags(struct ttm_buffer_object *tbo, /* struct xe_ttm_tt - Subclassed ttm_tt for xe */ struct xe_ttm_tt { struct ttm_tt ttm; - /** @xe - The xe device */ - struct xe_device *xe; struct sg_table sgt; struct sg_table *sg; /** @purgeable: Whether the content of the pages of @ttm is purgeable. */ bool purgeable; }; -static int xe_tt_map_sg(struct ttm_tt *tt) +static int xe_tt_map_sg(struct xe_device *xe, struct ttm_tt *tt) { struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm); unsigned long num_pages = tt->num_pages; @@ -359,13 +357,13 @@ static int xe_tt_map_sg(struct ttm_tt *tt) ret = sg_alloc_table_from_pages_segment(&xe_tt->sgt, tt->pages, num_pages, 0, (u64)num_pages << PAGE_SHIFT, - xe_sg_segment_size(xe_tt->xe->drm.dev), + xe_sg_segment_size(xe->drm.dev), GFP_KERNEL); if (ret) return ret; xe_tt->sg = &xe_tt->sgt; - ret = dma_map_sgtable(xe_tt->xe->drm.dev, xe_tt->sg, DMA_BIDIRECTIONAL, + ret = dma_map_sgtable(xe->drm.dev, xe_tt->sg, DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); if (ret) { sg_free_table(xe_tt->sg); @@ -376,12 +374,12 @@ static int xe_tt_map_sg(struct ttm_tt *tt) return 0; } -static void xe_tt_unmap_sg(struct ttm_tt *tt) +static void xe_tt_unmap_sg(struct xe_device *xe, struct ttm_tt *tt) { struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm); if (xe_tt->sg) { - dma_unmap_sgtable(xe_tt->xe->drm.dev, xe_tt->sg, + dma_unmap_sgtable(xe->drm.dev, xe_tt->sg, DMA_BIDIRECTIONAL, 0); sg_free_table(xe_tt->sg); xe_tt->sg = NULL; @@ -400,24 +398,24 @@ struct sg_table *xe_bo_sg(struct xe_bo *bo) * Account ttm pages against the device shrinker's shrinkable and * purgeable counts. */ -static void xe_ttm_tt_account_add(struct ttm_tt *tt) +static void xe_ttm_tt_account_add(struct xe_device *xe, struct ttm_tt *tt) { struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm); if (xe_tt->purgeable) - xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, 0, tt->num_pages); + xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages); else - xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, tt->num_pages, 0); + xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0); } -static void xe_ttm_tt_account_subtract(struct ttm_tt *tt) +static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt) { struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm); if (xe_tt->purgeable) - xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, 0, -(long)tt->num_pages); + xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages); else - xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, -(long)tt->num_pages, 0); + xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0); } static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, @@ -436,7 +434,6 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, return NULL; tt = &xe_tt->ttm; - xe_tt->xe = xe; extra_pages = 0; if (xe_bo_needs_ccs_pages(bo)) @@ -527,21 +524,23 @@ static int xe_ttm_tt_populate(struct ttm_device *ttm_dev, struct ttm_tt *tt, return err; xe_tt->purgeable = false; - xe_ttm_tt_account_add(tt); + xe_ttm_tt_account_add(ttm_to_xe_device(ttm_dev), tt); return 0; } static void xe_ttm_tt_unpopulate(struct ttm_device *ttm_dev, struct ttm_tt *tt) { + struct xe_device *xe = ttm_to_xe_device(ttm_dev); + if ((tt->page_flags & TTM_TT_FLAG_EXTERNAL) && !(tt->page_flags & TTM_TT_FLAG_EXTERNAL_MAPPABLE)) return; - xe_tt_unmap_sg(tt); + xe_tt_unmap_sg(xe, tt); ttm_pool_free(&ttm_dev->pool, tt); - xe_ttm_tt_account_subtract(tt); + xe_ttm_tt_account_subtract(xe, tt); } static void xe_ttm_tt_destroy(struct ttm_device *ttm_dev, struct ttm_tt *tt) @@ -789,7 +788,7 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, /* Bo creation path, moving to system or TT. */ if ((!old_mem && ttm) && !handle_system_ccs) { if (new_mem->mem_type == XE_PL_TT) - ret = xe_tt_map_sg(ttm); + ret = xe_tt_map_sg(xe, ttm); if (!ret) ttm_bo_move_null(ttm_bo, new_mem); goto out; @@ -812,7 +811,7 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, (!ttm && ttm_bo->type == ttm_bo_type_device); if (new_mem->mem_type == XE_PL_TT) { - ret = xe_tt_map_sg(ttm); + ret = xe_tt_map_sg(xe, ttm); if (ret) goto out; } @@ -958,7 +957,7 @@ out: if (timeout < 0) ret = timeout; - xe_tt_unmap_sg(ttm_bo->ttm); + xe_tt_unmap_sg(xe, ttm_bo->ttm); } return ret; @@ -968,6 +967,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, unsigned long *scanned) { + struct xe_device *xe = ttm_to_xe_device(bo->bdev); long lret; /* Fake move to system, without copying data. */ @@ -982,7 +982,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, if (lret) return lret; - xe_tt_unmap_sg(bo->ttm); + xe_tt_unmap_sg(xe, bo->ttm); ttm_bo_move_null(bo, new_resource); } @@ -993,7 +993,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, .allow_move = false}); if (lret > 0) - xe_ttm_tt_account_subtract(bo->ttm); + xe_ttm_tt_account_subtract(xe, bo->ttm); return lret; } @@ -1043,7 +1043,7 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm); struct ttm_place place = {.mem_type = bo->resource->mem_type}; struct xe_bo *xe_bo = ttm_to_xe_bo(bo); - struct xe_device *xe = xe_tt->xe; + struct xe_device *xe = ttm_to_xe_device(bo->bdev); bool needs_rpm; long lret = 0L; @@ -1080,7 +1080,7 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, xe_pm_runtime_put(xe); if (lret > 0) - xe_ttm_tt_account_subtract(tt); + xe_ttm_tt_account_subtract(xe, tt); out_unref: xe_bo_put(xe_bo); @@ -1381,7 +1381,8 @@ int xe_bo_dma_unmap_pinned(struct xe_bo *bo) ttm_bo->sg = NULL; xe_tt->sg = NULL; } else if (xe_tt->sg) { - dma_unmap_sgtable(xe_tt->xe->drm.dev, xe_tt->sg, + dma_unmap_sgtable(ttm_to_xe_device(ttm_bo->bdev)->drm.dev, + xe_tt->sg, DMA_BIDIRECTIONAL, 0); sg_free_table(xe_tt->sg); xe_tt->sg = NULL; @@ -2293,7 +2294,7 @@ int xe_bo_pin_external(struct xe_bo *bo) ttm_bo_pin(&bo->ttm); if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm)) - xe_ttm_tt_account_subtract(bo->ttm.ttm); + xe_ttm_tt_account_subtract(xe, bo->ttm.ttm); /* * FIXME: If we always use the reserve / unreserve functions for locking @@ -2341,7 +2342,7 @@ int xe_bo_pin(struct xe_bo *bo) ttm_bo_pin(&bo->ttm); if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm)) - xe_ttm_tt_account_subtract(bo->ttm.ttm); + xe_ttm_tt_account_subtract(xe, bo->ttm.ttm); /* * FIXME: If we always use the reserve / unreserve functions for locking @@ -2377,7 +2378,7 @@ void xe_bo_unpin_external(struct xe_bo *bo) ttm_bo_unpin(&bo->ttm); if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm)) - xe_ttm_tt_account_add(bo->ttm.ttm); + xe_ttm_tt_account_add(xe, bo->ttm.ttm); /* * FIXME: If we always use the reserve / unreserve functions for locking @@ -2409,7 +2410,7 @@ void xe_bo_unpin(struct xe_bo *bo) } ttm_bo_unpin(&bo->ttm); if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm)) - xe_ttm_tt_account_add(bo->ttm.ttm); + xe_ttm_tt_account_add(xe, bo->ttm.ttm); } /** -- GitLab From f574855a4c57dbabbfa7675e0516203c51ed833b Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 4 Jun 2025 22:29:06 +0200 Subject: [PATCH 250/902] drm/xe/topology: Simplify code for loading DSS mask Instead of passing registers using va_list we can keep them in the static array and pass as such and also lower driver footprint: add/remove: 2/0 grow/shrink: 0/2 up/down: 24/-175 (-151) Function old new delta geometry_regs - 12 +12 compute_regs - 12 +12 xe_gt_topology_init 550 527 -23 load_dss_mask 449 297 -152 Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250604202908.769-2-michal.wajdeczko@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_topology.c | 33 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_topology.c b/drivers/gpu/drm/xe/xe_gt_topology.c index acec6559e2f21..62bfb6e1a1661 100644 --- a/drivers/gpu/drm/xe/xe_gt_topology.c +++ b/drivers/gpu/drm/xe/xe_gt_topology.c @@ -16,20 +16,17 @@ #include "xe_mmio.h" #include "xe_wa.h" -static void -load_dss_mask(struct xe_gt *gt, xe_dss_mask_t mask, int numregs, ...) +static void load_dss_mask(struct xe_gt *gt, xe_dss_mask_t mask, int numregs, + const struct xe_reg regs[]) { - va_list argp; u32 fuse_val[XE_MAX_DSS_FUSE_REGS] = {}; int i; if (drm_WARN_ON(>_to_xe(gt)->drm, numregs > XE_MAX_DSS_FUSE_REGS)) numregs = XE_MAX_DSS_FUSE_REGS; - va_start(argp, numregs); for (i = 0; i < numregs; i++) - fuse_val[i] = xe_mmio_read32(>->mmio, va_arg(argp, struct xe_reg)); - va_end(argp); + fuse_val[i] = xe_mmio_read32(>->mmio, regs[i]); bitmap_from_arr32(mask, fuse_val, numregs * 32); } @@ -219,9 +216,19 @@ get_num_dss_regs(struct xe_device *xe, int *geometry_regs, int *compute_regs) void xe_gt_topology_init(struct xe_gt *gt) { + static const struct xe_reg geometry_regs[] = { + XELP_GT_GEOMETRY_DSS_ENABLE, + XE2_GT_GEOMETRY_DSS_1, + XE2_GT_GEOMETRY_DSS_2, + }; + static const struct xe_reg compute_regs[] = { + XEHP_GT_COMPUTE_DSS_ENABLE, + XEHPC_GT_COMPUTE_DSS_ENABLE_EXT, + XE2_GT_COMPUTE_DSS_2, + }; + int num_geometry_regs, num_compute_regs; struct xe_device *xe = gt_to_xe(gt); struct drm_printer p; - int num_geometry_regs, num_compute_regs; get_num_dss_regs(xe, &num_geometry_regs, &num_compute_regs); @@ -233,14 +240,10 @@ xe_gt_topology_init(struct xe_gt *gt) drm_WARN_ON(&xe->drm, num_compute_regs > 3); load_dss_mask(gt, gt->fuse_topo.g_dss_mask, - num_geometry_regs, - XELP_GT_GEOMETRY_DSS_ENABLE, - XE2_GT_GEOMETRY_DSS_1, - XE2_GT_GEOMETRY_DSS_2); - load_dss_mask(gt, gt->fuse_topo.c_dss_mask, num_compute_regs, - XEHP_GT_COMPUTE_DSS_ENABLE, - XEHPC_GT_COMPUTE_DSS_ENABLE_EXT, - XE2_GT_COMPUTE_DSS_2); + num_geometry_regs, geometry_regs); + load_dss_mask(gt, gt->fuse_topo.c_dss_mask, + num_compute_regs, compute_regs); + load_eu_mask(gt, gt->fuse_topo.eu_mask_per_dss, >->fuse_topo.eu_type); load_l3_bank_mask(gt, gt->fuse_topo.l3_bank_mask); -- GitLab From 113c3f596807b7b593b389d923091821d1d46e1b Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 4 Jun 2025 22:29:07 +0200 Subject: [PATCH 251/902] drm/xe/topology: Use register array size instead magic number Since we keep registers in the array we can simply count them and stop relying on magic number when checking if didn't make mistake. Also we can switch to use xe_gt_assert() since it could be just our programming mistake during platform bringup, no need to keep drm_WARN() in the production driver. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250604202908.769-3-michal.wajdeczko@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_topology.c b/drivers/gpu/drm/xe/xe_gt_topology.c index 62bfb6e1a1661..048743913b368 100644 --- a/drivers/gpu/drm/xe/xe_gt_topology.c +++ b/drivers/gpu/drm/xe/xe_gt_topology.c @@ -236,8 +236,8 @@ xe_gt_topology_init(struct xe_gt *gt) * Register counts returned shouldn't exceed the number of registers * passed as parameters below. */ - drm_WARN_ON(&xe->drm, num_geometry_regs > 3); - drm_WARN_ON(&xe->drm, num_compute_regs > 3); + xe_gt_assert(gt, num_geometry_regs <= ARRAY_SIZE(geometry_regs)); + xe_gt_assert(gt, num_compute_regs <= ARRAY_SIZE(compute_regs)); load_dss_mask(gt, gt->fuse_topo.g_dss_mask, num_geometry_regs, geometry_regs); -- GitLab From bfb114751af9f44bc0fdd595bc09b085c81cc61f Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 4 Jun 2025 22:29:08 +0200 Subject: [PATCH 252/902] drm/xe/topology: Stop trying to fix programming mistakes We shouldn't ever pass more DSS registers than our hardcoded limit, it should be sufficient to just assert that instead of trying to fix it, as this will never happen in the production driver. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Matt Roper Link: https://lore.kernel.org/r/20250604202908.769-4-michal.wajdeczko@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_topology.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_topology.c b/drivers/gpu/drm/xe/xe_gt_topology.c index 048743913b368..305939c697475 100644 --- a/drivers/gpu/drm/xe/xe_gt_topology.c +++ b/drivers/gpu/drm/xe/xe_gt_topology.c @@ -22,8 +22,7 @@ static void load_dss_mask(struct xe_gt *gt, xe_dss_mask_t mask, int numregs, u32 fuse_val[XE_MAX_DSS_FUSE_REGS] = {}; int i; - if (drm_WARN_ON(>_to_xe(gt)->drm, numregs > XE_MAX_DSS_FUSE_REGS)) - numregs = XE_MAX_DSS_FUSE_REGS; + xe_gt_assert(gt, numregs <= ARRAY_SIZE(fuse_val)); for (i = 0; i < numregs; i++) fuse_val[i] = xe_mmio_read32(>->mmio, regs[i]); -- GitLab From 02670deede2288d8e4e3d800477b27c091080fae Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Fri, 6 Jun 2025 13:21:34 -0700 Subject: [PATCH 253/902] libbpf: Handle unsupported mmap-based /sys/kernel/btf/vmlinux correctly libbpf_err_ptr() helpers are meant to return NULL and set errno, if there is an error. But btf_parse_raw_mmap() is meant to be used internally and is expected to return ERR_PTR() values. Because of this mismatch, when libbpf tries to mmap /sys/kernel/btf/vmlinux, we don't detect the error correctly with IS_ERR() check, and never fallback to old non-mmap-based way of loading vmlinux BTF. Fix this by using proper ERR_PTR() returns internally. Reported-by: Arnaldo Carvalho de Melo Reviewed-by: Arnaldo Carvalho de Melo Tested-by: Arnaldo Carvalho de Melo Fixes: 3c0421c93ce4 ("libbpf: Use mmap to parse vmlinux BTF from sysfs") Cc: Lorenz Bauer Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20250606202134.2738910-1-andrii@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/btf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index f1d495dc66bba..37682908cb0f3 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -1384,12 +1384,12 @@ static struct btf *btf_parse_raw_mmap(const char *path, struct btf *base_btf) fd = open(path, O_RDONLY); if (fd < 0) - return libbpf_err_ptr(-errno); + return ERR_PTR(-errno); if (fstat(fd, &st) < 0) { err = -errno; close(fd); - return libbpf_err_ptr(err); + return ERR_PTR(err); } data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); @@ -1397,7 +1397,7 @@ static struct btf *btf_parse_raw_mmap(const char *path, struct btf *base_btf) close(fd); if (data == MAP_FAILED) - return libbpf_err_ptr(err); + return ERR_PTR(err); btf = btf_new(data, st.st_size, base_btf, true); if (IS_ERR(btf)) -- GitLab From 4c529a4a7260776bb4abe264498857b4537aa70d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 7 Jun 2025 14:22:56 +0200 Subject: [PATCH 254/902] x86/smp: PM/hibernate: Split arch_resume_nosmt() Move the inner part of the arch_resume_nosmt() code into a separate function called arch_cpu_rescan_dead_smt_siblings(), so it can be used in other places where "dead" SMT siblings may need to be taken online and offline again in order to get into deep idle states. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Dave Hansen Tested-by: Artem Bityutskiy Link: https://patch.msgid.link/3361688.44csPzL39Z@rjwysocki.net [ rjw: Prevent build issues with CONFIG_SMP unset ] Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/smp.c | 24 ++++++++++++++++++++++++ arch/x86/power/hibernate.c | 19 ++++++------------- include/linux/cpu.h | 3 +++ 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 18266cc3d98c1..b014e6d229f95 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -299,3 +299,27 @@ struct smp_ops smp_ops = { .send_call_func_single_ipi = native_send_call_func_single_ipi, }; EXPORT_SYMBOL_GPL(smp_ops); + +int arch_cpu_rescan_dead_smt_siblings(void) +{ + enum cpuhp_smt_control old = cpu_smt_control; + int ret; + + /* + * If SMT has been disabled and SMT siblings are in HLT, bring them back + * online and offline them again so that they end up in MWAIT proper. + * + * Called with hotplug enabled. + */ + if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED) + return 0; + + ret = cpuhp_smt_enable(); + if (ret) + return ret; + + ret = cpuhp_smt_disable(old); + + return ret; +} +EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings); diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c index a7c23f2a58c99..a2294c1649f65 100644 --- a/arch/x86/power/hibernate.c +++ b/arch/x86/power/hibernate.c @@ -192,7 +192,8 @@ out: int arch_resume_nosmt(void) { - int ret = 0; + int ret; + /* * We reached this while coming out of hibernation. This means * that SMT siblings are sleeping in hlt, as mwait is not safe @@ -206,18 +207,10 @@ int arch_resume_nosmt(void) * Called with hotplug disabled. */ cpu_hotplug_enable(); - if (cpu_smt_control == CPU_SMT_DISABLED || - cpu_smt_control == CPU_SMT_FORCE_DISABLED) { - enum cpuhp_smt_control old = cpu_smt_control; - - ret = cpuhp_smt_enable(); - if (ret) - goto out; - ret = cpuhp_smt_disable(old); - if (ret) - goto out; - } -out: + + ret = arch_cpu_rescan_dead_smt_siblings(); + cpu_hotplug_disable(); + return ret; } diff --git a/include/linux/cpu.h b/include/linux/cpu.h index e6089abc28e2c..96a3a0d6a60ed 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -120,6 +120,7 @@ extern void cpu_maps_update_begin(void); extern void cpu_maps_update_done(void); int bringup_hibernate_cpu(unsigned int sleep_cpu); void bringup_nonboot_cpus(unsigned int max_cpus); +int arch_cpu_rescan_dead_smt_siblings(void); #else /* CONFIG_SMP */ #define cpuhp_tasks_frozen 0 @@ -134,6 +135,8 @@ static inline void cpu_maps_update_done(void) static inline int add_cpu(unsigned int cpu) { return 0;} +static inline int arch_cpu_rescan_dead_smt_siblings(void) { return 0; } + #endif /* CONFIG_SMP */ extern const struct bus_type cpu_subsys; -- GitLab From a430c11f401589a0f4f57fd398271a5d85142c7a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 5 Jun 2025 17:06:08 +0200 Subject: [PATCH 255/902] intel_idle: Rescan "dead" SMT siblings during initialization Make intel_idle_init() call arch_cpu_rescan_dead_smt_siblings() after successfully registering intel_idle as the cpuidle driver so as to allow the "dead" SMT siblings (if any) to go into deep idle states. This is necessary for the processor to be able to reach deep package C-states (like PC10) going forward which is requisite for reducing power sufficiently in suspend-to-idle, among other things. Signed-off-by: Rafael J. Wysocki Tested-by: Artem Bityutskiy Link: https://patch.msgid.link/10669885.nUPlyArG6x@rjwysocki.net --- drivers/idle/intel_idle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 64ac4da080940..63565814c7e5d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -2507,6 +2507,8 @@ static int __init intel_idle_init(void) pr_debug("Local APIC timer is reliable in %s\n", boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1"); + arch_cpu_rescan_dead_smt_siblings(); + return 0; hp_setup_fail: -- GitLab From f694481b1d3177144fcac4242eb750cfcb9f7bd5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 5 Jun 2025 17:07:31 +0200 Subject: [PATCH 256/902] ACPI: processor: Rescan "dead" SMT siblings during initialization Make acpi_processor_driver_init() call arch_cpu_rescan_dead_smt_siblings(), via a new wrapper function called acpi_idle_rescan_dead_smt_siblings(), after successfully initializing the driver, to allow the "dead" SMT siblings to go into deep idle states, which is necessary for the processor to be able to reach deep package C-states (like PC10) going forward, so that power can be reduced sufficiently in suspend-to-idle, among other things. However, do it only if the ACPI idle driver is the current cpuidle driver (otherwise it is assumed that another cpuidle driver will take care of this) and avoid doing it on architectures other than x86. Signed-off-by: Rafael J. Wysocki Tested-by: Artem Bityutskiy Link: https://patch.msgid.link/2005721.PYKUYFuaPT@rjwysocki.net --- drivers/acpi/internal.h | 6 ++++++ drivers/acpi/processor_driver.c | 3 +++ drivers/acpi/processor_idle.c | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 00910ccd7eda8..e2781864fdceb 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -175,6 +175,12 @@ bool processor_physically_present(acpi_handle handle); static inline void acpi_early_processor_control_setup(void) {} #endif +#ifdef CONFIG_ACPI_PROCESSOR_CSTATE +void acpi_idle_rescan_dead_smt_siblings(void); +#else +static inline void acpi_idle_rescan_dead_smt_siblings(void) {} +#endif + /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 3b281bc1e73c3..65e779be64ffc 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -279,6 +279,9 @@ static int __init acpi_processor_driver_init(void) * after acpi_cppc_processor_probe() has been called for all online CPUs */ acpi_processor_init_invariance_cppc(); + + acpi_idle_rescan_dead_smt_siblings(); + return 0; err: driver_unregister(&acpi_processor_driver); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e2febca2ec13e..2c2dc559e0f8d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -24,6 +24,8 @@ #include #include +#include "internal.h" + /* * Include the apic definitions for x86 to have the APIC timer related defines * available also for UP (on SMP it gets magically included via linux/smp.h). @@ -55,6 +57,12 @@ struct cpuidle_driver acpi_idle_driver = { }; #ifdef CONFIG_ACPI_PROCESSOR_CSTATE +void acpi_idle_rescan_dead_smt_siblings(void) +{ + if (cpuidle_get_driver() == &acpi_idle_driver) + arch_cpu_rescan_dead_smt_siblings(); +} + static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); -- GitLab From a18d098f2aab82abde1d59c56aef9beca01c892b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 5 Jun 2025 17:09:35 +0200 Subject: [PATCH 257/902] Reapply "x86/smp: Eliminate mwait_play_dead_cpuid_hint()" Revert commit 70523f335734 ("Revert "x86/smp: Eliminate mwait_play_dead_cpuid_hint()"") to reapply the changes from commit 96040f7273e2 ("x86/smp: Eliminate mwait_play_dead_cpuid_hint()") reverted by it. Previously, these changes caused idle power to rise on systems booting with "nosmt" in the kernel command line because they effectively caused "dead" SMT siblings to remain in idle state C1 after executing the HLT instruction, which prevented the processor from reaching package idle states deeper than PC2 going forward. Now, the "dead" SMT siblings are rescanned after initializing a proper cpuidle driver for the processor (either intel_idle or ACPI idle), at which point they are able to enter a sufficiently deep idle state in native_play_dead() via cpuidle, so the code changes in question can be reapplied. Signed-off-by: Rafael J. Wysocki Acked-by: Dave Hansen Tested-by: Artem Bityutskiy Link: https://patch.msgid.link/7813065.EvYhyI6sBW@rjwysocki.net --- arch/x86/kernel/smpboot.c | 54 +++++---------------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fc78c2325fd29..58ede3fa6a75b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1244,6 +1244,10 @@ void play_dead_common(void) local_irq_disable(); } +/* + * We need to flush the caches before going to sleep, lest we have + * dirty data in our caches when we come back up. + */ void __noreturn mwait_play_dead(unsigned int eax_hint) { struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); @@ -1289,50 +1293,6 @@ void __noreturn mwait_play_dead(unsigned int eax_hint) } } -/* - * We need to flush the caches before going to sleep, lest we have - * dirty data in our caches when we come back up. - */ -static inline void mwait_play_dead_cpuid_hint(void) -{ - unsigned int eax, ebx, ecx, edx; - unsigned int highest_cstate = 0; - unsigned int highest_subcstate = 0; - int i; - - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || - boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) - return; - if (!this_cpu_has(X86_FEATURE_MWAIT)) - return; - if (!this_cpu_has(X86_FEATURE_CLFLUSH)) - return; - - eax = CPUID_LEAF_MWAIT; - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); - - /* - * eax will be 0 if EDX enumeration is not valid. - * Initialized below to cstate, sub_cstate value when EDX is valid. - */ - if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) { - eax = 0; - } else { - edx >>= MWAIT_SUBSTATE_SIZE; - for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) { - if (edx & MWAIT_SUBSTATE_MASK) { - highest_cstate = i; - highest_subcstate = edx & MWAIT_SUBSTATE_MASK; - } - } - eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | - (highest_subcstate - 1); - } - - mwait_play_dead(eax); -} - /* * Kick all "offline" CPUs out of mwait on kexec(). See comment in * mwait_play_dead(). @@ -1383,9 +1343,9 @@ void native_play_dead(void) play_dead_common(); tboot_shutdown(TB_SHUTDOWN_WFS); - mwait_play_dead_cpuid_hint(); - if (cpuidle_play_dead()) - hlt_play_dead(); + /* Below returns only on error. */ + cpuidle_play_dead(); + hlt_play_dead(); } #else /* ... !CONFIG_HOTPLUG_CPU */ -- GitLab From 1650d32b92b01db03a1a95d69ee74fcbc34d4b00 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 18 Mar 2025 20:50:27 +0000 Subject: [PATCH 258/902] ath10k: snoc: fix unbalanced IRQ enable in crash recovery In ath10k_snoc_hif_stop() we skip disabling the IRQs in the crash recovery flow, but we still unconditionally call enable again in ath10k_snoc_hif_start(). We can't check the ATH10K_FLAG_CRASH_FLUSH bit since it is cleared before hif_start() is called, so instead check the ATH10K_SNOC_FLAG_RECOVERY flag and skip enabling the IRQs during crash recovery. This fixes unbalanced IRQ enable splats that happen after recovering from a crash. Fixes: 0e622f67e041 ("ath10k: add support for WCN3990 firmware crash recovery") Signed-off-by: Caleb Connolly Tested-by: Loic Poulain Link: https://patch.msgid.link/20250318205043.1043148-1-caleb.connolly@linaro.org Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath10k/snoc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 866bad2db3348..65673b1aba55d 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -937,7 +937,9 @@ static int ath10k_snoc_hif_start(struct ath10k *ar) dev_set_threaded(ar->napi_dev, true); ath10k_core_napi_enable(ar); - ath10k_snoc_irq_enable(ar); + /* IRQs are left enabled when we restart due to a firmware crash */ + if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags)) + ath10k_snoc_irq_enable(ar); ath10k_snoc_rx_post(ar); clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags); -- GitLab From dc9c4252fe0d7a7f1ee904405ea91534277305bf Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Thu, 22 May 2025 15:17:04 +0200 Subject: [PATCH 259/902] wifi: ath10k: Avoid vdev delete timeout when firmware is already down In some scenarios, the firmware may be stopped before the interface is removed, either due to a crash or because the remoteproc (e.g., MPSS) is shut down early during system reboot or shutdown. This leads to a delay during interface teardown, as the driver waits for a vdev delete response that never arrives, eventually timing out. Example (SNOC): $ echo stop > /sys/class/remoteproc/remoteproc0/state [ 71.64] remoteproc remoteproc0: stopped remote processor modem $ reboot [ 74.84] ath10k_snoc c800000.wifi: failed to transmit packet, dropping: -108 [ 74.84] ath10k_snoc c800000.wifi: failed to submit frame: -108 [...] [ 82.39] ath10k_snoc c800000.wifi: Timeout in receiving vdev delete response To avoid this, skip waiting for the vdev delete response if the firmware is already marked as unreachable (`ATH10K_FLAG_CRASH_FLUSH`), similar to how `ath10k_mac_wait_tx_complete()` and `ath10k_vdev_setup_sync()` handle this case. Signed-off-by: Loic Poulain Link: https://patch.msgid.link/20250522131704.612206-1-loic.poulain@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath10k/mac.c | 33 ++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8c7ffea0fa44b..07fe05384cdfb 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4,6 +4,7 @@ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "mac.h" @@ -1022,6 +1023,26 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) return ar->last_wmi_vdev_start_status; } +static inline int ath10k_vdev_delete_sync(struct ath10k *ar) +{ + unsigned long time_left; + + lockdep_assert_held(&ar->conf_mutex); + + if (!test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) + return 0; + + if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + return -ESHUTDOWN; + + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, + ATH10K_VDEV_DELETE_TIMEOUT_HZ); + if (time_left == 0) + return -ETIMEDOUT; + + return 0; +} + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; @@ -5900,7 +5921,6 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; - unsigned long time_left; int ret; int i; @@ -5940,13 +5960,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n", arvif->vdev_id, ret); - if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { - time_left = wait_for_completion_timeout(&ar->vdev_delete_done, - ATH10K_VDEV_DELETE_TIMEOUT_HZ); - if (time_left == 0) { - ath10k_warn(ar, "Timeout in receiving vdev delete response\n"); - goto out; - } + ret = ath10k_vdev_delete_sync(ar); + if (ret) { + ath10k_warn(ar, "Error in receiving vdev delete response: %d\n", ret); + goto out; } /* Some firmware revisions don't notify host about self-peer removal -- GitLab From 593963660919a97a4546acfd706dac93625724f5 Mon Sep 17 00:00:00 2001 From: Sebastian Gottschall Date: Tue, 4 Mar 2025 08:21:31 +0700 Subject: [PATCH 260/902] wil6210: fix support for sparrow chipsets the wil6210 driver irq handling code is unconditionally writing edma irq registers which are supposed to be only used on Talyn chipsets. This however leade to a chipset hang on the older sparrow chipset generation and firmware will not even boot. Fix that by simply checking for edma support before handling these registers. Tested on Netgear R9000 Signed-off-by: Sebastian Gottschall Link: https://patch.msgid.link/20250304012131.25970-2-s.gottschall@dd-wrt.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/wil6210/interrupt.c | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 67172385a5d66..89d4394cedcff 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -179,9 +179,11 @@ void wil_mask_irq(struct wil6210_priv *wil) wil_dbg_irq(wil, "mask_irq\n"); wil6210_mask_irq_tx(wil); - wil6210_mask_irq_tx_edma(wil); + if (wil->use_enhanced_dma_hw) + wil6210_mask_irq_tx_edma(wil); wil6210_mask_irq_rx(wil); - wil6210_mask_irq_rx_edma(wil); + if (wil->use_enhanced_dma_hw) + wil6210_mask_irq_rx_edma(wil); wil6210_mask_irq_misc(wil, true); wil6210_mask_irq_pseudo(wil); } @@ -190,10 +192,12 @@ void wil_unmask_irq(struct wil6210_priv *wil) { wil_dbg_irq(wil, "unmask_irq\n"); - wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_VALUE); - wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_VALUE); + if (wil->use_enhanced_dma_hw) { + wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), + WIL_ICR_ICC_VALUE); + wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), + WIL_ICR_ICC_VALUE); + } wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_MISC_VALUE); wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC), @@ -845,10 +849,12 @@ void wil6210_clear_irq(struct wil6210_priv *wil) offsetof(struct RGF_ICR, ICR)); wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + offsetof(struct RGF_ICR, ICR)); - wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + - offsetof(struct RGF_ICR, ICR)); - wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + - offsetof(struct RGF_ICR, ICR)); + if (wil->use_enhanced_dma_hw) { + wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + + offsetof(struct RGF_ICR, ICR)); + wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + + offsetof(struct RGF_ICR, ICR)); + } wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + offsetof(struct RGF_ICR, ICR)); wmb(); /* make sure write completed */ -- GitLab From 9f6e82d11bb9692a90d20b10f87345598945c803 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:42 +0800 Subject: [PATCH 261/902] wifi: ath11k: avoid burning CPU in ath11k_debugfs_fw_stats_request() We get report [1] that CPU is running a hot loop in ath11k_debugfs_fw_stats_request(): 94.60% 0.00% i3status [kernel.kallsyms] [k] do_syscall_64 | --94.60%--do_syscall_64 | --94.55%--__sys_sendmsg ___sys_sendmsg ____sys_sendmsg netlink_sendmsg netlink_unicast genl_rcv netlink_rcv_skb genl_rcv_msg | --94.55%--genl_family_rcv_msg_dumpit __netlink_dump_start netlink_dump genl_dumpit nl80211_dump_station | --94.55%--ieee80211_dump_station sta_set_sinfo | --94.55%--ath11k_mac_op_sta_statistics ath11k_debugfs_get_fw_stats | --94.55%--ath11k_debugfs_fw_stats_request | |--41.73%--_raw_spin_lock_bh | |--22.74%--__local_bh_enable_ip | |--9.22%--_raw_spin_unlock_bh | --6.66%--srso_alias_safe_ret This is because, if for whatever reason ar->fw_stats_done is not set by ath11k_update_stats_event(), ath11k_debugfs_fw_stats_request() won't yield CPU before an up to 3s timeout. Change to completion mechanism to avoid CPU burning. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Reported-by: Yury Vostrikov Closes: https://lore.kernel.org/all/7324ac7a-8b7a-42a5-aa19-de52138ff638@app.fastmail.com/ # [1] Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-2-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/core.c | 1 + drivers/net/wireless/ath/ath11k/core.h | 2 +- drivers/net/wireless/ath/ath11k/debugfs.c | 38 +++++++++-------------- drivers/net/wireless/ath/ath11k/mac.c | 2 +- drivers/net/wireless/ath/ath11k/wmi.c | 2 +- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 2e9f8a5e61e4c..c8c5008be7f26 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -990,6 +990,7 @@ void ath11k_fw_stats_init(struct ath11k *ar) INIT_LIST_HEAD(&ar->fw_stats.bcn); init_completion(&ar->fw_stats_complete); + init_completion(&ar->fw_stats_done); } void ath11k_fw_stats_free(struct ath11k_fw_stats *stats) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 339d4fca1ed5f..41bb81d00189c 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -784,7 +784,7 @@ struct ath11k { u8 alpha2[REG_ALPHA2_LEN + 1]; struct ath11k_fw_stats fw_stats; struct completion fw_stats_complete; - bool fw_stats_done; + struct completion fw_stats_done; /* protected by conf_mutex */ bool ps_state_enable; diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index bf192529e3fe2..1d03e3aab011d 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -96,7 +96,6 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar) { spin_lock_bh(&ar->data_lock); - ar->fw_stats_done = false; ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); spin_unlock_bh(&ar->data_lock); @@ -114,7 +113,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * /* WMI_REQUEST_PDEV_STAT request has been already processed */ if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { - ar->fw_stats_done = true; + complete(&ar->fw_stats_done); return; } @@ -138,7 +137,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * &ar->fw_stats.vdevs); if (is_end) { - ar->fw_stats_done = true; + complete(&ar->fw_stats_done); num_vdev = 0; } return; @@ -158,7 +157,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * &ar->fw_stats.bcn); if (is_end) { - ar->fw_stats_done = true; + complete(&ar->fw_stats_done); num_bcn = 0; } } @@ -168,21 +167,15 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, struct stats_request_params *req_param) { struct ath11k_base *ab = ar->ab; - unsigned long timeout, time_left; + unsigned long time_left; int ret; lockdep_assert_held(&ar->conf_mutex); - /* FW stats can get split when exceeding the stats data buffer limit. - * In that case, since there is no end marking for the back-to-back - * received 'update stats' event, we keep a 3 seconds timeout in case, - * fw_stats_done is not marked yet - */ - timeout = jiffies + secs_to_jiffies(3); - ath11k_debugfs_fw_stats_reset(ar); reinit_completion(&ar->fw_stats_complete); + reinit_completion(&ar->fw_stats_done); ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); @@ -193,21 +186,18 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, } time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); - if (!time_left) return -ETIMEDOUT; - for (;;) { - if (time_after(jiffies, timeout)) - break; + /* FW stats can get split when exceeding the stats data buffer limit. + * In that case, since there is no end marking for the back-to-back + * received 'update stats' event, we keep a 3 seconds timeout in case, + * fw_stats_done is not marked yet + */ + time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); + if (!time_left) + return -ETIMEDOUT; - spin_lock_bh(&ar->data_lock); - if (ar->fw_stats_done) { - spin_unlock_bh(&ar->data_lock); - break; - } - spin_unlock_bh(&ar->data_lock); - } return 0; } diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 08d7b136851fa..9ab501cd4f47a 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9390,11 +9390,11 @@ static int ath11k_fw_stats_request(struct ath11k *ar, lockdep_assert_held(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); - ar->fw_stats_done = false; ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); spin_unlock_bh(&ar->data_lock); reinit_completion(&ar->fw_stats_complete); + reinit_completion(&ar->fw_stats_done); ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); if (ret) { diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index d7f852bebf4aa..27cb0bb06b93c 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8189,7 +8189,7 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk */ if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs); - ar->fw_stats_done = true; + complete(&ar->fw_stats_done); goto complete; } -- GitLab From 2bcf73b2612dda7432f2c2eaad6679bd291791f2 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:43 +0800 Subject: [PATCH 262/902] wifi: ath11k: don't use static variables in ath11k_debugfs_fw_stats_process() Currently ath11k_debugfs_fw_stats_process() is using static variables to count firmware stat events. Taking num_vdev as an example, if for whatever reason ( say ar->num_started_vdevs is 0 or firmware bug etc.) the following condition (++num_vdev) == total_vdevs_started is not met, is_end is not set thus num_vdev won't be cleared. Next time when firmware stats is requested again, even if everything is working fine, we will fail due to the condition above will never be satisfied. The same applies to num_bcn as well. Change to use non-static counters so that we have a chance to clear them each time firmware stats is requested. Currently only ath11k_fw_stats_request() and ath11k_debugfs_fw_stats_request() are requesting firmware stats, so clear counters there. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes: da3a9d3c1576 ("ath11k: refactor debugfs code into debugfs.c") Signed-off-by: Baochen Qiang Acked-by: Kalle Valo Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-3-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/core.h | 2 ++ drivers/net/wireless/ath/ath11k/debugfs.c | 16 +++++++--------- drivers/net/wireless/ath/ath11k/mac.c | 2 ++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 41bb81d00189c..6b2f207975e33 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -600,6 +600,8 @@ struct ath11k_fw_stats { struct list_head pdevs; struct list_head vdevs; struct list_head bcn; + u32 num_vdev_recvd; + u32 num_bcn_recvd; }; struct ath11k_dbg_htt_stats { diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index 1d03e3aab011d..27c93c0b4c223 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -98,6 +98,8 @@ static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar) spin_lock_bh(&ar->data_lock); ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); + ar->fw_stats.num_vdev_recvd = 0; + ar->fw_stats.num_bcn_recvd = 0; spin_unlock_bh(&ar->data_lock); } @@ -106,7 +108,6 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * struct ath11k_base *ab = ar->ab; struct ath11k_pdev *pdev; bool is_end; - static unsigned int num_vdev, num_bcn; size_t total_vdevs_started = 0; int i; @@ -131,15 +132,14 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * total_vdevs_started += ar->num_started_vdevs; } - is_end = ((++num_vdev) == total_vdevs_started); + is_end = ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started); list_splice_tail_init(&stats->vdevs, &ar->fw_stats.vdevs); - if (is_end) { + if (is_end) complete(&ar->fw_stats_done); - num_vdev = 0; - } + return; } @@ -151,15 +151,13 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * /* Mark end until we reached the count of all started VDEVs * within the PDEV */ - is_end = ((++num_bcn) == ar->num_started_vdevs); + is_end = ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs); list_splice_tail_init(&stats->bcn, &ar->fw_stats.bcn); - if (is_end) { + if (is_end) complete(&ar->fw_stats_done); - num_bcn = 0; - } } } diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 9ab501cd4f47a..5e098780cf236 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9391,6 +9391,8 @@ static int ath11k_fw_stats_request(struct ath11k *ar, spin_lock_bh(&ar->data_lock); ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); + ar->fw_stats.num_vdev_recvd = 0; + ar->fw_stats.num_bcn_recvd = 0; spin_unlock_bh(&ar->data_lock); reinit_completion(&ar->fw_stats_complete); -- GitLab From 3b6d00fa883075dcaf49221538230e038a9c0b43 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:44 +0800 Subject: [PATCH 263/902] wifi: ath11k: don't wait when there is no vdev started For WMI_REQUEST_VDEV_STAT request, firmware might split response into multiple events dut to buffer limit, hence currently in ath11k_debugfs_fw_stats_process() we wait until all events received. In case there is no vdev started, this results in that below condition would never get satisfied ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started) finally the requestor would be blocked until wait time out. The same applies to WMI_REQUEST_BCN_STAT request as well due to: ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs) Change to check the number of started vdev first: if it is zero, finish wait directly; if not, follow the old way. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-4-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/debugfs.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index 27c93c0b4c223..ccf0e62c7d7ae 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -107,7 +107,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * { struct ath11k_base *ab = ar->ab; struct ath11k_pdev *pdev; - bool is_end; + bool is_end = true; size_t total_vdevs_started = 0; int i; @@ -132,7 +132,9 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * total_vdevs_started += ar->num_started_vdevs; } - is_end = ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started); + if (total_vdevs_started) + is_end = ((++ar->fw_stats.num_vdev_recvd) == + total_vdevs_started); list_splice_tail_init(&stats->vdevs, &ar->fw_stats.vdevs); @@ -151,7 +153,9 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * /* Mark end until we reached the count of all started VDEVs * within the PDEV */ - is_end = ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs); + if (ar->num_started_vdevs) + is_end = ((++ar->fw_stats.num_bcn_recvd) == + ar->num_started_vdevs); list_splice_tail_init(&stats->bcn, &ar->fw_stats.bcn); -- GitLab From 72610ed7d79da17ee09102534d6c696a4ea8a08e Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:45 +0800 Subject: [PATCH 264/902] wifi: ath11k: move some firmware stats related functions outside of debugfs Commit b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855") and commit c3b39553fc77 ("ath11k: add signal report to mac80211 for QCA6390 and WCN6855") call debugfs functions in mac ops. Those functions are no-ops if CONFIG_ATH11K_DEBUGFS is not enabled, thus cause wrong status reported. Move them to mac.c. Besides, since WMI_REQUEST_RSSI_PER_CHAIN_STAT and WMI_REQUEST_VDEV_STAT stats could also be requested via mac ops, process them directly in ath11k_update_stats_event(). Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes: b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855") Fixes: c3b39553fc77 ("ath11k: add signal report to mac80211 for QCA6390 and WCN6855") Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-5-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/debugfs.c | 126 ++-------------------- drivers/net/wireless/ath/ath11k/debugfs.h | 10 +- drivers/net/wireless/ath/ath11k/mac.c | 88 ++++++++++++++- drivers/net/wireless/ath/ath11k/mac.h | 4 +- drivers/net/wireless/ath/ath11k/wmi.c | 45 +++++++- 5 files changed, 135 insertions(+), 138 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index ccf0e62c7d7ae..5d46f8e4c231f 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -93,58 +93,14 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, spin_unlock_bh(&dbr_data->lock); } -static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar) -{ - spin_lock_bh(&ar->data_lock); - ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); - ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); - ar->fw_stats.num_vdev_recvd = 0; - ar->fw_stats.num_bcn_recvd = 0; - spin_unlock_bh(&ar->data_lock); -} - void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats) { struct ath11k_base *ab = ar->ab; - struct ath11k_pdev *pdev; bool is_end = true; - size_t total_vdevs_started = 0; - int i; - - /* WMI_REQUEST_PDEV_STAT request has been already processed */ - - if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { - complete(&ar->fw_stats_done); - return; - } - - if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { - if (list_empty(&stats->vdevs)) { - ath11k_warn(ab, "empty vdev stats"); - return; - } - /* FW sends all the active VDEV stats irrespective of PDEV, - * hence limit until the count of all VDEVs started - */ - for (i = 0; i < ab->num_radios; i++) { - pdev = rcu_dereference(ab->pdevs_active[i]); - if (pdev && pdev->ar) - total_vdevs_started += ar->num_started_vdevs; - } - - if (total_vdevs_started) - is_end = ((++ar->fw_stats.num_vdev_recvd) == - total_vdevs_started); - - list_splice_tail_init(&stats->vdevs, - &ar->fw_stats.vdevs); - - if (is_end) - complete(&ar->fw_stats_done); - - return; - } + /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and + * WMI_REQUEST_VDEV_STAT requests have been already processed. + */ if (stats->stats_id == WMI_REQUEST_BCN_STAT) { if (list_empty(&stats->bcn)) { ath11k_warn(ab, "empty bcn stats"); @@ -165,76 +121,6 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * } } -static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, - struct stats_request_params *req_param) -{ - struct ath11k_base *ab = ar->ab; - unsigned long time_left; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - ath11k_debugfs_fw_stats_reset(ar); - - reinit_completion(&ar->fw_stats_complete); - reinit_completion(&ar->fw_stats_done); - - ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); - - if (ret) { - ath11k_warn(ab, "could not request fw stats (%d)\n", - ret); - return ret; - } - - time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); - if (!time_left) - return -ETIMEDOUT; - - /* FW stats can get split when exceeding the stats data buffer limit. - * In that case, since there is no end marking for the back-to-back - * received 'update stats' event, we keep a 3 seconds timeout in case, - * fw_stats_done is not marked yet - */ - time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); - if (!time_left) - return -ETIMEDOUT; - - return 0; -} - -int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, - u32 vdev_id, u32 stats_id) -{ - struct ath11k_base *ab = ar->ab; - struct stats_request_params req_param; - int ret; - - mutex_lock(&ar->conf_mutex); - - if (ar->state != ATH11K_STATE_ON) { - ret = -ENETDOWN; - goto err_unlock; - } - - req_param.pdev_id = pdev_id; - req_param.vdev_id = vdev_id; - req_param.stats_id = stats_id; - - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); - if (ret) - ath11k_warn(ab, "failed to request fw stats: %d\n", ret); - - ath11k_dbg(ab, ATH11K_DBG_WMI, - "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", - pdev_id, vdev_id, stats_id); - -err_unlock: - mutex_unlock(&ar->conf_mutex); - - return ret; -} - static int ath11k_open_pdev_stats(struct inode *inode, struct file *file) { struct ath11k *ar = inode->i_private; @@ -260,7 +146,7 @@ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file) req_param.vdev_id = 0; req_param.stats_id = WMI_REQUEST_PDEV_STAT; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); goto err_free; @@ -331,7 +217,7 @@ static int ath11k_open_vdev_stats(struct inode *inode, struct file *file) req_param.vdev_id = 0; req_param.stats_id = WMI_REQUEST_VDEV_STAT; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret); goto err_free; @@ -407,7 +293,7 @@ static int ath11k_open_bcn_stats(struct inode *inode, struct file *file) continue; req_param.vdev_id = arvif->vdev_id; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret); goto err_free; diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h index a39e458637b01..ed7fec177588f 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022, 2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _ATH11K_DEBUGFS_H_ @@ -273,8 +273,6 @@ void ath11k_debugfs_unregister(struct ath11k *ar); void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats); void ath11k_debugfs_fw_stats_init(struct ath11k *ar); -int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, - u32 vdev_id, u32 stats_id); static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar) { @@ -381,12 +379,6 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar) return 0; } -static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar, - u32 pdev_id, u32 vdev_id, u32 stats_id) -{ - return 0; -} - static inline void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, enum wmi_direct_buffer_module id, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 5e098780cf236..1550533b55876 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -8997,6 +8997,86 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo, } } +static void ath11k_mac_fw_stats_reset(struct ath11k *ar) +{ + spin_lock_bh(&ar->data_lock); + ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); + ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); + ar->fw_stats.num_vdev_recvd = 0; + ar->fw_stats.num_bcn_recvd = 0; + spin_unlock_bh(&ar->data_lock); +} + +int ath11k_mac_fw_stats_request(struct ath11k *ar, + struct stats_request_params *req_param) +{ + struct ath11k_base *ab = ar->ab; + unsigned long time_left; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ath11k_mac_fw_stats_reset(ar); + + reinit_completion(&ar->fw_stats_complete); + reinit_completion(&ar->fw_stats_done); + + ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); + + if (ret) { + ath11k_warn(ab, "could not request fw stats (%d)\n", + ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); + if (!time_left) + return -ETIMEDOUT; + + /* FW stats can get split when exceeding the stats data buffer limit. + * In that case, since there is no end marking for the back-to-back + * received 'update stats' event, we keep a 3 seconds timeout in case, + * fw_stats_done is not marked yet + */ + time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); + if (!time_left) + return -ETIMEDOUT; + + return 0; +} + +static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id, + u32 vdev_id, u32 stats_id) +{ + struct ath11k_base *ab = ar->ab; + struct stats_request_params req_param; + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH11K_STATE_ON) { + ret = -ENETDOWN; + goto err_unlock; + } + + req_param.pdev_id = pdev_id; + req_param.vdev_id = vdev_id; + req_param.stats_id = stats_id; + + ret = ath11k_mac_fw_stats_request(ar, &req_param); + if (ret) + ath11k_warn(ab, "failed to request fw stats: %d\n", ret); + + ath11k_dbg(ab, ATH11K_DBG_WMI, + "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", + pdev_id, vdev_id, stats_id); + +err_unlock: + mutex_unlock(&ar->conf_mutex); + + return ret; +} + static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -9034,8 +9114,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && ar->ab->hw_params.supports_rssi_stats && - !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, - WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { + !ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true); } @@ -9043,8 +9123,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, if (!signal && arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && ar->ab->hw_params.supports_rssi_stats && - !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, - WMI_REQUEST_VDEV_STAT))) + !(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_VDEV_STAT))) signal = arsta->rssi_beacon; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index f5800fbecff89..5e61eea1bb037 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_MAC_H @@ -179,4 +179,6 @@ int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx); +int ath11k_mac_fw_stats_request(struct ath11k *ar, + struct stats_request_params *req_param); #endif diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 27cb0bb06b93c..98811726d33bf 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8158,6 +8158,11 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb) { struct ath11k_fw_stats stats = {}; + size_t total_vdevs_started = 0; + struct ath11k_pdev *pdev; + bool is_end = true; + int i; + struct ath11k *ar; int ret; @@ -8184,7 +8189,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk spin_lock_bh(&ar->data_lock); - /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via + /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_VDEV_STAT and + * WMI_REQUEST_RSSI_PER_CHAIN_STAT can be requested via mac ops or via * debugfs fw stats. Therefore, processing it separately. */ if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { @@ -8193,9 +8199,40 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk goto complete; } - /* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT - * are currently requested only via debugfs fw stats. Hence, processing these - * in debugfs context + if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { + complete(&ar->fw_stats_done); + goto complete; + } + + if (stats.stats_id == WMI_REQUEST_VDEV_STAT) { + if (list_empty(&stats.vdevs)) { + ath11k_warn(ab, "empty vdev stats"); + goto complete; + } + /* FW sends all the active VDEV stats irrespective of PDEV, + * hence limit until the count of all VDEVs started + */ + for (i = 0; i < ab->num_radios; i++) { + pdev = rcu_dereference(ab->pdevs_active[i]); + if (pdev && pdev->ar) + total_vdevs_started += ar->num_started_vdevs; + } + + if (total_vdevs_started) + is_end = ((++ar->fw_stats.num_vdev_recvd) == + total_vdevs_started); + + list_splice_tail_init(&stats.vdevs, + &ar->fw_stats.vdevs); + + if (is_end) + complete(&ar->fw_stats_done); + + goto complete; + } + + /* WMI_REQUEST_BCN_STAT is currently requested only via debugfs fw stats. + * Hence, processing it in debugfs context */ ath11k_debugfs_fw_stats_process(ar, &stats); -- GitLab From 81f64165c9dc2d9b070d8240dd369974ebe188d3 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:46 +0800 Subject: [PATCH 265/902] wifi: ath11k: adjust unlock sequence in ath11k_update_stats_event() Currently RCU lock and ar->data_lock are acquired in a sequence of rcu_read_lock() spin_lock_bh(&ar->data_lock) but released in a sequence of rcu_read_unlock() spin_unlock_bh(&ar->data_lock) Although there are no apparent issues with this, reorder them to achieve symmetry. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Signed-off-by: Baochen Qiang Acked-by: Kalle Valo Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-6-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 98811726d33bf..56af2e9634f42 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8238,8 +8238,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk complete: complete(&ar->fw_stats_complete); - rcu_read_unlock(); spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised * at this point, no need to free the individual list. -- GitLab From c5b92a2c18938ebb08e8d4062408ab1524da31c3 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:47 +0800 Subject: [PATCH 266/902] wifi: ath11k: move locking outside of ath11k_mac_get_fw_stats() Currently ath11k_mac_get_fw_stats() is acquiring/releasing ar->conf_mutex by itself. In order to reuse this function in a context where that lock is already taken, move lock handling to its callers, then the function itself only has to assert it. There is only one caller now, i.e., ath11k_mac_op_sta_statistics(), so add lock handling there. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-7-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/mac.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 1550533b55876..18e1d78cac45e 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9052,12 +9052,10 @@ static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id, struct stats_request_params req_param; int ret; - mutex_lock(&ar->conf_mutex); + lockdep_assert_held(&ar->conf_mutex); - if (ar->state != ATH11K_STATE_ON) { - ret = -ENETDOWN; - goto err_unlock; - } + if (ar->state != ATH11K_STATE_ON) + return -ENETDOWN; req_param.pdev_id = pdev_id; req_param.vdev_id = vdev_id; @@ -9071,9 +9069,6 @@ static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id, "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", pdev_id, vdev_id, stats_id); -err_unlock: - mutex_unlock(&ar->conf_mutex); - return ret; } @@ -9111,6 +9106,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false); + mutex_lock(&ar->conf_mutex); if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && ar->ab->hw_params.supports_rssi_stats && @@ -9126,6 +9122,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, !(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, WMI_REQUEST_VDEV_STAT))) signal = arsta->rssi_beacon; + mutex_unlock(&ar->conf_mutex); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", -- GitLab From 29e2adf2ef2966379bd3fe002530b10dfc3030ba Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 20 Feb 2025 16:24:48 +0800 Subject: [PATCH 267/902] wifi: ath11k: consistently use ath11k_mac_get_fw_stats() Currently to get firmware stats, ath11k_mac_op_get_txpower() calls ath11k_fw_stats_request() and ath11k_mac_op_sta_statistics() calls ath11k_mac_get_fw_stats(). Those two helpers are basically doing the same, except for: 1. ath11k_mac_get_fw_stats() verifies ar->state inside itself. 2. ath11k_mac_get_fw_stats() calls ath11k_mac_fw_stats_request() which then calls ath11k_mac_fw_stats_reset() to free pdev/vdev stats whereas only pdev stats are freed by ath11k_fw_stats_request(). 3. ath11k_mac_get_fw_stats() waits for ar->fw_stats_complete and ar->fw_stats_done, whereas ath11k_fw_stats_request() only waits for ar->fw_stats_complete. Change to call ath11k_mac_get_fw_stats() in ath11k_mac_op_get_txpower(). This is valid because: 1. ath11k_mac_op_get_txpower() also has the same request on ar->state. 2. it is harmless to call ath11k_fw_stats_vdevs_free() since ar->fw_stats.vdevs should be empty and there should be no one expecting it at that time. 3. ath11k_mac_op_get_txpower() only needs pdev stats. For pdev stats, ar->fw_stats_done is set to true whenever ar->fw_stats_complete is set to true in ath11k_update_stats_event(). So additional wait on ar->fw_stats_done does not wast any time. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250220082448.31039-8-quic_bqiang@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/mac.c | 44 ++------------------------- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 18e1d78cac45e..13301ca317a53 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9457,40 +9457,6 @@ exit: return ret; } -static int ath11k_fw_stats_request(struct ath11k *ar, - struct stats_request_params *req_param) -{ - struct ath11k_base *ab = ar->ab; - unsigned long time_left; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - spin_lock_bh(&ar->data_lock); - ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); - ar->fw_stats.num_vdev_recvd = 0; - ar->fw_stats.num_bcn_recvd = 0; - spin_unlock_bh(&ar->data_lock); - - reinit_completion(&ar->fw_stats_complete); - reinit_completion(&ar->fw_stats_done); - - ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); - if (ret) { - ath11k_warn(ab, "could not request fw stats (%d)\n", - ret); - return ret; - } - - time_left = wait_for_completion_timeout(&ar->fw_stats_complete, - 1 * HZ); - - if (!time_left) - return -ETIMEDOUT; - - return 0; -} - static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, @@ -9498,7 +9464,6 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; - struct stats_request_params req_param = {0}; struct ath11k_fw_stats_pdev *pdev; int ret; @@ -9510,9 +9475,6 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, */ mutex_lock(&ar->conf_mutex); - if (ar->state != ATH11K_STATE_ON) - goto err_fallback; - /* Firmware doesn't provide Tx power during CAC hence no need to fetch * the stats. */ @@ -9521,10 +9483,8 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, return -EAGAIN; } - req_param.pdev_id = ar->pdev->pdev_id; - req_param.stats_id = WMI_REQUEST_PDEV_STAT; - - ret = ath11k_fw_stats_request(ar, &req_param); + ret = ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_PDEV_STAT); if (ret) { ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); goto err_fallback; -- GitLab From b0d226a60856a1b765bb9a3848c7b2322fd08c47 Mon Sep 17 00:00:00 2001 From: Rodrigo Gobbi Date: Thu, 22 May 2025 17:01:12 -0300 Subject: [PATCH 268/902] wifi: ath11k: validate ath11k_crypto_mode on top of ath11k_core_qmi_firmware_ready if ath11k_crypto_mode is invalid (not ATH11K_CRYPT_MODE_SW/ATH11K_CRYPT_MODE_HW), ath11k_core_qmi_firmware_ready() will not undo some actions that was previously started/configured. Do the validation as soon as possible in order to avoid undoing actions in that case and also to fix the following smatch warning: drivers/net/wireless/ath/ath11k/core.c:2166 ath11k_core_qmi_firmware_ready() warn: missing unwind goto? Signed-off-by: Rodrigo Gobbi Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202304151955.oqAetVFd-lkp@intel.com/ Fixes: aa2092a9bab3 ("ath11k: add raw mode and software crypto support") Reviewed-by: Baochen Qiang Link: https://patch.msgid.link/20250522200519.16858-1-rodrigo.gobbi.7@gmail.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath11k/core.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index c8c5008be7f26..22a1011361350 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -2135,6 +2135,20 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; + switch (ath11k_crypto_mode) { + case ATH11K_CRYPT_MODE_SW: + set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + case ATH11K_CRYPT_MODE_HW: + clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + default: + ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); + return -EINVAL; + } + ret = ath11k_core_start_firmware(ab, ab->fw_mode); if (ret) { ath11k_err(ab, "failed to start firmware: %d\n", ret); @@ -2153,20 +2167,6 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) goto err_firmware_stop; } - switch (ath11k_crypto_mode) { - case ATH11K_CRYPT_MODE_SW: - set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); - set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); - break; - case ATH11K_CRYPT_MODE_HW: - clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); - clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); - break; - default: - ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); - return -EINVAL; - } - if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW) set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); -- GitLab From 7588a893cde5385ad308400ff167d29a29913b3a Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Fri, 23 May 2025 10:23:05 +0800 Subject: [PATCH 269/902] wifi: ath12k: fix GCC_GCC_PCIE_HOT_RST definition for WCN7850 GCC_GCC_PCIE_HOT_RST is wrongly defined for WCN7850, causing kernel crash on some specific platforms. Since this register is divergent for WCN7850 and QCN9274, move it to register table to allow different definitions. Then correct the register address for WCN7850 to fix this issue. Note IPQ5332 is not affected as it is not PCIe based device. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Reported-by: Parth Pancholi Closes: https://lore.kernel.org/all/86899b2235a59c9134603beebe08f2bb0b244ea0.camel@gmail.com Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Tested-by: Parth Pancholi Link: https://patch.msgid.link/20250523-ath12k-wrong-global-reset-addr-v1-1-3b06eb556196@quicinc.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/hw.c | 6 ++++++ drivers/net/wireless/ath/ath12k/hw.h | 2 ++ drivers/net/wireless/ath/ath12k/pci.c | 6 +++--- drivers/net/wireless/ath/ath12k/pci.h | 4 +++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 7e2cf0fb2085a..8254dc10b53bb 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -951,6 +951,8 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e38338, }; static const struct ath12k_hw_regs qcn9274_v2_regs = { @@ -1042,6 +1044,8 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e38338, }; static const struct ath12k_hw_regs ipq5332_regs = { @@ -1215,6 +1219,8 @@ static const struct ath12k_hw_regs wcn7850_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e40304, }; static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index 0fbc17649df46..0a75bc5abfa24 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -375,6 +375,8 @@ struct ath12k_hw_regs { u32 hal_reo_cmd_ring_base; u32 hal_reo_status_ring_base; + + u32 gcc_gcc_pcie_hot_rst; }; static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 489d546390fcd..1f3cfd9b89fdc 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -292,10 +292,10 @@ static void ath12k_pci_enable_ltssm(struct ath12k_base *ab) ath12k_dbg(ab, ATH12K_DBG_PCI, "pci ltssm 0x%x\n", val); - val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); + val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); val |= GCC_GCC_PCIE_HOT_RST_VAL; - ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val); - val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); + ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST(ab), val); + val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); ath12k_dbg(ab, ATH12K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val); diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h index 0b4c459d6d8ea..d1ec8aad7f6c3 100644 --- a/drivers/net/wireless/ath/ath12k/pci.h +++ b/drivers/net/wireless/ath/ath12k/pci.h @@ -28,7 +28,9 @@ #define PCIE_PCIE_PARF_LTSSM 0x1e081b0 #define PARM_LTSSM_VALUE 0x111 -#define GCC_GCC_PCIE_HOT_RST 0x1e38338 +#define GCC_GCC_PCIE_HOT_RST(ab) \ + ((ab)->hw_params->regs->gcc_gcc_pcie_hot_rst) + #define GCC_GCC_PCIE_HOT_RST_VAL 0x10 #define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228 -- GitLab From b6bca6d7149e0bc1a56e831af0296d45688945ec Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 5 Jun 2025 10:27:22 -0700 Subject: [PATCH 270/902] wifi: ath12k: Fix hal_reo_cmd_status kernel-doc Currently a warning is reported when running: % scripts/kernel-doc -Wall -Werror -none drivers/net/wireless/ath/ath12k/hal.h Warning: drivers/net/wireless/ath/ath12k/hal.h:596 Enum value 'HAL_REO_CMD_RESOURCE_BLOCKED' not described in enum 'hal_reo_cmd_status' Add the missing description of HAL_REO_CMD_RESOURCE_BLOCKED. Link: https://patch.msgid.link/20250605-hal_reo_cmd_status-kdoc-v1-1-e59f4b814b88@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/hal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 0ee9c6b26dab4..c1750b5dc03cb 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -585,7 +585,8 @@ enum hal_reo_cmd_type { * or cache was blocked * @HAL_REO_CMD_FAILED: Command execution failed, could be due to * invalid queue desc - * @HAL_REO_CMD_RESOURCE_BLOCKED: + * @HAL_REO_CMD_RESOURCE_BLOCKED: Command could not be executed because + * one or more descriptors were blocked * @HAL_REO_CMD_DRAIN: */ enum hal_reo_cmd_status { -- GitLab From f3fe49dbddd73f0155a8935af47cb63693069dbe Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Wed, 4 Jun 2025 13:52:50 +0800 Subject: [PATCH 271/902] wifi: ath12k: fix uaf in ath12k_core_init() When the execution of ath12k_core_hw_group_assign() or ath12k_core_hw_group_create() fails, the registered notifier chain is not unregistered properly. Its memory is freed after rmmod, which may trigger to a use-after-free (UAF) issue if there is a subsequent access to this notifier chain. Fixes the issue by calling ath12k_core_panic_notifier_unregister() in failure cases. Call trace: notifier_chain_register+0x4c/0x1f0 (P) atomic_notifier_chain_register+0x38/0x68 ath12k_core_init+0x50/0x4e8 [ath12k] ath12k_pci_probe+0x5f8/0xc28 [ath12k] pci_device_probe+0xbc/0x1a8 really_probe+0xc8/0x3a0 __driver_probe_device+0x84/0x1b0 driver_probe_device+0x44/0x130 __driver_attach+0xcc/0x208 bus_for_each_dev+0x84/0x100 driver_attach+0x2c/0x40 bus_add_driver+0x130/0x260 driver_register+0x70/0x138 __pci_register_driver+0x68/0x80 ath12k_pci_init+0x30/0x68 [ath12k] ath12k_init+0x28/0x78 [ath12k] Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Fixes: 6f245ea0ec6c ("wifi: ath12k: introduce device group abstraction") Signed-off-by: Miaoqing Pan Reviewed-by: Baochen Qiang Link: https://patch.msgid.link/20250604055250.1228501-1-miaoqing.pan@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 31d851d8e6883..ebc0560d40e34 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -2129,7 +2129,8 @@ int ath12k_core_init(struct ath12k_base *ab) if (!ag) { mutex_unlock(&ath12k_hw_group_mutex); ath12k_warn(ab, "unable to get hw group\n"); - return -ENODEV; + ret = -ENODEV; + goto err_unregister_notifier; } mutex_unlock(&ath12k_hw_group_mutex); @@ -2144,7 +2145,7 @@ int ath12k_core_init(struct ath12k_base *ab) if (ret) { mutex_unlock(&ag->mutex); ath12k_warn(ab, "unable to create hw group\n"); - goto err; + goto err_destroy_hw_group; } } @@ -2152,9 +2153,12 @@ int ath12k_core_init(struct ath12k_base *ab) return 0; -err: +err_destroy_hw_group: ath12k_core_hw_group_destroy(ab->ag); ath12k_core_hw_group_unassign(ab); +err_unregister_notifier: + ath12k_core_panic_notifier_unregister(ab); + return ret; } -- GitLab From 06118ae36855b7d3d22688298e74a766ccf0cb7a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 27 May 2025 08:44:14 +0300 Subject: [PATCH 272/902] regulator: max20086: Fix refcount leak in max20086_parse_regulators_dt() There is a missing call to of_node_put() if devm_kcalloc() fails. Fix this by changing the code to use cleanup.h magic to drop the refcount. Fixes: 6b0cd72757c6 ("regulator: max20086: fix invalid memory access") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/aDVRLqgJWMxYU03G@stanley.mountain Reviewed-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/regulator/max20086-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index b4fe76e33ff27..fcdd2d0317a57 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -5,6 +5,7 @@ // Copyright (C) 2022 Laurent Pinchart // Copyright (C) 2018 Avnet, Inc. +#include #include #include #include @@ -133,11 +134,11 @@ static int max20086_regulators_register(struct max20086 *chip) static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) { struct of_regulator_match *matches; - struct device_node *node; unsigned int i; int ret; - node = of_get_child_by_name(chip->dev->of_node, "regulators"); + struct device_node *node __free(device_node) = + of_get_child_by_name(chip->dev->of_node, "regulators"); if (!node) { dev_err(chip->dev, "regulators node not found\n"); return -ENODEV; @@ -153,7 +154,6 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) ret = of_regulator_match(chip->dev, node, matches, chip->info->num_outputs); - of_node_put(node); if (ret < 0) { dev_err(chip->dev, "Failed to match regulators\n"); return -EINVAL; -- GitLab From a5bf5272295d3f058adeee025d2a0b6625f8ba7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Fri, 6 Jun 2025 15:37:24 +0200 Subject: [PATCH 273/902] spi: omap2-mcspi: Disable multi mode when CS should be kept asserted after message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the last transfer of a SPI message has the cs_change flag, the CS is kept asserted after the message. Multi-mode can't respect this as CS is deasserted by the hardware at the end of the message. Disable multi-mode when not applicable to the current message. Fixes: d153ff4056cb ("spi: omap2-mcspi: Add support for MULTI-mode") Signed-off-by: Félix Piédallu Link: https://patch.msgid.link/20250606-cs_change_fix-v1-1-27191a98a2e5@non.se.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 29c616e2c408c..e834fb42fd4ba 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1287,9 +1287,15 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, mcspi->use_multi_mode = false; } - /* Check if transfer asks to change the CS status after the transfer */ - if (!tr->cs_change) - mcspi->use_multi_mode = false; + if (list_is_last(&tr->transfer_list, &msg->transfers)) { + /* Check if transfer asks to keep the CS status after the whole message */ + if (tr->cs_change) + mcspi->use_multi_mode = false; + } else { + /* Check if transfer asks to change the CS status after the transfer */ + if (!tr->cs_change) + mcspi->use_multi_mode = false; + } /* * If at least one message is not compatible, switch back to single mode -- GitLab From 10c24e0d2f7cd2bc8a847cf750f01301ce67dbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Fri, 6 Jun 2025 15:37:25 +0200 Subject: [PATCH 274/902] spi: omap2-mcspi: Disable multi-mode when the previous message kept CS asserted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the last transfer of a SPI message has the cs_change flag, the CS is kept asserted after the message. The next message can't use multi-mode because the CS will be briefly deasserted before the first transfer. Remove the early exit of the list_for_each_entry because the last transfer actually needs to be always checked. Fixes: d153ff4056cb ("spi: omap2-mcspi: Add support for MULTI-mode") Signed-off-by: Félix Piédallu Link: https://patch.msgid.link/20250606-cs_change_fix-v1-2-27191a98a2e5@non.se.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index e834fb42fd4ba..70bb74b3bd9c3 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -134,6 +134,7 @@ struct omap2_mcspi { size_t max_xfer_len; u32 ref_clk_hz; bool use_multi_mode; + bool last_msg_kept_cs; }; struct omap2_mcspi_cs { @@ -1269,6 +1270,10 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, * multi-mode is applicable. */ mcspi->use_multi_mode = true; + + if (mcspi->last_msg_kept_cs) + mcspi->use_multi_mode = false; + list_for_each_entry(tr, &msg->transfers, transfer_list) { if (!tr->bits_per_word) bits_per_word = msg->spi->bits_per_word; @@ -1289,22 +1294,17 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, if (list_is_last(&tr->transfer_list, &msg->transfers)) { /* Check if transfer asks to keep the CS status after the whole message */ - if (tr->cs_change) + if (tr->cs_change) { mcspi->use_multi_mode = false; + mcspi->last_msg_kept_cs = true; + } else { + mcspi->last_msg_kept_cs = false; + } } else { /* Check if transfer asks to change the CS status after the transfer */ if (!tr->cs_change) mcspi->use_multi_mode = false; } - - /* - * If at least one message is not compatible, switch back to single mode - * - * The bits_per_word of certain transfer can be different, but it will have no - * impact on the signal itself. - */ - if (!mcspi->use_multi_mode) - break; } omap2_mcspi_set_mode(ctlr); -- GitLab From 1dd630088332b5b310f3dd7eaacae9f3c4465651 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sun, 8 Jun 2025 22:29:39 +0800 Subject: [PATCH 275/902] spi: loongson: Fix build warnings about export.h After commit a934a57a42f64a4 ("scripts/misc-check: check missing #include when W=1") and 7d95680d64ac8e836c ("scripts/misc-check: check unnecessary #include when W=1"), we get some build warnings with W=1: drivers/spi/spi-loongson-core.c: warning: EXPORT_SYMBOL() is used, but #include is missing So fix these build warnings for SPI/Loongson. Signed-off-by: Huacai Chen Link: https://patch.msgid.link/20250608142939.172108-1-chenhuacai@loongson.cn Signed-off-by: Mark Brown --- drivers/spi/spi-loongson-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c index 4fec226456d1b..b46f072a0387b 100644 --- a/drivers/spi/spi-loongson-core.c +++ b/drivers/spi/spi-loongson-core.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include -- GitLab From 2b74aea6d078ade810a3b0f7d1bcfcba2eaad416 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 6 Jun 2025 12:04:14 +0300 Subject: [PATCH 276/902] spi: spi-pci1xxxx: Fix error code in probe Return the error code if pci_alloc_irq_vectors() fails. Don't return success. Fixes: b4608e944177 ("spi: spi-pci1xxxx: Fix Probe failure with Dual SPI instance with INTx interrupts") Signed-off-by: Dan Carpenter Reviewed-by: Thangaraj Samynathan Link: https://patch.msgid.link/aEKvDrUxD19GWi0u@stanley.mountain Signed-off-by: Mark Brown --- drivers/spi/spi-pci1xxxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index c6489e90b8b9c..9112d8a1a0c82 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -765,7 +765,7 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * PCI_IRQ_ALL_TYPES); if (num_vector < 0) { dev_err(&pdev->dev, "Error allocating MSI vectors\n"); - return ret; + return num_vector; } init_completion(&spi_sub_ptr->spi_xfer_done); -- GitLab From 83c4c67076c209787515e06fffd41dd0bdab09b9 Mon Sep 17 00:00:00 2001 From: "James A. MacInnes" Date: Wed, 12 Feb 2025 15:03:46 -0800 Subject: [PATCH 277/902] drm/msm/dp: Disable wide bus support for SDM845 When widebus was enabled for DisplayPort in commit c7c412202623 ("drm/msm/dp: enable widebus on all relevant chipsets") it was clarified that it is only supported on DPU 5.0.0 onwards which includes SC7180 on DPU revision 6.2. However, this patch missed that the description structure for SC7180 is also reused for SDM845 (because of identical io_start address) which is only DPU 4.0.0, leading to a wrongly enbled widebus feature and corruption on that platform. Create a separate msm_dp_desc_sdm845 structure for this SoC compatible, with the wide_bus_supported flag turned off. Fixes: c7c412202623 ("drm/msm/dp: enable widebus on all relevant chipsets") Signed-off-by: James A. MacInnes [DB: reworded commit text following Marijn's suggestion] Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/636944/ Link: https://lore.kernel.org/r/20250212-sdm845_dp-v2-1-4954e51458f4@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 386c4669c831e..a48e6db4f156a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -128,6 +128,11 @@ static const struct msm_dp_desc msm_dp_desc_sa8775p[] = { {} }; +static const struct msm_dp_desc msm_dp_desc_sdm845[] = { + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 }, + {} +}; + static const struct msm_dp_desc msm_dp_desc_sc7180[] = { { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, {} @@ -180,7 +185,7 @@ static const struct of_device_id msm_dp_dt_match[] = { { .compatible = "qcom,sc8180x-edp", .data = &msm_dp_desc_sc8180x }, { .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp }, { .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp }, - { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 }, + { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sdm845 }, { .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 }, { .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 }, -- GitLab From 146e87f3e11de0dfa091ff87e34b4bc6eec761a4 Mon Sep 17 00:00:00 2001 From: "James A. MacInnes" Date: Wed, 12 Feb 2025 15:03:47 -0800 Subject: [PATCH 278/902] drm/msm/disp: Correct porch timing for SDM845 Type-C DisplayPort inoperable due to incorrect porch settings. - Re-used wide_bus_en as flag to prevent porch shifting Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: James A. MacInnes Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/636945/ Link: https://lore.kernel.org/r/20250212-sdm845_dp-v2-2-4954e51458f4@gmail.com Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 8a618841e3ea8..1c468ca5d692b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -94,17 +94,21 @@ static void drm_mode_to_intf_timing_params( timing->vsync_polarity = 0; } - /* for DP/EDP, Shift timings to align it to bottom right */ - if (phys_enc->hw_intf->cap->type == INTF_DP) { + timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); + + /* + * For DP/EDP, Shift timings to align it to bottom right. + * wide_bus_en is set for everything excluding SDM845 & + * porch changes cause DisplayPort failure and HDMI tearing. + */ + if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { timing->h_back_porch += timing->h_front_porch; timing->h_front_porch = 0; timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; } - timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); - timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); - /* * for DP, divide the horizonal parameters by 2 when * widebus is enabled -- GitLab From 8a48e35becb214743214f5504e726c3ec131cd6d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 20 May 2025 13:13:26 +0200 Subject: [PATCH 279/902] drm/msm/dsi/dsi_phy_10nm: Fix missing initial VCO rate Driver unconditionally saves current state on first init in dsi_pll_10nm_init(), but does not save the VCO rate, only some of the divider registers. The state is then restored during probe/enable via msm_dsi_phy_enable() -> msm_dsi_phy_pll_restore_state() -> dsi_10nm_pll_restore_state(). Restoring calls dsi_pll_10nm_vco_set_rate() with pll_10nm->vco_current_rate=0, which basically overwrites existing rate of VCO and messes with clock hierarchy, by setting frequency to 0 to clock tree. This makes anyway little sense - VCO rate was not saved, so should not be restored. If PLL was not configured configure it to minimum rate to avoid glitches and configuring entire in clock hierarchy to 0 Hz. Suggested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/sz4kbwy5nwsebgf64ia7uq4ee7wbsa5uy3xmlqwcstsbntzcov@ew3dcyjdzmi2/ Signed-off-by: Krzysztof Kozlowski Fixes: a4ccc37693a2 ("drm/msm/dsi_pll_10nm: restore VCO rate during Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/654796/ Link: https://lore.kernel.org/r/20250520111325.92352-2-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 9812b4d691979..af2e30f3f842a 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -704,6 +704,13 @@ static int dsi_pll_10nm_init(struct msm_dsi_phy *phy) /* TODO: Remove this when we have proper display handover support */ msm_dsi_phy_pll_save_state(phy); + /* + * Store also proper vco_current_rate, because its value will be used in + * dsi_10nm_pll_restore_state(). + */ + if (!dsi_pll_10nm_vco_recalc_rate(&pll_10nm->clk_hw, VCO_REF_CLK_RATE)) + pll_10nm->vco_current_rate = pll_10nm->phy->cfg->min_pll_rate; + return 0; } -- GitLab From 9a2d22a46b385eb297aba88180ce358977d7fd88 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 5 Jun 2025 09:46:44 +0200 Subject: [PATCH 280/902] drm/xe: Remove IOSF_MBI select. IOSF_MBI was only useful for some gen8 platforms, which were never supported by Xe. Presumably needed for display at one point, but display is fixed to put stubs in compat-i915-headers/vlv_sideband.h. (in drm-intel-next: vlv_iosf_sb.h) Link: https://lore.kernel.org/r/20250605074644.71036-1-dev@lankhorst.se Reviewed-by: Lucas De Marchi Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 98b46c5342787..93de829621720 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -31,7 +31,6 @@ config DRM_XE select ACPI_VIDEO if X86 && ACPI select ACPI_WMI if X86 && ACPI select SYNC_FILE - select IOSF_MBI select CRC32 select SND_HDA_I915 if SND_HDA_CORE select CEC_CORE if CEC_NOTIFIER -- GitLab From 56ec63a6e107e724619e61c7e605b49d365dfa07 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 13 May 2025 21:38:59 +0300 Subject: [PATCH 281/902] pinctrl: qcom: switch to devm_gpiochip_add_data() In order to simplify cleanup actions, use devres-enabled version of gpiochip_add_data(). As the msm_pinctrl_remove() function is now empty, drop it and all its calls from the corresponding pinctrl drivers. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/20250513-pinctrl-msm-fix-v2-3-249999af0fc1@oss.qualcomm.com Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-apq8064.c | 1 - drivers/pinctrl/qcom/pinctrl-apq8084.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq5018.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq5332.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq5424.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq6018.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq8064.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq8074.c | 1 - drivers/pinctrl/qcom/pinctrl-ipq9574.c | 1 - drivers/pinctrl/qcom/pinctrl-mdm9607.c | 1 - drivers/pinctrl/qcom/pinctrl-mdm9615.c | 1 - drivers/pinctrl/qcom/pinctrl-msm.c | 11 +---------- drivers/pinctrl/qcom/pinctrl-msm.h | 1 - drivers/pinctrl/qcom/pinctrl-msm8226.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8660.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8909.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8916.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8917.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8953.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8960.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8976.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8994.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8996.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8998.c | 1 - drivers/pinctrl/qcom/pinctrl-msm8x74.c | 1 - drivers/pinctrl/qcom/pinctrl-qcm2290.c | 1 - drivers/pinctrl/qcom/pinctrl-qcs404.c | 1 - drivers/pinctrl/qcom/pinctrl-qcs615.c | 1 - drivers/pinctrl/qcom/pinctrl-qcs8300.c | 1 - drivers/pinctrl/qcom/pinctrl-qdf2xxx.c | 1 - drivers/pinctrl/qcom/pinctrl-qdu1000.c | 1 - drivers/pinctrl/qcom/pinctrl-sa8775p.c | 1 - drivers/pinctrl/qcom/pinctrl-sar2130p.c | 1 - drivers/pinctrl/qcom/pinctrl-sc7180.c | 1 - drivers/pinctrl/qcom/pinctrl-sc7280.c | 1 - drivers/pinctrl/qcom/pinctrl-sc8180x.c | 1 - drivers/pinctrl/qcom/pinctrl-sc8280xp.c | 1 - drivers/pinctrl/qcom/pinctrl-sdm660.c | 1 - drivers/pinctrl/qcom/pinctrl-sdm670.c | 1 - drivers/pinctrl/qcom/pinctrl-sdm845.c | 1 - drivers/pinctrl/qcom/pinctrl-sdx55.c | 1 - drivers/pinctrl/qcom/pinctrl-sdx65.c | 1 - drivers/pinctrl/qcom/pinctrl-sdx75.c | 1 - drivers/pinctrl/qcom/pinctrl-sm4450.c | 1 - drivers/pinctrl/qcom/pinctrl-sm6115.c | 1 - drivers/pinctrl/qcom/pinctrl-sm6125.c | 1 - drivers/pinctrl/qcom/pinctrl-sm6350.c | 1 - drivers/pinctrl/qcom/pinctrl-sm6375.c | 1 - drivers/pinctrl/qcom/pinctrl-sm7150.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8150.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8250.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8350.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8450.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8550.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8650.c | 1 - drivers/pinctrl/qcom/pinctrl-sm8750.c | 1 - drivers/pinctrl/qcom/pinctrl-x1e80100.c | 1 - 58 files changed, 1 insertion(+), 67 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c index 20c3b90250445..3654913f1ae58 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c @@ -629,7 +629,6 @@ static struct platform_driver apq8064_pinctrl_driver = { .of_match_table = apq8064_pinctrl_of_match, }, .probe = apq8064_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init apq8064_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c index 3fc0a40762b63..27693cd648818 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8084.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c @@ -1207,7 +1207,6 @@ static struct platform_driver apq8084_pinctrl_driver = { .of_match_table = apq8084_pinctrl_of_match, }, .probe = apq8084_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init apq8084_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 1f7944dd829d1..6ede3149b6e17 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -710,7 +710,6 @@ static struct platform_driver ipq4019_pinctrl_driver = { .of_match_table = ipq4019_pinctrl_of_match, }, .probe = ipq4019_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq4019_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c index e2951f81c3eeb..10b99d5d8a11d 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c @@ -754,7 +754,6 @@ static struct platform_driver ipq5018_pinctrl_driver = { .of_match_table = ipq5018_pinctrl_of_match, }, .probe = ipq5018_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5018_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c index 625f8014051f6..1ac2fc09c1192 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c @@ -834,7 +834,6 @@ static struct platform_driver ipq5332_pinctrl_driver = { .of_match_table = ipq5332_pinctrl_of_match, }, .probe = ipq5332_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5332_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5424.c b/drivers/pinctrl/qcom/pinctrl-ipq5424.c index 0d610b076da3b..7ff1f8acc1a3a 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5424.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5424.c @@ -791,7 +791,6 @@ static struct platform_driver ipq5424_pinctrl_driver = { .of_match_table = ipq5424_pinctrl_of_match, }, .probe = ipq5424_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5424_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c index 0ad08647dbcdf..a4ba980252e18 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -1080,7 +1080,6 @@ static struct platform_driver ipq6018_pinctrl_driver = { .of_match_table = ipq6018_pinctrl_of_match, }, .probe = ipq6018_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq6018_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index e2bb94e86aef6..0a9e357e64c60 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -631,7 +631,6 @@ static struct platform_driver ipq8064_pinctrl_driver = { .of_match_table = ipq8064_pinctrl_of_match, }, .probe = ipq8064_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq8064_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c index 337f3a1c92c19..482f13282fc2b 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c @@ -1041,7 +1041,6 @@ static struct platform_driver ipq8074_pinctrl_driver = { .of_match_table = ipq8074_pinctrl_of_match, }, .probe = ipq8074_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq8074_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c index e2491617b2364..89c05d8eb5503 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c @@ -799,7 +799,6 @@ static struct platform_driver ipq9574_pinctrl_driver = { .of_match_table = ipq9574_pinctrl_of_match, }, .probe = ipq9574_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq9574_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c index e7cd3ef1cf3e8..3e18ba124fede 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c @@ -1059,7 +1059,6 @@ static struct platform_driver mdm9607_pinctrl_driver = { .of_match_table = mdm9607_pinctrl_of_match, }, .probe = mdm9607_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init mdm9607_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c index 0a2ae383d3d57..bea1ca3d1b7f8 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c @@ -446,7 +446,6 @@ static struct platform_driver mdm9615_pinctrl_driver = { .of_match_table = mdm9615_pinctrl_of_match, }, .probe = mdm9615_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init mdm9615_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index f012ea88aa22c..5c4687de1464a 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1442,7 +1442,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) girq->handler = handle_bad_irq; girq->parents[0] = pctrl->irq; - ret = gpiochip_add_data(&pctrl->chip, pctrl); + ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); if (ret) { dev_err(pctrl->dev, "Failed register gpiochip\n"); return ret; @@ -1463,7 +1463,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) dev_name(pctrl->dev), 0, 0, chip->ngpio); if (ret) { dev_err(pctrl->dev, "Failed to add pin range\n"); - gpiochip_remove(&pctrl->chip); return ret; } } @@ -1599,13 +1598,5 @@ int msm_pinctrl_probe(struct platform_device *pdev, } EXPORT_SYMBOL(msm_pinctrl_probe); -void msm_pinctrl_remove(struct platform_device *pdev) -{ - struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); - - gpiochip_remove(&pctrl->chip); -} -EXPORT_SYMBOL(msm_pinctrl_remove); - MODULE_DESCRIPTION("Qualcomm Technologies, Inc. TLMM driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 63852ed702957..d7dc0947bb161 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -171,6 +171,5 @@ extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops; int msm_pinctrl_probe(struct platform_device *pdev, const struct msm_pinctrl_soc_data *soc_data); -void msm_pinctrl_remove(struct platform_device *pdev); #endif diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c index 64fee70f1772c..f9a9573473408 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8226.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c @@ -654,7 +654,6 @@ static struct platform_driver msm8226_pinctrl_driver = { .of_match_table = msm8226_pinctrl_of_match, }, .probe = msm8226_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8226_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c index 999a5f867eb50..4dbc19ffd80ef 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8660.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c @@ -981,7 +981,6 @@ static struct platform_driver msm8660_pinctrl_driver = { .of_match_table = msm8660_pinctrl_of_match, }, .probe = msm8660_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8660_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c index 756856d20d6b5..0aa4f77b774f4 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8909.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c @@ -929,7 +929,6 @@ static struct platform_driver msm8909_pinctrl_driver = { .of_match_table = msm8909_pinctrl_of_match, }, .probe = msm8909_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8909_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c index cea5c54f92fec..0dfc6dd33d58b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8916.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c @@ -969,7 +969,6 @@ static struct platform_driver msm8916_pinctrl_driver = { .of_match_table = msm8916_pinctrl_of_match, }, .probe = msm8916_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8916_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8917.c b/drivers/pinctrl/qcom/pinctrl-msm8917.c index 350636807b07d..2e1a94ab18b21 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8917.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8917.c @@ -1607,7 +1607,6 @@ static struct platform_driver msm8917_pinctrl_driver = { .of_match_table = msm8917_pinctrl_of_match, }, .probe = msm8917_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8917_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c index 998351bdfee13..956383341a7a7 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8953.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c @@ -1816,7 +1816,6 @@ static struct platform_driver msm8953_pinctrl_driver = { .of_match_table = msm8953_pinctrl_of_match, }, .probe = msm8953_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8953_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c index ebe230b3b437c..a937ea867de70 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8960.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c @@ -1246,7 +1246,6 @@ static struct platform_driver msm8960_pinctrl_driver = { .of_match_table = msm8960_pinctrl_of_match, }, .probe = msm8960_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8960_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c index c30d80e4e98ca..3bcb03387781f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8976.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c @@ -1096,7 +1096,6 @@ static struct platform_driver msm8976_pinctrl_driver = { .of_match_table = msm8976_pinctrl_of_match, }, .probe = msm8976_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8976_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c index b1a6759ab4a5e..7a3b6cbccb687 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8994.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -1343,7 +1343,6 @@ static struct platform_driver msm8994_pinctrl_driver = { .of_match_table = msm8994_pinctrl_of_match, }, .probe = msm8994_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8994_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c index 1b5d80eaab83c..d86d83106d3ba 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8996.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c @@ -1920,7 +1920,6 @@ static struct platform_driver msm8996_pinctrl_driver = { .of_match_table = msm8996_pinctrl_of_match, }, .probe = msm8996_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8996_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c index b7cbf32b3125a..1daee815888f5 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8998.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c @@ -1535,7 +1535,6 @@ static struct platform_driver msm8998_pinctrl_driver = { .of_match_table = msm8998_pinctrl_of_match, }, .probe = msm8998_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8998_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c index 238c83f6ec4f4..8253aa25775b2 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c @@ -1083,7 +1083,6 @@ static struct platform_driver msm8x74_pinctrl_driver = { .of_match_table = msm8x74_pinctrl_of_match, }, .probe = msm8x74_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8x74_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index f885af571ec93..85c951305abd6 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -1125,7 +1125,6 @@ static struct platform_driver qcm2290_pinctrl_driver = { .of_match_table = qcm2290_pinctrl_of_match, }, .probe = qcm2290_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcm2290_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index ae7224012f8aa..54e3b44353494 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -1644,7 +1644,6 @@ static struct platform_driver qcs404_pinctrl_driver = { .of_match_table = qcs404_pinctrl_of_match, }, .probe = qcs404_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs404_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615.c b/drivers/pinctrl/qcom/pinctrl-qcs615.c index 17ca743c2210f..2a943bc46a629 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs615.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs615.c @@ -1087,7 +1087,6 @@ static struct platform_driver qcs615_tlmm_driver = { .of_match_table = qcs615_tlmm_of_match, }, .probe = qcs615_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs615_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs8300.c b/drivers/pinctrl/qcom/pinctrl-qcs8300.c index 5f5f7c4ac644c..d6437e26392b6 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs8300.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs8300.c @@ -1227,7 +1227,6 @@ static struct platform_driver qcs8300_pinctrl_driver = { .of_match_table = qcs8300_pinctrl_of_match, }, .probe = qcs8300_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs8300_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c index b5808fcfb13cd..9ecc4d40e4dc4 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c +++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c @@ -145,7 +145,6 @@ static struct platform_driver qdf2xxx_pinctrl_driver = { .acpi_match_table = qdf2xxx_acpi_ids, }, .probe = qdf2xxx_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qdf2xxx_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c index 47bc529ef550d..eacb89fa38885 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c +++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c @@ -1248,7 +1248,6 @@ static struct platform_driver qdu1000_tlmm_driver = { .of_match_table = qdu1000_tlmm_of_match, }, .probe = qdu1000_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init qdu1000_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index a5b38221aea85..1b62eb3e6620c 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -1540,7 +1540,6 @@ static struct platform_driver sa8775p_pinctrl_driver = { .of_match_table = sa8775p_pinctrl_of_match, }, .probe = sa8775p_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sa8775p_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sar2130p.c b/drivers/pinctrl/qcom/pinctrl-sar2130p.c index 19a2e37826c7b..3dd1b5e5cfee4 100644 --- a/drivers/pinctrl/qcom/pinctrl-sar2130p.c +++ b/drivers/pinctrl/qcom/pinctrl-sar2130p.c @@ -1486,7 +1486,6 @@ static struct platform_driver sar2130p_tlmm_driver = { .of_match_table = sar2130p_tlmm_of_match, }, .probe = sar2130p_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sar2130p_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c index 6eb0c73791c0b..c43fe10b71add 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7180.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c @@ -1159,7 +1159,6 @@ static struct platform_driver sc7180_pinctrl_driver = { .of_match_table = sc7180_pinctrl_of_match, }, .probe = sc7180_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc7180_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 0c10eeb60b55e..1b070e9d41f59 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -1505,7 +1505,6 @@ static struct platform_driver sc7280_pinctrl_driver = { .of_match_table = sc7280_pinctrl_of_match, }, .probe = sc7280_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc7280_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c index d6a79ad41a40a..26dd165d15434 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c @@ -1720,7 +1720,6 @@ static struct platform_driver sc8180x_pinctrl_driver = { .acpi_match_table = sc8180x_pinctrl_acpi_match, }, .probe = sc8180x_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc8180x_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c index 96f4fb5a5d297..6ccd7e5648d42 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c @@ -1926,7 +1926,6 @@ static struct platform_driver sc8280xp_pinctrl_driver = { .of_match_table = sc8280xp_pinctrl_of_match, }, .probe = sc8280xp_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc8280xp_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c index 907e4ffca5e7d..1a78288f1bc83 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm660.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c @@ -1442,7 +1442,6 @@ static struct platform_driver sdm660_pinctrl_driver = { .of_match_table = sdm660_pinctrl_of_match, }, .probe = sdm660_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm660_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c index c76183ba95e17..0fe1fa94cd6da 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm670.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c @@ -1337,7 +1337,6 @@ static struct platform_driver sdm670_pinctrl_driver = { .of_match_table = sdm670_pinctrl_of_match, }, .probe = sdm670_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm670_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index cc05c415ed155..0446e291aa483 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -1351,7 +1351,6 @@ static struct platform_driver sdm845_pinctrl_driver = { .acpi_match_table = ACPI_PTR(sdm845_pinctrl_acpi_match), }, .probe = sdm845_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm845_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c index 8826db9d21d04..2c17bf8891463 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx55.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c @@ -990,7 +990,6 @@ static struct platform_driver sdx55_pinctrl_driver = { .of_match_table = sdx55_pinctrl_of_match, }, .probe = sdx55_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx55_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c index f6f319c997fc7..85b5c0206dbd1 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx65.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c @@ -939,7 +939,6 @@ static struct platform_driver sdx65_pinctrl_driver = { .of_match_table = sdx65_pinctrl_of_match, }, .probe = sdx65_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx65_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c index 3cfe8c7f04df8..ab13a3a57a830 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx75.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c @@ -1124,7 +1124,6 @@ static struct platform_driver sdx75_pinctrl_driver = { .of_match_table = sdx75_pinctrl_of_match, }, .probe = sdx75_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx75_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm4450.c b/drivers/pinctrl/qcom/pinctrl-sm4450.c index 622f20e6f6f85..1ecdf1ab4f275 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm4450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm4450.c @@ -994,7 +994,6 @@ static struct platform_driver sm4450_tlmm_driver = { .of_match_table = sm4450_tlmm_of_match, }, .probe = sm4450_tlmm_probe, - .remove = msm_pinctrl_remove, }; MODULE_DEVICE_TABLE(of, sm4450_tlmm_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c index 4e91c75ad9524..c273efa439963 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6115.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c @@ -907,7 +907,6 @@ static struct platform_driver sm6115_tlmm_driver = { .of_match_table = sm6115_tlmm_of_match, }, .probe = sm6115_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6115_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c index c188842047aae..5092f20e0c1bd 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6125.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c @@ -1266,7 +1266,6 @@ static struct platform_driver sm6125_tlmm_driver = { .of_match_table = sm6125_tlmm_of_match, }, .probe = sm6125_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6125_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c index f3828c07b1345..ba4686c86c54b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c @@ -1373,7 +1373,6 @@ static struct platform_driver sm6350_tlmm_driver = { .of_match_table = sm6350_tlmm_of_match, }, .probe = sm6350_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6350_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c index c82c8516932ea..49031571e65ee 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6375.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c @@ -1516,7 +1516,6 @@ static struct platform_driver sm6375_tlmm_driver = { .of_match_table = sm6375_tlmm_of_match, }, .probe = sm6375_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6375_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c index 3c7fd8af6635b..6e89966cd70e3 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm7150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c @@ -1255,7 +1255,6 @@ static struct platform_driver sm7150_tlmm_driver = { .of_match_table = sm7150_tlmm_of_match, }, .probe = sm7150_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm7150_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 01aea9c70b7a7..794ed99463f76 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -1542,7 +1542,6 @@ static struct platform_driver sm8150_pinctrl_driver = { .of_match_table = sm8150_pinctrl_of_match, }, .probe = sm8150_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8150_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index e9961a49ff981..fb6f005d64f53 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -1351,7 +1351,6 @@ static struct platform_driver sm8250_pinctrl_driver = { .of_match_table = sm8250_pinctrl_of_match, }, .probe = sm8250_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8250_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c index 9c69458bd9109..c8a3f39ce6f1b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c @@ -1642,7 +1642,6 @@ static struct platform_driver sm8350_tlmm_driver = { .of_match_table = sm8350_tlmm_of_match, }, .probe = sm8350_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8350_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c index d11bb1ee9e3d8..f2e52d5a0f936 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c @@ -1677,7 +1677,6 @@ static struct platform_driver sm8450_tlmm_driver = { .of_match_table = sm8450_tlmm_of_match, }, .probe = sm8450_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8450_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index 3c847d9cb5d93..1b4496cb39eb4 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -1762,7 +1762,6 @@ static struct platform_driver sm8550_tlmm_driver = { .of_match_table = sm8550_tlmm_of_match, }, .probe = sm8550_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8550_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650.c b/drivers/pinctrl/qcom/pinctrl-sm8650.c index 104708252d12a..449a0077f4b10 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8650.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8650.c @@ -1742,7 +1742,6 @@ static struct platform_driver sm8650_tlmm_driver = { .of_match_table = sm8650_tlmm_of_match, }, .probe = sm8650_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8650_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8750.c b/drivers/pinctrl/qcom/pinctrl-sm8750.c index b94fb4ee0ec38..8516693d1db51 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8750.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8750.c @@ -1711,7 +1711,6 @@ static struct platform_driver sm8750_tlmm_driver = { .of_match_table = sm8750_tlmm_of_match, }, .probe = sm8750_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8750_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c index 419cb8facb2f3..d4b215f34c39b 100644 --- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -1861,7 +1861,6 @@ static struct platform_driver x1e80100_pinctrl_driver = { .of_match_table = x1e80100_pinctrl_of_match, }, .probe = x1e80100_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init x1e80100_pinctrl_init(void) -- GitLab From 315345610faee8a0568b522dba9e35067d1732ab Mon Sep 17 00:00:00 2001 From: Wojciech Slenska Date: Fri, 23 May 2025 12:14:37 +0200 Subject: [PATCH 282/902] pinctrl: qcom: pinctrl-qcm2290: Add missing pins Added the missing pins to the qcm2290_pins table. Signed-off-by: Wojciech Slenska Fixes: 48e049ef1238 ("pinctrl: qcom: Add QCM2290 pinctrl driver") Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/20250523101437.59092-1-wojciech.slenska@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-qcm2290.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index 85c951305abd6..eeeec6434f6a6 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -167,6 +167,10 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = { PINCTRL_PIN(62, "GPIO_62"), PINCTRL_PIN(63, "GPIO_63"), PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), PINCTRL_PIN(69, "GPIO_69"), PINCTRL_PIN(70, "GPIO_70"), PINCTRL_PIN(71, "GPIO_71"), @@ -181,12 +185,17 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = { PINCTRL_PIN(80, "GPIO_80"), PINCTRL_PIN(81, "GPIO_81"), PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), PINCTRL_PIN(86, "GPIO_86"), PINCTRL_PIN(87, "GPIO_87"), PINCTRL_PIN(88, "GPIO_88"), PINCTRL_PIN(89, "GPIO_89"), PINCTRL_PIN(90, "GPIO_90"), PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), PINCTRL_PIN(94, "GPIO_94"), PINCTRL_PIN(95, "GPIO_95"), PINCTRL_PIN(96, "GPIO_96"), -- GitLab From fcd65d65fd85dbde090ef8c2615760ebc5ccf9e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 28 May 2025 11:22:02 +0200 Subject: [PATCH 283/902] pinctrl: st: Drop unused st_gpio_bank() function Static inline st_gpio_bank() function is not referenced: pinctrl-st.c:377:19: error: unused function 'st_gpio_bank' [-Werror,-Wunused-function] Fixes: 701016c0cba5 ("pinctrl: st: Add pinctrl and pinconf support.") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/20250528092201.52132-2-krzysztof.kozlowski@linaro.org Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index fe2d52e434db8..8a2ef74862d34 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -374,11 +374,6 @@ static struct st_pio_control *st_get_pio_control( } /* Low level functions.. */ -static inline int st_gpio_bank(int gpio) -{ - return gpio/ST_GPIO_PINS_PER_BANK; -} - static inline int st_gpio_pin(int gpio) { return gpio%ST_GPIO_PINS_PER_BANK; -- GitLab From d38e00c417e1ca0c586802e47ad7d54347c91f67 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 28 May 2025 12:45:15 +0200 Subject: [PATCH 284/902] pinctrl: MAINTAINERS: Drop bouncing Jianlong Huang Emails to Jianlong Huang bounce since 9 months, so drop the person from maintainers: 550 5.4.1 Recipient address rejected: Access denied. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/20250528104514.184122-2-krzysztof.kozlowski@linaro.org Signed-off-by: Linus Walleij --- .../bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml | 2 +- .../bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml | 2 +- MAINTAINERS | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml index b470901f5f562..4dbef86bd9581 100644 --- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml @@ -15,7 +15,7 @@ description: | Some peripherals such as PWM have their I/O go through the 4 "GPIOs". maintainers: - - Jianlong Huang + - Hal Feng properties: compatible: diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml index 222b9e240f8af..e2a25a20f6a6e 100644 --- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml @@ -18,7 +18,7 @@ description: | any GPIO can be set up to be controlled by any of the peripherals. maintainers: - - Jianlong Huang + - Hal Feng properties: compatible: diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa163..4f17af5d7240a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23661,7 +23661,6 @@ F: include/dt-bindings/clock/starfive?jh71*.h STARFIVE JH71X0 PINCTRL DRIVERS M: Emil Renner Berthing -M: Jianlong Huang M: Hal Feng L: linux-gpio@vger.kernel.org S: Maintained -- GitLab From 24b0277c1c539cd41539d9297baafc62df04464a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 1 Jun 2025 12:51:01 +0200 Subject: [PATCH 285/902] pinctrl: tb10x: Drop of_match_ptr for ID table The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). This also fixes !CONFIG_OF warning: pinctrl-tb10x.c:815:34: warning: unused variable 'tb10x_pinctrl_dt_ids' [-Wunused-const-variable] Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202505301317.EI1caRC0-lkp@intel.com/ Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/20250601105100.27927-2-krzysztof.kozlowski@linaro.org Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tb10x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index d6bb8f58978df..4edb20e619510 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -823,7 +823,7 @@ static struct platform_driver tb10x_pinctrl_pdrv = { .remove = tb10x_pinctrl_remove, .driver = { .name = "tb10x_pinctrl", - .of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids), + .of_match_table = tb10x_pinctrl_dt_ids, } }; -- GitLab From 3975d356839e2c1ec53392fb21a0bbac56c2ca3f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:14 +0200 Subject: [PATCH 286/902] drm/xe: Use xe_ggtt_map_bo_unlocked for resume This is the first step to hide the details of struct xe_ggtt. Signed-off-by: Maarten Lankhorst Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250505121924.921544-2-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_bo_evict.c | 4 +--- drivers/gpu/drm/xe/xe_ggtt.c | 16 +++++++++++++++- drivers/gpu/drm/xe/xe_ggtt.h | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo_evict.c b/drivers/gpu/drm/xe/xe_bo_evict.c index ed3746d32b27b..7484ce55a303d 100644 --- a/drivers/gpu/drm/xe/xe_bo_evict.c +++ b/drivers/gpu/drm/xe/xe_bo_evict.c @@ -197,9 +197,7 @@ static int xe_bo_restore_and_map_ggtt(struct xe_bo *bo) if (tile != bo->tile && !(bo->flags & XE_BO_FLAG_GGTTx(tile))) continue; - mutex_lock(&tile->mem.ggtt->lock); - xe_ggtt_map_bo(tile->mem.ggtt, bo); - mutex_unlock(&tile->mem.ggtt->lock); + xe_ggtt_map_bo_unlocked(tile->mem.ggtt, bo); } } diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index b9a0fd5ccaba3..b4bd5e7b27545 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -636,7 +636,7 @@ bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node) * @ggtt: the &xe_ggtt where node will be mapped * @bo: the &xe_bo to be mapped */ -void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) +static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; @@ -654,6 +654,20 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) } } +/** + * xe_ggtt_map_bo_unlocked - Restore a mapping of a BO into GGTT + * @ggtt: the &xe_ggtt where node will be mapped + * @bo: the &xe_bo to be mapped + * + * This is used to restore a GGTT mapping after suspend. + */ +void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) +{ + mutex_lock(&ggtt->lock); + xe_ggtt_map_bo(ggtt, bo); + mutex_unlock(&ggtt->lock); +} + static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, u64 start, u64 end) { diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 4337a279ff3b0..d7dc3abda02cd 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -25,7 +25,7 @@ int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, u32 size, u32 align, u32 mm_flags); void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); -void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo); +void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo); int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo); int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, u64 start, u64 end); -- GitLab From b5fe33dcb8d4b6cf4d4664eaf2432617a7843bf9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:15 +0200 Subject: [PATCH 287/902] drm/xe: Add xe_ggtt_might_lock Another requirement of hiding more of struct xe_ggtt. Signed-off-by: Maarten Lankhorst Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250505121924.921544-3-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_bo.c | 2 +- drivers/gpu/drm/xe/xe_ggtt.c | 7 +++++++ drivers/gpu/drm/xe/xe_ggtt.h | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index f35a7786a56fb..4e39188a021ab 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -3076,7 +3076,7 @@ void xe_bo_put(struct xe_bo *bo) #endif for_each_tile(tile, xe_bo_device(bo), id) if (bo->ggtt_node[id] && bo->ggtt_node[id]->ggtt) - might_lock(&bo->ggtt_node[id]->ggtt->lock); + xe_ggtt_might_lock(bo->ggtt_node[id]->ggtt); drm_gem_object_put(&bo->ttm.base); } } diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index b4bd5e7b27545..bf69737ed5ea8 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -176,6 +176,13 @@ static void ggtt_fini(void *arg) ggtt->scratch = NULL; } +#ifdef CONFIG_LOCKDEP +void xe_ggtt_might_lock(struct xe_ggtt *ggtt) +{ + might_lock(&ggtt->lock); +} +#endif + static void primelockdep(struct xe_ggtt *ggtt) { if (!IS_ENABLED(CONFIG_LOCKDEP)) diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index d7dc3abda02cd..58ba68d32f2e2 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -39,4 +39,11 @@ u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid); #endif +#ifndef CONFIG_LOCKDEP +static inline void xe_ggtt_might_lock(struct xe_ggtt *ggtt) +{ } +#else +void xe_ggtt_might_lock(struct xe_ggtt *ggtt); +#endif + #endif -- GitLab From e0ee402750e12e35a14e8abe794544972eba8c92 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:16 +0200 Subject: [PATCH 288/902] drm/xe: Add xe_ggtt_alloc Instead of allocating inside xe_tile, create a new function that returns an allocated struct xe_ggtt from xe_ggtt.c Signed-off-by: Maarten Lankhorst Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250505121924.921544-4-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_ggtt.c | 16 ++++++++++++++++ drivers/gpu/drm/xe/xe_ggtt.h | 2 ++ drivers/gpu/drm/xe/xe_tile.c | 6 +----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index bf69737ed5ea8..3e5641e0268bf 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -160,6 +160,22 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size) } } +/** + * xe_ggtt_alloc - Allocate a GGTT for a given &xe_tile + * @tile: &xe_tile + * + * Allocates a &xe_ggtt for a given tile. + * + * Return: &xe_ggtt on success, or NULL when out of memory. + */ +struct xe_ggtt *xe_ggtt_alloc(struct xe_tile *tile) +{ + struct xe_ggtt *ggtt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*ggtt), GFP_KERNEL); + if (ggtt) + ggtt->tile = tile; + return ggtt; +} + static void ggtt_fini_early(struct drm_device *drm, void *arg) { struct xe_ggtt *ggtt = arg; diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 58ba68d32f2e2..ceae9a97d76e9 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -9,7 +9,9 @@ #include "xe_ggtt_types.h" struct drm_printer; +struct xe_tile; +struct xe_ggtt *xe_ggtt_alloc(struct xe_tile *tile); int xe_ggtt_init_early(struct xe_ggtt *ggtt); int xe_ggtt_init(struct xe_ggtt *ggtt); diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c index 0771acbbf3676..672faa0b67f16 100644 --- a/drivers/gpu/drm/xe/xe_tile.c +++ b/drivers/gpu/drm/xe/xe_tile.c @@ -87,13 +87,9 @@ */ static int xe_tile_alloc(struct xe_tile *tile) { - struct drm_device *drm = &tile_to_xe(tile)->drm; - - tile->mem.ggtt = drmm_kzalloc(drm, sizeof(*tile->mem.ggtt), - GFP_KERNEL); + tile->mem.ggtt = xe_ggtt_alloc(tile); if (!tile->mem.ggtt) return -ENOMEM; - tile->mem.ggtt->tile = tile; return 0; } -- GitLab From ea54d492853275b92a2407825d61bd8df8760cfd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:17 +0200 Subject: [PATCH 289/902] drm/xe/display: Remove dereferences of ggtt for tile id Obtain the id from the root tile. Likely this can be hardcoded to 0, but use the clean solution of obtaining root id and doing that. to_xe_device(ggtt->tile) can also be easily replaced with xe. Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250505121924.921544-5-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index d918ae1c80618..d509def82b134 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -199,14 +199,15 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, struct drm_gem_object *obj = intel_fb_bo(&fb->base); struct xe_bo *bo = gem_to_xe_bo(obj); struct xe_device *xe = to_xe_device(fb->base.dev); - struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; + struct xe_tile *tile0 = xe_device_get_root_tile(xe); + struct xe_ggtt *ggtt = tile0->mem.ggtt; u32 align; int ret; /* TODO: Consider sharing framebuffer mapping? * embed i915_vma inside intel_framebuffer */ - xe_pm_runtime_get_noresume(tile_to_xe(ggtt->tile)); + xe_pm_runtime_get_noresume(xe); ret = mutex_lock_interruptible(&ggtt->lock); if (ret) goto out; @@ -215,8 +216,8 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) align = max_t(u32, align, SZ_64K); - if (bo->ggtt_node[ggtt->tile->id] && view->type == I915_GTT_VIEW_NORMAL) { - vma->node = bo->ggtt_node[ggtt->tile->id]; + if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { + vma->node = bo->ggtt_node[tile0->id]; } else if (view->type == I915_GTT_VIEW_NORMAL) { u32 x, size = bo->ttm.base.size; @@ -271,7 +272,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, out_unlock: mutex_unlock(&ggtt->lock); out: - xe_pm_runtime_put(tile_to_xe(ggtt->tile)); + xe_pm_runtime_put(xe); return ret; } @@ -348,7 +349,7 @@ err: static void __xe_unpin_fb_vma(struct i915_vma *vma) { - u8 tile_id = vma->node->ggtt->tile->id; + u8 tile_id = xe_device_get_root_tile(xe_bo_device(vma->bo))->id; if (!refcount_dec_and_test(&vma->ref)) return; -- GitLab From 57f6af194fcd4d9901d0060b996dfb0d5543c4b7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:18 +0200 Subject: [PATCH 290/902] drm/xe/ggtt: Seperate flags and address in PTE encoding Pinning large linear display framebuffers is becoming a bottleneck. My plan of attack is doing a custom walk over the BO, this allows for easier optimization of consecutive entries. Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250505121924.921544-6-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_ggtt.c | 85 +++++++++++++++++++++--------- drivers/gpu/drm/xe/xe_ggtt.h | 2 + drivers/gpu/drm/xe/xe_ggtt_types.h | 5 +- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 3e5641e0268bf..82ece4aa9ae2e 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -26,6 +26,7 @@ #include "xe_map.h" #include "xe_mmio.h" #include "xe_pm.h" +#include "xe_res_cursor.h" #include "xe_sriov.h" #include "xe_tile_sriov_vf.h" #include "xe_wa.h" @@ -64,13 +65,9 @@ * give us the correct placement for free. */ -static u64 xelp_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset, - u16 pat_index) +static u64 xelp_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) { - u64 pte; - - pte = xe_bo_addr(bo, bo_offset, XE_PAGE_SIZE); - pte |= XE_PAGE_PRESENT; + u64 pte = XE_PAGE_PRESENT; if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo)) pte |= XE_GGTT_PTE_DM; @@ -78,13 +75,17 @@ static u64 xelp_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset, return pte; } -static u64 xelpg_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset, - u16 pat_index) +static u64 xelp_ggtt_encode_bo(struct xe_bo *bo, u64 bo_offset, u16 pat_index) +{ + return xelp_ggtt_pte_flags(bo, pat_index) | xe_bo_addr(bo, bo_offset, XE_PAGE_SIZE); +} + +static u64 xelpg_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) { struct xe_device *xe = xe_bo_device(bo); u64 pte; - pte = xelp_ggtt_pte_encode_bo(bo, bo_offset, pat_index); + pte = xelp_ggtt_pte_flags(bo, pat_index); xe_assert(xe, pat_index <= 3); @@ -97,6 +98,12 @@ static u64 xelpg_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset, return pte; } +static u64 xelpg_ggtt_encode_bo(struct xe_bo *bo, u64 bo_offset, + u16 pat_index) +{ + return xelpg_ggtt_pte_flags(bo, pat_index) | xe_bo_addr(bo, bo_offset, XE_PAGE_SIZE); +} + static unsigned int probe_gsm_size(struct pci_dev *pdev) { u16 gmch_ctl, ggms; @@ -149,8 +156,9 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size) xe_tile_assert(ggtt->tile, start < end); if (ggtt->scratch) - scratch_pte = ggtt->pt_ops->pte_encode_bo(ggtt->scratch, 0, - pat_index); + scratch_pte = xe_bo_addr(ggtt->scratch, 0, XE_PAGE_SIZE) | + ggtt->pt_ops->pte_encode_flags(ggtt->scratch, + pat_index); else scratch_pte = 0; @@ -210,17 +218,20 @@ static void primelockdep(struct xe_ggtt *ggtt) } static const struct xe_ggtt_pt_ops xelp_pt_ops = { - .pte_encode_bo = xelp_ggtt_pte_encode_bo, + .pte_encode_bo = xelp_ggtt_encode_bo, + .pte_encode_flags = xelp_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte, }; static const struct xe_ggtt_pt_ops xelpg_pt_ops = { - .pte_encode_bo = xelpg_ggtt_pte_encode_bo, + .pte_encode_bo = xelpg_ggtt_encode_bo, + .pte_encode_flags = xelpg_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte, }; static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { - .pte_encode_bo = xelpg_ggtt_pte_encode_bo, + .pte_encode_bo = xelpg_ggtt_encode_bo, + .pte_encode_flags = xelpg_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte_and_flush, }; @@ -657,23 +668,39 @@ bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node) /** * xe_ggtt_map_bo - Map the BO into GGTT * @ggtt: the &xe_ggtt where node will be mapped + * @node: the &xe_ggtt_node where this BO is mapped * @bo: the &xe_bo to be mapped + * @pat_index: Which pat_index to use. */ -static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) +void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, + struct xe_bo *bo, u16 pat_index) { - u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; - u64 start; - u64 offset, pte; - if (XE_WARN_ON(!bo->ggtt_node[ggtt->tile->id])) + u64 start, pte, end; + struct xe_res_cursor cur; + + if (XE_WARN_ON(!node)) return; - start = bo->ggtt_node[ggtt->tile->id]->base.start; + start = node->base.start; + end = start + bo->size; + + pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); + if (!xe_bo_is_vram(bo) && !xe_bo_is_stolen(bo)) { + xe_assert(xe_bo_device(bo), bo->ttm.ttm); + + for (xe_res_first_sg(xe_bo_sg(bo), 0, bo->size, &cur); + cur.remaining; xe_res_next(&cur, XE_PAGE_SIZE)) + ggtt->pt_ops->ggtt_set_pte(ggtt, end - cur.remaining, + pte | xe_res_dma(&cur)); + } else { + /* Prepend GPU offset */ + pte |= vram_region_gpu_offset(bo->ttm.resource); - for (offset = 0; offset < bo->size; offset += XE_PAGE_SIZE) { - pte = ggtt->pt_ops->pte_encode_bo(bo, offset, pat_index); - ggtt->pt_ops->ggtt_set_pte(ggtt, start + offset, pte); + for (xe_res_first(bo->ttm.resource, 0, bo->size, &cur); + cur.remaining; xe_res_next(&cur, XE_PAGE_SIZE)) + ggtt->pt_ops->ggtt_set_pte(ggtt, end - cur.remaining, + pte + cur.start); } } @@ -686,8 +713,11 @@ static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) */ void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) { + u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; + u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + mutex_lock(&ggtt->lock); - xe_ggtt_map_bo(ggtt, bo); + xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pat_index); mutex_unlock(&ggtt->lock); } @@ -727,7 +757,10 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, xe_ggtt_node_fini(bo->ggtt_node[tile_id]); bo->ggtt_node[tile_id] = NULL; } else { - xe_ggtt_map_bo(ggtt, bo); + u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; + u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + + xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pat_index); } mutex_unlock(&ggtt->lock); diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index ceae9a97d76e9..53d084d7076ec 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -27,6 +27,8 @@ int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, u32 size, u32 align, u32 mm_flags); void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); +void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, + struct xe_bo *bo, u16 pat_index); void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo); int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo); int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h b/drivers/gpu/drm/xe/xe_ggtt_types.h index cb02b7994a9ac..06b1a602dd8d1 100644 --- a/drivers/gpu/drm/xe/xe_ggtt_types.h +++ b/drivers/gpu/drm/xe/xe_ggtt_types.h @@ -74,8 +74,11 @@ struct xe_ggtt_node { * Which can vary from platform to platform. */ struct xe_ggtt_pt_ops { - /** @pte_encode_bo: Encode PTE address for a given BO */ + /** @pte_encode_bo: Encode PTE flags for a given BO */ u64 (*pte_encode_bo)(struct xe_bo *bo, u64 bo_offset, u16 pat_index); + + /** @pte_encode_flags: Encode PTE flags for a given BO */ + u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index); /** @ggtt_set_pte: Directly write into GGTT's PTE */ void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte); }; -- GitLab From 8ce1c8cc68208bf5a3f4dfddbdb6579ae6f75be5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:19 +0200 Subject: [PATCH 291/902] drm/xe/display: Dont poke into GGTT internals to fill a DPT For DPT, it is sufficient to get the GGTT encode flags to fill the DPT. Create a function to return the encode flags, and then encode using the BO address. Reviewed-by: Juha-Pekka Heikkila Link: https://lore.kernel.org/r/20250505121924.921544-7-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 20 +++++++++----------- drivers/gpu/drm/xe/xe_ggtt.c | 15 +++++++++++++++ drivers/gpu/drm/xe/xe_ggtt.h | 2 ++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index d509def82b134..5392e46a3a134 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -23,6 +23,7 @@ write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; u32 column, row; + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); /* TODO: Maybe rewrite so we can traverse the bo addresses sequentially, * by writing dpt/ggtt in a different order? @@ -32,10 +33,9 @@ write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ u32 src_idx = src_stride * (height - 1) + column + bo_ofs; for (row = 0; row < height; row++) { - u64 pte = ggtt->pt_ops->pte_encode_bo(bo, src_idx * XE_PAGE_SIZE, - xe->pat.idx[XE_CACHE_NONE]); + u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE); - iosys_map_wr(map, *dpt_ofs, u64, pte); + iosys_map_wr(map, *dpt_ofs, u64, pte | addr); *dpt_ofs += 8; src_idx -= src_stride; } @@ -55,17 +55,15 @@ write_dpt_remapped(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, { struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; - u64 (*pte_encode_bo)(struct xe_bo *bo, u64 bo_offset, u16 pat_index) - = ggtt->pt_ops->pte_encode_bo; u32 column, row; + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); for (row = 0; row < height; row++) { u32 src_idx = src_stride * row + bo_ofs; for (column = 0; column < width; column++) { - iosys_map_wr(map, *dpt_ofs, u64, - pte_encode_bo(bo, src_idx * XE_PAGE_SIZE, - xe->pat.idx[XE_CACHE_NONE])); + u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE); + iosys_map_wr(map, *dpt_ofs, u64, pte | addr); *dpt_ofs += 8; src_idx++; @@ -129,13 +127,13 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, return PTR_ERR(dpt); if (view->type == I915_GTT_VIEW_NORMAL) { + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); u32 x; for (x = 0; x < size / XE_PAGE_SIZE; x++) { - u64 pte = ggtt->pt_ops->pte_encode_bo(bo, x * XE_PAGE_SIZE, - xe->pat.idx[XE_CACHE_NONE]); + u64 addr = xe_bo_addr(bo, x * XE_PAGE_SIZE, XE_PAGE_SIZE); - iosys_map_wr(&dpt->vmap, x * 8, u64, pte); + iosys_map_wr(&dpt->vmap, x * 8, u64, pte | addr); } } else if (view->type == I915_GTT_VIEW_REMAPPED) { const struct intel_remapped_info *remap_info = &view->remapped; diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 82ece4aa9ae2e..9772c0433c5c1 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -956,3 +956,18 @@ u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer return total; } + +/** + * xe_ggtt_encode_pte_flags - Get PTE encoding flags for BO + * @ggtt: &xe_ggtt + * @bo: &xe_bo + * @pat_index: The pat_index for the PTE. + * + * This function returns the pte_flags for a given BO, without address. + * It's used for DPT to fill a GGTT mapped BO with a linear lookup table. + */ +u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, + struct xe_bo *bo, u16 pat_index) +{ + return ggtt->pt_ops->pte_encode_flags(bo, pat_index); +} diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 53d084d7076ec..fc4ffb090a5a0 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -50,4 +50,6 @@ static inline void xe_ggtt_might_lock(struct xe_ggtt *ggtt) void xe_ggtt_might_lock(struct xe_ggtt *ggtt); #endif +u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, struct xe_bo *bo, u16 pat_index); + #endif -- GitLab From 34eca621335819bee9954064cab976e58af2ff8b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:20 +0200 Subject: [PATCH 292/902] drm/xe/display: Convert GGTT mapping to use pte_encode_flags Another small step in removing pte_encode_bo callback. Reviewed-by: Juha-Pekka Heikkila Link: https://lore.kernel.org/r/20250505121924.921544-8-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 5392e46a3a134..9059b56bc23c8 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -171,15 +171,15 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo { struct xe_device *xe = xe_bo_device(bo); u32 column, row; + u64 pte = ggtt->pt_ops->pte_encode_flags(bo, xe->pat.idx[XE_CACHE_NONE]); for (column = 0; column < width; column++) { u32 src_idx = src_stride * (height - 1) + column + bo_ofs; for (row = 0; row < height; row++) { - u64 pte = ggtt->pt_ops->pte_encode_bo(bo, src_idx * XE_PAGE_SIZE, - xe->pat.idx[XE_CACHE_NONE]); + u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE); - ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte); + ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte | addr); *ggtt_ofs += XE_PAGE_SIZE; src_idx -= src_stride; } @@ -217,26 +217,19 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { vma->node = bo->ggtt_node[tile0->id]; } else if (view->type == I915_GTT_VIEW_NORMAL) { - u32 x, size = bo->ttm.base.size; - vma->node = xe_ggtt_node_init(ggtt); if (IS_ERR(vma->node)) { ret = PTR_ERR(vma->node); goto out_unlock; } - ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); + ret = xe_ggtt_node_insert_locked(vma->node, bo->size, align, 0); if (ret) { xe_ggtt_node_fini(vma->node); goto out_unlock; } - for (x = 0; x < size; x += XE_PAGE_SIZE) { - u64 pte = ggtt->pt_ops->pte_encode_bo(bo, x, - xe->pat.idx[XE_CACHE_NONE]); - - ggtt->pt_ops->ggtt_set_pte(ggtt, vma->node->base.start + x, pte); - } + xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]); } else { u32 i, ggtt_ofs; const struct intel_rotation_info *rot_info = &view->rotated; -- GitLab From 0c52d722524a2ac3aefdbbc4cbc33658b08b9f79 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:21 +0200 Subject: [PATCH 293/902] drm/xe: Remove pte_encode_bo callback The users inside display have been converted to use thepte_encode_flags callback, we can now remove the pte_encode_bo cb. Reviewed-by: Juha-Pekka Heikkila Link: https://lore.kernel.org/r/20250505121924.921544-9-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_ggtt.c | 14 -------------- drivers/gpu/drm/xe/xe_ggtt_types.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 9772c0433c5c1..b4b3ecd1c1b9e 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -75,11 +75,6 @@ static u64 xelp_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) return pte; } -static u64 xelp_ggtt_encode_bo(struct xe_bo *bo, u64 bo_offset, u16 pat_index) -{ - return xelp_ggtt_pte_flags(bo, pat_index) | xe_bo_addr(bo, bo_offset, XE_PAGE_SIZE); -} - static u64 xelpg_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) { struct xe_device *xe = xe_bo_device(bo); @@ -98,12 +93,6 @@ static u64 xelpg_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) return pte; } -static u64 xelpg_ggtt_encode_bo(struct xe_bo *bo, u64 bo_offset, - u16 pat_index) -{ - return xelpg_ggtt_pte_flags(bo, pat_index) | xe_bo_addr(bo, bo_offset, XE_PAGE_SIZE); -} - static unsigned int probe_gsm_size(struct pci_dev *pdev) { u16 gmch_ctl, ggms; @@ -218,19 +207,16 @@ static void primelockdep(struct xe_ggtt *ggtt) } static const struct xe_ggtt_pt_ops xelp_pt_ops = { - .pte_encode_bo = xelp_ggtt_encode_bo, .pte_encode_flags = xelp_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte, }; static const struct xe_ggtt_pt_ops xelpg_pt_ops = { - .pte_encode_bo = xelpg_ggtt_encode_bo, .pte_encode_flags = xelpg_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte, }; static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { - .pte_encode_bo = xelpg_ggtt_encode_bo, .pte_encode_flags = xelpg_ggtt_pte_flags, .ggtt_set_pte = xe_ggtt_set_pte_and_flush, }; diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h b/drivers/gpu/drm/xe/xe_ggtt_types.h index 06b1a602dd8d1..c5e999d58ff2a 100644 --- a/drivers/gpu/drm/xe/xe_ggtt_types.h +++ b/drivers/gpu/drm/xe/xe_ggtt_types.h @@ -74,9 +74,6 @@ struct xe_ggtt_node { * Which can vary from platform to platform. */ struct xe_ggtt_pt_ops { - /** @pte_encode_bo: Encode PTE flags for a given BO */ - u64 (*pte_encode_bo)(struct xe_bo *bo, u64 bo_offset, u16 pat_index); - /** @pte_encode_flags: Encode PTE flags for a given BO */ u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index); /** @ggtt_set_pte: Directly write into GGTT's PTE */ -- GitLab From e0096fdcf88ce5e64a4c2e62d3198f05a70052d8 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:22 +0200 Subject: [PATCH 294/902] drm/xe: Implement a helper for reading out a GGTT PTE at a specified offset Split the GGTT PTE readout to a separate function, this is useful for adding testcases in the next commit, and also cleaner than manually reading out GGTT. Reviewed-by: Juha-Pekka Heikkila Link: https://lore.kernel.org/r/20250505121924.921544-10-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_plane_initial.c | 6 +----- drivers/gpu/drm/xe/xe_ggtt.c | 12 ++++++++++++ drivers/gpu/drm/xe/xe_ggtt.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 6502b82741732..59b2ff2026d47 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -87,12 +87,8 @@ initial_plane_bo(struct xe_device *xe, base = round_down(plane_config->base, page_size); if (IS_DGFX(xe)) { - u64 __iomem *gte = tile0->mem.ggtt->gsm; - u64 pte; + u64 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base); - gte += base / XE_PAGE_SIZE; - - pte = ioread64(gte); if (!(pte & XE_GGTT_PTE_DM)) { drm_err(&xe->drm, "Initial plane programming missing DM bit\n"); diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index b4b3ecd1c1b9e..ad0479c96b217 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -957,3 +957,15 @@ u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, { return ggtt->pt_ops->pte_encode_flags(bo, pat_index); } + +/** + * xe_ggtt_read_pte - Read a PTE from the GGTT + * @ggtt: &xe_ggtt + * @offset: the offset for which the mapping should be read. + * + * Used by testcases, and by display reading out an inherited bios FB. + */ +u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset) +{ + return ioread64(ggtt->gsm + (offset / XE_PAGE_SIZE)); +} diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index fc4ffb090a5a0..dd43c82f4cade 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -51,5 +51,6 @@ void xe_ggtt_might_lock(struct xe_ggtt *ggtt); #endif u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, struct xe_bo *bo, u16 pat_index); +u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset); #endif -- GitLab From b2d6fd7ac598880f29989ebd763957dcedd66d40 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 May 2025 14:19:23 +0200 Subject: [PATCH 295/902] drm/xe: Do not rely on GGTT internals in xe_guc_buf kunit tests Add a function to init ggtt for kunit, and use the GGTT function for initialising the GGTT node without populating it. This prevents the test from ever knowing about struct xe_ggtt. Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250505121924.921544-11-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c | 11 +++++----- drivers/gpu/drm/xe/xe_ggtt.c | 23 ++++++++++++++++----- drivers/gpu/drm/xe/xe_ggtt.h | 1 + 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c index 6faffcd748694..537766cdd882e 100644 --- a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c +++ b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c @@ -42,10 +42,8 @@ static struct xe_bo *replacement_xe_managed_bo_create_pin_map(struct xe_device * KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo->ggtt_node[tile->id]); KUNIT_ASSERT_EQ(test, 0, - drm_mm_insert_node_in_range(&ggtt->mm, - &bo->ggtt_node[tile->id]->base, - bo->size, SZ_4K, - 0, 0, U64_MAX, 0)); + xe_ggtt_node_insert(bo->ggtt_node[tile->id], + bo->size, SZ_4K)); } return bo; @@ -67,8 +65,9 @@ static int guc_buf_test_init(struct kunit *test) ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt; guc = &xe_device_get_gt(test->priv, 0)->uc.guc; - drm_mm_init(&ggtt->mm, DUT_GGTT_START, DUT_GGTT_SIZE); - mutex_init(&ggtt->lock); + KUNIT_ASSERT_EQ(test, 0, + xe_ggtt_init_kunit(ggtt, DUT_GGTT_START, + DUT_GGTT_START + DUT_GGTT_SIZE)); kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, replacement_xe_managed_bo_create_pin_map); diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index ad0479c96b217..be22909592747 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -5,6 +5,7 @@ #include "xe_ggtt.h" +#include #include #include #include @@ -221,6 +222,22 @@ static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { .ggtt_set_pte = xe_ggtt_set_pte_and_flush, }; +static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u32 reserved) +{ + drm_mm_init(&ggtt->mm, reserved, + ggtt->size - reserved); + mutex_init(&ggtt->lock); + primelockdep(ggtt); +} + +int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size) +{ + ggtt->size = size; + __xe_ggtt_init_early(ggtt, reserved); + return 0; +} +EXPORT_SYMBOL_IF_KUNIT(xe_ggtt_init_kunit); + /** * xe_ggtt_init_early - Early GGTT initialization * @ggtt: the &xe_ggtt to be initialized @@ -267,11 +284,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) ggtt->pt_ops = &xelp_pt_ops; ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM); - - drm_mm_init(&ggtt->mm, xe_wopcm_size(xe), - ggtt->size - xe_wopcm_size(xe)); - mutex_init(&ggtt->lock); - primelockdep(ggtt); + __xe_ggtt_init_early(ggtt, xe_wopcm_size(xe)); err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); if (err) diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index dd43c82f4cade..fbe1e397d05d6 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -13,6 +13,7 @@ struct xe_tile; struct xe_ggtt *xe_ggtt_alloc(struct xe_tile *tile); int xe_ggtt_init_early(struct xe_ggtt *ggtt); +int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size); int xe_ggtt_init(struct xe_ggtt *ggtt); struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt); -- GitLab From 188bdfb77615ab14da49bf1438ab3a1413da9898 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 6 Jun 2025 13:22:56 +0300 Subject: [PATCH 296/902] drm/i915: split out display register macros to a separate file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a scripted split of the display related register macros from i915_reg.h to display/intel_display_regs.h. As a starting point, move all the macros that are only used in display code (or GVT). If there are users in core i915 code or soc/, or no users anywhere, keep the macros in i915_reg.h. This is done in groups of macros separated by blank lines, moving the comments along with the groups. Some manually picked macro groups are kept/moved regardless of the heuristics above. This is obviously a very crude approach. It's not perfect. But there are 4.2k lines in i915_reg.h, and its refactoring has ground to a halt. This is the big hammer that splits the file to two, and enables further cleanup. Cc: Suraj Kandpal Cc: Ville Syrjälä Cc: Lucas De Marchi Reviewed-by: Suraj Kandpal # v2 Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250606102256.2080073-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/g4x_dp.c | 1 + drivers/gpu/drm/i915/display/g4x_hdmi.c | 1 + drivers/gpu/drm/i915/display/hsw_ips.c | 1 + .../gpu/drm/i915/display/i9xx_display_sr.c | 1 + drivers/gpu/drm/i915/display/i9xx_plane.c | 2 + drivers/gpu/drm/i915/display/i9xx_wm.c | 1 + drivers/gpu/drm/i915/display/icl_dsi.c | 1 + .../gpu/drm/i915/display/intel_backlight.c | 2 +- drivers/gpu/drm/i915/display/intel_bw.c | 2 + drivers/gpu/drm/i915/display/intel_cdclk.c | 1 + drivers/gpu/drm/i915/display/intel_cmtg.c | 3 +- .../gpu/drm/i915/display/intel_combo_phy.c | 1 + drivers/gpu/drm/i915/display/intel_crt.c | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 3 +- .../drm/i915/display/intel_display_debugfs.c | 3 +- .../drm/i915/display/intel_display_device.c | 1 + .../gpu/drm/i915/display/intel_display_irq.c | 1 + .../drm/i915/display/intel_display_power.c | 2 + .../i915/display/intel_display_power_map.c | 1 + .../i915/display/intel_display_power_well.c | 3 +- .../gpu/drm/i915/display/intel_display_regs.h | 2935 +++++++++++++++++ .../gpu/drm/i915/display/intel_display_wa.c | 1 + drivers/gpu/drm/i915/display/intel_dmc.c | 3 +- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 + drivers/gpu/drm/i915/display/intel_dp_test.c | 1 + drivers/gpu/drm/i915/display/intel_dpio_phy.c | 1 + drivers/gpu/drm/i915/display/intel_dpll.c | 1 + drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + .../gpu/drm/i915/display/intel_dpt_common.c | 1 + drivers/gpu/drm/i915/display/intel_drrs.c | 1 + drivers/gpu/drm/i915/display/intel_dsb.c | 1 + drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/intel_dvo.c | 1 + drivers/gpu/drm/i915/display/intel_fbc.c | 3 + drivers/gpu/drm/i915/display/intel_fdi.c | 1 + .../drm/i915/display/intel_fifo_underrun.c | 1 + drivers/gpu/drm/i915/display/intel_gmbus.c | 1 + drivers/gpu/drm/i915/display/intel_hdcp.c | 1 + drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- .../gpu/drm/i915/display/intel_hotplug_irq.c | 1 + drivers/gpu/drm/i915/display/intel_lspcon.c | 1 + .../drm/i915/display/intel_modeset_setup.c | 1 + drivers/gpu/drm/i915/display/intel_overlay.c | 2 + .../gpu/drm/i915/display/intel_pch_display.c | 1 + .../gpu/drm/i915/display/intel_pch_refclk.c | 1 + drivers/gpu/drm/i915/display/intel_pfit.c | 1 + drivers/gpu/drm/i915/display/intel_pipe_crc.c | 1 + drivers/gpu/drm/i915/display/intel_pmdemand.c | 1 + drivers/gpu/drm/i915/display/intel_pps.c | 1 + drivers/gpu/drm/i915/display/intel_psr.c | 1 + drivers/gpu/drm/i915/display/intel_sdvo.c | 1 + drivers/gpu/drm/i915/display/intel_snps_phy.c | 1 + drivers/gpu/drm/i915/display/intel_tc.c | 1 + drivers/gpu/drm/i915/display/intel_tv.c | 1 + drivers/gpu/drm/i915/display/intel_vblank.c | 1 + drivers/gpu/drm/i915/display/intel_vrr.c | 1 + drivers/gpu/drm/i915/display/skl_scaler.c | 1 + .../drm/i915/display/skl_universal_plane.c | 4 +- drivers/gpu/drm/i915/display/skl_watermark.c | 2 + drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + drivers/gpu/drm/i915/gvt/cmd_parser.c | 1 + drivers/gpu/drm/i915/gvt/display.c | 1 + drivers/gpu/drm/i915/gvt/fb_decoder.c | 1 + drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/gvt/interrupt.c | 1 + drivers/gpu/drm/i915/gvt/mmio.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 2924 ---------------- drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 1 + drivers/gpu/drm/xe/display/xe_plane_initial.c | 1 + 73 files changed, 3020 insertions(+), 2934 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_display_regs.h diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index e0a98e6fd6d1d..87f6b9602b16a 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -18,6 +18,7 @@ #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_aux.h" diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 1d252432d729a..2610f5702fb9a 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -15,6 +15,7 @@ #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp_aux.h" #include "intel_dpio_phy.h" diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c index 4307e2ed03d94..0d33782f11be1 100644 --- a/drivers/gpu/drm/i915/display/hsw_ips.c +++ b/drivers/gpu/drm/i915/display/hsw_ips.c @@ -10,6 +10,7 @@ #include "i915_reg.h" #include "intel_color_regs.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/display/i9xx_display_sr.c b/drivers/gpu/drm/i915/display/i9xx_display_sr.c index 32abe9743014b..357212f09a0fc 100644 --- a/drivers/gpu/drm/i915/display/i9xx_display_sr.c +++ b/drivers/gpu/drm/i915/display/i9xx_display_sr.c @@ -9,6 +9,7 @@ #include "i9xx_display_sr.h" #include "i9xx_wm_regs.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_gmbus.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index a2a6d52be0a5f..8f15333a4b07c 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -2,6 +2,7 @@ /* * Copyright © 2020 Intel Corporation */ + #include #include @@ -17,6 +18,7 @@ #include "intel_atomic_plane.h" #include "intel_de.h" #include "intel_display_irq.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fbc.h" diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 8e4e938f1ee5e..1f9db51187772 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -11,6 +11,7 @@ #include "intel_bo.h" #include "intel_de.h" #include "intel_display.h" +#include "intel_display_regs.h" #include "intel_display_trace.h" #include "intel_fb.h" #include "intel_mchbar_regs.h" diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 026361354e6fc..a825dbe0a46e8 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -45,6 +45,7 @@ #include "intel_crtc.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_dsi.h" #include "intel_dsi_vbt.h" #include "intel_panel.h" diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 5827da5860032..e007380e9a631 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -7,7 +7,6 @@ #include #include #include - #include #include @@ -19,6 +18,7 @@ #include "intel_backlight_regs.h" #include "intel_connector.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dp_aux_backlight.h" diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 97aef729f7d4c..6c2ab2e0dc91e 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -6,6 +6,7 @@ #include #include "soc/intel_dram.h" + #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" @@ -13,6 +14,7 @@ #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_display_core.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index f0c673e40ce55..38b3094b37d7f 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -38,6 +38,7 @@ #include "intel_cdclk.h" #include "intel_crtc.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_mchbar_regs.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c b/drivers/gpu/drm/i915/display/intel_cmtg.c index 82606ebae1de9..d98b47a074517 100644 --- a/drivers/gpu/drm/i915/display/intel_cmtg.c +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c @@ -10,12 +10,13 @@ #include #include "i915_reg.h" -#include "intel_crtc.h" #include "intel_cmtg.h" #include "intel_cmtg_regs.h" +#include "intel_crtc.h" #include "intel_de.h" #include "intel_display_device.h" #include "intel_display_power.h" +#include "intel_display_regs.h" /** * DOC: Common Primary Timing Generator (CMTG) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index f5cc38dbe5590..b1bff2f0b020c 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -10,6 +10,7 @@ #include "intel_combo_phy.h" #include "intel_combo_phy_regs.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #define for_each_combo_phy(__display, __phy) \ diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 04ef729dae0ba..6a1c5a4326fe5 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -43,6 +43,7 @@ #include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_driver.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_fdi.h" #include "intel_fdi_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 4c845dd410a2a..cbd1060e96643 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -50,6 +50,7 @@ #include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" #include "intel_dkl_phy_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 06f58c062b296..b0c7c46ffbe24 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -67,13 +67,14 @@ #include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_cursor.h" #include "intel_cursor_regs.h" #include "intel_cx0_phy.h" -#include "intel_cursor.h" #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_driver.h" #include "intel_display_power.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dmc.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b671b4ea1a24d..ce3f9810c42d2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -4,8 +4,8 @@ */ #include -#include #include +#include #include #include @@ -25,6 +25,7 @@ #include "intel_display_debugfs_params.h" #include "intel_display_power.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dmc.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index 1d8c2036d967f..a4070f40e26f9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -18,6 +18,7 @@ #include "intel_display_params.h" #include "intel_display_power.h" #include "intel_display_reg_defs.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_fbc.h" #include "intel_step.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 0c9fff26653ba..8d0dcf252bed2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -13,6 +13,7 @@ #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_irq.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_rps.h" #include "intel_display_trace.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 8e8c3a2f401bb..fe3a8e90b97ae 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -6,6 +6,7 @@ #include #include "soc/intel_dram.h" + #include "i915_drv.h" #include "i915_irq.h" #include "i915_reg.h" @@ -17,6 +18,7 @@ #include "intel_display_power.h" #include "intel_display_power_map.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dmc.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index b4c302544909d..8c9a637b94072 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -9,6 +9,7 @@ #include "intel_display_core.h" #include "intel_display_power_map.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "vlv_iosf_sb_reg.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 02e3c22be21e0..cba96f920fd24 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -13,6 +13,7 @@ #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" @@ -30,8 +31,8 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" #include "vlv_iosf_sb_reg.h" +#include "vlv_sideband.h" struct i915_power_well_regs { i915_reg_t bios; diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h new file mode 100644 index 0000000000000..e101105da4afc --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -0,0 +1,2935 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __INTEL_DISPLAY_REGS_H__ +#define __INTEL_DISPLAY_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _GEN7_PIPEA_DE_LOAD_SL 0x70068 +#define _GEN7_PIPEB_DE_LOAD_SL 0x71068 +#define GEN7_PIPE_DE_LOAD_SL(pipe) _MMIO_PIPE(pipe, _GEN7_PIPEA_DE_LOAD_SL, _GEN7_PIPEB_DE_LOAD_SL) + +#define DPIO_CTL _MMIO(VLV_DISPLAY_BASE + 0x2110) +#define DPIO_MODSEL1 (1 << 3) /* if ref clk b == 27 */ +#define DPIO_MODSEL0 (1 << 2) /* if ref clk a == 27 */ +#define DPIO_SFR_BYPASS (1 << 1) +#define DPIO_CMNRST (1 << 0) + +#define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090) +#define MIPIO_RST_CTRL (1 << 2) + +#define _BXT_PHY_CTL_DDI_A 0x64C00 +#define _BXT_PHY_CTL_DDI_B 0x64C10 +#define _BXT_PHY_CTL_DDI_C 0x64C20 +#define BXT_PHY_CMNLANE_POWERDOWN_ACK (1 << 10) +#define BXT_PHY_LANE_POWERDOWN_ACK (1 << 9) +#define BXT_PHY_LANE_ENABLED (1 << 8) +#define BXT_PHY_CTL(port) _MMIO_PORT(port, _BXT_PHY_CTL_DDI_A, \ + _BXT_PHY_CTL_DDI_B) + +#define _PHY_CTL_FAMILY_DDI 0x64C90 +#define _PHY_CTL_FAMILY_EDP 0x64C80 +#define _PHY_CTL_FAMILY_DDI_C 0x64CA0 +#define COMMON_RESET_DIS (1 << 31) +#define BXT_PHY_CTL_FAMILY(phy) \ + _MMIO(_PICK_EVEN_2RANGES(phy, 1, \ + _PHY_CTL_FAMILY_DDI, _PHY_CTL_FAMILY_DDI, \ + _PHY_CTL_FAMILY_EDP, _PHY_CTL_FAMILY_DDI_C)) + +/* UAIMI scratch pad register 1 */ +#define UAIMI_SPR1 _MMIO(0x4F074) +/* SKL VccIO mask */ +#define SKL_VCCIO_MASK 0x1 +/* SKL balance leg register */ +#define DISPIO_CR_TX_BMU_CR0 _MMIO(0x6C00C) +/* I_boost values */ +#define BALANCE_LEG_SHIFT(port) (8 + 3 * (port)) +#define BALANCE_LEG_MASK(port) (7 << (8 + 3 * (port))) +/* Balance leg disable bits */ +#define BALANCE_LEG_DISABLE_SHIFT 23 +#define BALANCE_LEG_DISABLE(port) (1 << (23 + (port))) + +#define ILK_GTT_FAULT _MMIO(0x44040) /* ilk/snb */ +#define GTT_FAULT_INVALID_GTT_PTE (1 << 7) +#define GTT_FAULT_INVALID_PTE_DATA (1 << 6) +#define GTT_FAULT_CURSOR_B_FAULT (1 << 5) +#define GTT_FAULT_CURSOR_A_FAULT (1 << 4) +#define GTT_FAULT_SPRITE_B_FAULT (1 << 3) +#define GTT_FAULT_SPRITE_A_FAULT (1 << 2) +#define GTT_FAULT_PRIMARY_B_FAULT (1 << 1) +#define GTT_FAULT_PRIMARY_A_FAULT (1 << 0) + +#define DERRMR _MMIO(0x44050) +/* Note that HBLANK events are reserved on bdw+ */ +#define DERRMR_PIPEA_SCANLINE (1 << 0) +#define DERRMR_PIPEA_PRI_FLIP_DONE (1 << 1) +#define DERRMR_PIPEA_SPR_FLIP_DONE (1 << 2) +#define DERRMR_PIPEA_VBLANK (1 << 3) +#define DERRMR_PIPEA_HBLANK (1 << 5) +#define DERRMR_PIPEB_SCANLINE (1 << 8) +#define DERRMR_PIPEB_PRI_FLIP_DONE (1 << 9) +#define DERRMR_PIPEB_SPR_FLIP_DONE (1 << 10) +#define DERRMR_PIPEB_VBLANK (1 << 11) +#define DERRMR_PIPEB_HBLANK (1 << 13) +/* Note that PIPEC is not a simple translation of PIPEA/PIPEB */ +#define DERRMR_PIPEC_SCANLINE (1 << 14) +#define DERRMR_PIPEC_PRI_FLIP_DONE (1 << 15) +#define DERRMR_PIPEC_SPR_FLIP_DONE (1 << 20) +#define DERRMR_PIPEC_VBLANK (1 << 21) +#define DERRMR_PIPEC_HBLANK (1 << 22) + +#define VLV_IRQ_REGS I915_IRQ_REGS(VLV_IMR, \ + VLV_IER, \ + VLV_IIR) + +#define VLV_EIR _MMIO(VLV_DISPLAY_BASE + 0x20b0) +#define VLV_EMR _MMIO(VLV_DISPLAY_BASE + 0x20b4) +#define VLV_ESR _MMIO(VLV_DISPLAY_BASE + 0x20b8) +#define VLV_ERROR_GUNIT_TLB_DATA (1 << 6) +#define VLV_ERROR_GUNIT_TLB_PTE (1 << 5) +#define VLV_ERROR_PAGE_TABLE (1 << 4) +#define VLV_ERROR_CLAIM (1 << 0) + +#define VLV_ERROR_REGS I915_ERROR_REGS(VLV_EMR, VLV_EIR) + +#define _MBUS_ABOX0_CTL 0x45038 +#define _MBUS_ABOX1_CTL 0x45048 +#define _MBUS_ABOX2_CTL 0x4504C +#define MBUS_ABOX_CTL(x) \ + _MMIO(_PICK_EVEN_2RANGES(x, 2, \ + _MBUS_ABOX0_CTL, _MBUS_ABOX1_CTL, \ + _MBUS_ABOX2_CTL, _MBUS_ABOX2_CTL)) + +#define MBUS_ABOX_BW_CREDIT_MASK (3 << 20) +#define MBUS_ABOX_BW_CREDIT(x) ((x) << 20) +#define MBUS_ABOX_B_CREDIT_MASK (0xF << 16) +#define MBUS_ABOX_B_CREDIT(x) ((x) << 16) +#define MBUS_ABOX_BT_CREDIT_POOL2_MASK (0x1F << 8) +#define MBUS_ABOX_BT_CREDIT_POOL2(x) ((x) << 8) +#define MBUS_ABOX_BT_CREDIT_POOL1_MASK (0x1F << 0) +#define MBUS_ABOX_BT_CREDIT_POOL1(x) ((x) << 0) + +#define IPS_CTL _MMIO(0x43408) +#define IPS_ENABLE REG_BIT(31) +#define IPS_FALSE_COLOR REG_BIT(4) + +/* + * Clock control & power management + */ +#define _DPLL_A 0x6014 +#define _DPLL_B 0x6018 +#define _CHV_DPLL_C 0x6030 +#define DPLL(dev_priv, pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ + (pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C) + +#define VGA0 _MMIO(0x6000) +#define VGA1 _MMIO(0x6004) +#define VGA_PD _MMIO(0x6010) +#define VGA0_PD_P2_DIV_4 (1 << 7) +#define VGA0_PD_P1_DIV_2 (1 << 5) +#define VGA0_PD_P1_SHIFT 0 +#define VGA0_PD_P1_MASK (0x1f << 0) +#define VGA1_PD_P2_DIV_4 (1 << 15) +#define VGA1_PD_P1_DIV_2 (1 << 13) +#define VGA1_PD_P1_SHIFT 8 +#define VGA1_PD_P1_MASK (0x1f << 8) +#define DPLL_VCO_ENABLE (1 << 31) +#define DPLL_SDVO_HIGH_SPEED (1 << 30) +#define DPLL_DVO_2X_MODE (1 << 30) +#define DPLL_EXT_BUFFER_ENABLE_VLV (1 << 30) +#define DPLL_SYNCLOCK_ENABLE (1 << 29) +#define DPLL_REF_CLK_ENABLE_VLV (1 << 29) +#define DPLL_VGA_MODE_DIS (1 << 28) +#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +#define DPLL_MODE_MASK (3 << 26) +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ +#define DPLL_LOCK_VLV (1 << 15) +#define DPLL_INTEGRATED_CRI_CLK_VLV (1 << 14) +#define DPLL_INTEGRATED_REF_CLK_VLV (1 << 13) +#define DPLL_SSC_REF_CLK_CHV (1 << 13) +#define DPLL_PORTC_READY_MASK (0xf << 4) +#define DPLL_PORTB_READY_MASK (0xf) + +#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 + +/* Additional CHV pll/phy registers */ +#define DPIO_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x6240) +#define DPLL_PORTD_READY_MASK (0xf) +#define DISPLAY_PHY_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x60100) +#define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2 * (phy) + (ch) + 27)) +#define PHY_LDO_DELAY_0NS 0x0 +#define PHY_LDO_DELAY_200NS 0x1 +#define PHY_LDO_DELAY_600NS 0x2 +#define PHY_LDO_SEQ_DELAY(delay, phy) ((delay) << (2 * (phy) + 23)) +#define PHY_CH_POWER_DOWN_OVRD(mask, phy, ch) ((mask) << (8 * (phy) + 4 * (ch) + 11)) +#define PHY_CH_SU_PSR 0x1 +#define PHY_CH_DEEP_PSR 0x7 +#define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6 * (phy) + 3 * (ch) + 2)) +#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy)) +#define DISPLAY_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x60104) +#define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1 << 31) : (1 << 30)) +#define PHY_STATUS_CMN_LDO(phy, ch) (1 << (6 - (6 * (phy) + 3 * (ch)))) +#define PHY_STATUS_SPLINE_LDO(phy, ch, spline) (1 << (8 - (6 * (phy) + 3 * (ch) + (spline)))) + +/* + * The i830 generation, in LVDS mode, defines P1 as the bit number set within + * this field (only one bit may be set). + */ +#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15 +/* i830, required in DVO non-gang */ +#define PLL_P2_DIVIDE_BY_4 (1 << 23) +#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +#define PLL_REF_INPUT_DREFCLK (0 << 13) +#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ +#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +#define PLL_REF_INPUT_MASK (3 << 13) +#define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* Ironlake */ +# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 +# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) +# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x) - 1) << 9) +# define DPLL_FPA1_P1_POST_DIV_SHIFT 0 +# define DPLL_FPA1_P1_POST_DIV_MASK 0xff + +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +/* + * SDVO multiplier for 945G/GM. Not used on 965. + */ +#define SDVO_MULTIPLIER_MASK 0x000000ff +#define SDVO_MULTIPLIER_SHIFT_HIRES 4 +#define SDVO_MULTIPLIER_SHIFT_VGA 0 + +#define _DPLL_A_MD 0x601c +#define _DPLL_B_MD 0x6020 +#define _CHV_DPLL_C_MD 0x603c +#define DPLL_MD(dev_priv, pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ + (pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD) + +/* + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +#define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/* + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/* + * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ +#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 + +#define RAWCLK_FREQ_VLV _MMIO(VLV_DISPLAY_BASE + 0x6024) + +#define _FPA0 0x6040 +#define _FPA1 0x6044 +#define _FPB0 0x6048 +#define _FPB1 0x604c +#define FP0(pipe) _MMIO_PIPE(pipe, _FPA0, _FPB0) +#define FP1(pipe) _MMIO_PIPE(pipe, _FPA1, _FPB1) +#define FP_N_DIV_MASK 0x003f0000 +#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 +#define FP_N_DIV_SHIFT 16 +#define FP_M1_DIV_MASK 0x00003f00 +#define FP_M1_DIV_SHIFT 8 +#define FP_M2_DIV_MASK 0x0000003f +#define FP_M2_PINEVIEW_DIV_MASK 0x000000ff +#define FP_M2_DIV_SHIFT 0 + +#define FW_BLC_SELF_VLV _MMIO(VLV_DISPLAY_BASE + 0x6500) +#define FW_CSPWRDWNEN (1 << 15) + +#define MI_ARB_VLV _MMIO(VLV_DISPLAY_BASE + 0x6504) + +#define CZCLK_CDCLK_FREQ_RATIO _MMIO(VLV_DISPLAY_BASE + 0x6508) +#define CDCLK_FREQ_SHIFT 4 +#define CDCLK_FREQ_MASK (0x1f << CDCLK_FREQ_SHIFT) +#define CZCLK_FREQ_MASK 0xf + +#define GCI_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x650C) +#define PFI_CREDIT_63 (9 << 28) /* chv only */ +#define PFI_CREDIT_31 (8 << 28) /* chv only */ +#define PFI_CREDIT(x) (((x) - 8) << 28) /* 8-15 */ +#define PFI_CREDIT_RESEND (1 << 27) +#define VGA_FAST_MODE_DISABLE (1 << 14) + +#define GMBUSFREQ_VLV _MMIO(VLV_DISPLAY_BASE + 0x6510) + +#define PEG_BAND_GAP_DATA _MMIO(0x14d68) + +/* + * Overlay regs + */ +#define OVADD _MMIO(0x30000) +#define DOVSTA _MMIO(0x30008) +#define OC_BUF (0x3 << 20) +#define OGAMC5 _MMIO(0x30010) +#define OGAMC4 _MMIO(0x30014) +#define OGAMC3 _MMIO(0x30018) +#define OGAMC2 _MMIO(0x3001c) +#define OGAMC1 _MMIO(0x30020) +#define OGAMC0 _MMIO(0x30024) + +#define GEN9_CLKGATE_DIS_4 _MMIO(0x4653C) +#define BXT_GMBUS_GATING_DIS (1 << 14) +#define DG2_DPFC_GATING_DIS REG_BIT(31) + +#define GEN9_CLKGATE_DIS_5 _MMIO(0x46540) +#define DPCE_GATING_DIS REG_BIT(17) + +#define _CLKGATE_DIS_PSL_A 0x46520 +#define _CLKGATE_DIS_PSL_B 0x46524 +#define _CLKGATE_DIS_PSL_C 0x46528 +#define DUPS1_GATING_DIS (1 << 15) +#define DUPS2_GATING_DIS (1 << 19) +#define DUPS3_GATING_DIS (1 << 23) +#define CURSOR_GATING_DIS REG_BIT(28) +#define DPF_GATING_DIS (1 << 10) +#define DPF_RAM_GATING_DIS (1 << 9) +#define DPFR_GATING_DIS (1 << 8) + +#define CLKGATE_DIS_PSL(pipe) \ + _MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_A, _CLKGATE_DIS_PSL_B) + +#define _CLKGATE_DIS_PSL_EXT_A 0x4654C +#define _CLKGATE_DIS_PSL_EXT_B 0x46550 +#define PIPEDMC_GATING_DIS REG_BIT(12) + +#define CLKGATE_DIS_PSL_EXT(pipe) \ + _MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_EXT_A, _CLKGATE_DIS_PSL_EXT_B) + +/* + * Display engine regs + */ +/* Pipe/transcoder A timing regs */ +#define _TRANS_HTOTAL_A 0x60000 +#define _TRANS_HTOTAL_B 0x61000 +#define TRANS_HTOTAL(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HTOTAL_A) +#define HTOTAL_MASK REG_GENMASK(31, 16) +#define HTOTAL(htotal) REG_FIELD_PREP(HTOTAL_MASK, (htotal)) +#define HACTIVE_MASK REG_GENMASK(15, 0) +#define HACTIVE(hdisplay) REG_FIELD_PREP(HACTIVE_MASK, (hdisplay)) + +#define _TRANS_HBLANK_A 0x60004 +#define _TRANS_HBLANK_B 0x61004 +#define TRANS_HBLANK(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HBLANK_A) +#define HBLANK_END_MASK REG_GENMASK(31, 16) +#define HBLANK_END(hblank_end) REG_FIELD_PREP(HBLANK_END_MASK, (hblank_end)) +#define HBLANK_START_MASK REG_GENMASK(15, 0) +#define HBLANK_START(hblank_start) REG_FIELD_PREP(HBLANK_START_MASK, (hblank_start)) + +#define _TRANS_HSYNC_A 0x60008 +#define _TRANS_HSYNC_B 0x61008 +#define TRANS_HSYNC(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HSYNC_A) +#define HSYNC_END_MASK REG_GENMASK(31, 16) +#define HSYNC_END(hsync_end) REG_FIELD_PREP(HSYNC_END_MASK, (hsync_end)) +#define HSYNC_START_MASK REG_GENMASK(15, 0) +#define HSYNC_START(hsync_start) REG_FIELD_PREP(HSYNC_START_MASK, (hsync_start)) + +#define _TRANS_VTOTAL_A 0x6000c +#define _TRANS_VTOTAL_B 0x6100c +#define TRANS_VTOTAL(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VTOTAL_A) +#define VTOTAL_MASK REG_GENMASK(31, 16) +#define VTOTAL(vtotal) REG_FIELD_PREP(VTOTAL_MASK, (vtotal)) +#define VACTIVE_MASK REG_GENMASK(15, 0) +#define VACTIVE(vdisplay) REG_FIELD_PREP(VACTIVE_MASK, (vdisplay)) + +#define _TRANS_VBLANK_A 0x60010 +#define _TRANS_VBLANK_B 0x61010 +#define TRANS_VBLANK(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VBLANK_A) +#define VBLANK_END_MASK REG_GENMASK(31, 16) +#define VBLANK_END(vblank_end) REG_FIELD_PREP(VBLANK_END_MASK, (vblank_end)) +#define VBLANK_START_MASK REG_GENMASK(15, 0) +#define VBLANK_START(vblank_start) REG_FIELD_PREP(VBLANK_START_MASK, (vblank_start)) + +#define _TRANS_VSYNC_A 0x60014 +#define _TRANS_VSYNC_B 0x61014 +#define TRANS_VSYNC(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNC_A) +#define VSYNC_END_MASK REG_GENMASK(31, 16) +#define VSYNC_END(vsync_end) REG_FIELD_PREP(VSYNC_END_MASK, (vsync_end)) +#define VSYNC_START_MASK REG_GENMASK(15, 0) +#define VSYNC_START(vsync_start) REG_FIELD_PREP(VSYNC_START_MASK, (vsync_start)) + +#define _PIPEASRC 0x6001c +#define _PIPEBSRC 0x6101c +#define PIPESRC(dev_priv, pipe) _MMIO_TRANS2(dev_priv, (pipe), _PIPEASRC) +#define PIPESRC_WIDTH_MASK REG_GENMASK(31, 16) +#define PIPESRC_WIDTH(w) REG_FIELD_PREP(PIPESRC_WIDTH_MASK, (w)) +#define PIPESRC_HEIGHT_MASK REG_GENMASK(15, 0) +#define PIPESRC_HEIGHT(h) REG_FIELD_PREP(PIPESRC_HEIGHT_MASK, (h)) + +#define _BCLRPAT_A 0x60020 +#define _BCLRPAT_B 0x61020 +#define BCLRPAT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _BCLRPAT_A) + +#define _TRANS_VSYNCSHIFT_A 0x60028 +#define _TRANS_VSYNCSHIFT_B 0x61028 +#define TRANS_VSYNCSHIFT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNCSHIFT_A) + +#define _TRANS_MULT_A 0x6002c +#define _TRANS_MULT_B 0x6102c +#define TRANS_MULT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_MULT_A) + +/* Hotplug control (945+ only) */ +#define PORT_HOTPLUG_EN(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61110) +#define PORTB_HOTPLUG_INT_EN (1 << 29) +#define PORTC_HOTPLUG_INT_EN (1 << 28) +#define PORTD_HOTPLUG_INT_EN (1 << 27) +#define SDVOB_HOTPLUG_INT_EN (1 << 26) +#define SDVOC_HOTPLUG_INT_EN (1 << 25) +#define TV_HOTPLUG_INT_EN (1 << 18) +#define CRT_HOTPLUG_INT_EN (1 << 9) +#define HOTPLUG_INT_EN_MASK (PORTB_HOTPLUG_INT_EN | \ + PORTC_HOTPLUG_INT_EN | \ + PORTD_HOTPLUG_INT_EN | \ + SDVOC_HOTPLUG_INT_EN | \ + SDVOB_HOTPLUG_INT_EN | \ + CRT_HOTPLUG_INT_EN) +#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) + +#define PORT_HOTPLUG_STAT(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61114) +/* HDMI/DP bits are g4x+ */ +#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 27) +#define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) +#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 29) +#define PORTD_HOTPLUG_INT_STATUS (3 << 21) +#define PORTD_HOTPLUG_INT_LONG_PULSE (2 << 21) +#define PORTD_HOTPLUG_INT_SHORT_PULSE (1 << 21) +#define PORTC_HOTPLUG_INT_STATUS (3 << 19) +#define PORTC_HOTPLUG_INT_LONG_PULSE (2 << 19) +#define PORTC_HOTPLUG_INT_SHORT_PULSE (1 << 19) +#define PORTB_HOTPLUG_INT_STATUS (3 << 17) +#define PORTB_HOTPLUG_INT_LONG_PULSE (2 << 17) +#define PORTB_HOTPLUG_INT_SHORT_PLUSE (1 << 17) +/* CRT/TV common between gen3+ */ +#define CRT_HOTPLUG_INT_STATUS (1 << 11) +#define TV_HOTPLUG_INT_STATUS (1 << 10) +#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +#define DP_AUX_CHANNEL_D_INT_STATUS_G4X (1 << 6) +#define DP_AUX_CHANNEL_C_INT_STATUS_G4X (1 << 5) +#define DP_AUX_CHANNEL_B_INT_STATUS_G4X (1 << 4) +#define DP_AUX_CHANNEL_MASK_INT_STATUS_G4X (7 << 4) + +/* SDVO is different across gen3/4 */ +#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) +#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) +/* + * Bspec seems to be seriously misleaded about the SDVO hpd bits on i965g/gm, + * since reality corrobates that they're the same as on gen3. But keep these + * bits here (and the comment!) to help any other lost wanderers back onto the + * right tracks. + */ +#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) +#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) +#define HOTPLUG_INT_STATUS_G4X (CRT_HOTPLUG_INT_STATUS | \ + SDVOB_HOTPLUG_INT_STATUS_G4X | \ + SDVOC_HOTPLUG_INT_STATUS_G4X | \ + PORTB_HOTPLUG_INT_STATUS | \ + PORTC_HOTPLUG_INT_STATUS | \ + PORTD_HOTPLUG_INT_STATUS) + +#define HOTPLUG_INT_STATUS_I915 (CRT_HOTPLUG_INT_STATUS | \ + SDVOB_HOTPLUG_INT_STATUS_I915 | \ + SDVOC_HOTPLUG_INT_STATUS_I915 | \ + PORTB_HOTPLUG_INT_STATUS | \ + PORTC_HOTPLUG_INT_STATUS | \ + PORTD_HOTPLUG_INT_STATUS) + +/* SDVO and HDMI port control. + * The same register may be used for SDVO or HDMI */ +#define _GEN3_SDVOB 0x61140 +#define _GEN3_SDVOC 0x61160 +#define GEN3_SDVOB _MMIO(_GEN3_SDVOB) +#define GEN3_SDVOC _MMIO(_GEN3_SDVOC) +#define GEN4_HDMIB GEN3_SDVOB +#define GEN4_HDMIC GEN3_SDVOC +#define VLV_HDMIB _MMIO(VLV_DISPLAY_BASE + 0x61140) +#define VLV_HDMIC _MMIO(VLV_DISPLAY_BASE + 0x61160) +#define CHV_HDMID _MMIO(VLV_DISPLAY_BASE + 0x6116C) +#define PCH_SDVOB _MMIO(0xe1140) +#define PCH_HDMIB PCH_SDVOB +#define PCH_HDMIC _MMIO(0xe1150) +#define PCH_HDMID _MMIO(0xe1160) + +#define PORT_DFT_I9XX _MMIO(0x61150) +#define DC_BALANCE_RESET (1 << 25) +#define PORT_DFT2_G4X(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61154) +#define DC_BALANCE_RESET_VLV (1 << 31) +#define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0)) +#define PIPE_C_SCRAMBLE_RESET REG_BIT(14) /* chv */ +#define PIPE_B_SCRAMBLE_RESET REG_BIT(1) +#define PIPE_A_SCRAMBLE_RESET REG_BIT(0) + +/* Gen 3 SDVO bits: */ +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_SEL_SHIFT 30 +#define SDVO_PIPE_SEL_MASK (1 << 30) +#define SDVO_PIPE_SEL(pipe) ((pipe) << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/* + * 915G/GM SDVO pixel multiplier. + * Programmed value is multiplier - 1, up to 5x. + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) /* Port C only */ +#define SDVO_BORDER_ENABLE (1 << 7) /* SDVO only */ +#define SDVOB_PCIE_CONCURRENCY (1 << 3) /* Port B only */ +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | \ + SDVO_INTERRUPT_ENABLE) +#define SDVOC_PRESERVE_MASK ((1 << 17) | SDVO_INTERRUPT_ENABLE) + +/* Gen 4 SDVO/HDMI bits: */ +#define SDVO_COLOR_FORMAT_8bpc (0 << 26) +#define SDVO_COLOR_FORMAT_MASK (7 << 26) +#define SDVO_ENCODING_SDVO (0 << 10) +#define SDVO_ENCODING_HDMI (2 << 10) +#define HDMI_MODE_SELECT_HDMI (1 << 9) /* HDMI only */ +#define HDMI_MODE_SELECT_DVI (0 << 9) /* HDMI only */ +#define HDMI_COLOR_RANGE_16_235 (1 << 8) /* HDMI only */ +#define HDMI_AUDIO_ENABLE (1 << 6) /* HDMI only */ +/* VSYNC/HSYNC bits new with 965, default is to be set */ +#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) + +/* Gen 5 (IBX) SDVO/HDMI bits: */ +#define HDMI_COLOR_FORMAT_12bpc (3 << 26) /* HDMI only */ +#define SDVOB_HOTPLUG_ENABLE (1 << 23) /* SDVO only */ + +/* Gen 6 (CPT) SDVO/HDMI bits: */ +#define SDVO_PIPE_SEL_SHIFT_CPT 29 +#define SDVO_PIPE_SEL_MASK_CPT (3 << 29) +#define SDVO_PIPE_SEL_CPT(pipe) ((pipe) << 29) + +/* CHV SDVO/HDMI bits: */ +#define SDVO_PIPE_SEL_SHIFT_CHV 24 +#define SDVO_PIPE_SEL_MASK_CHV (3 << 24) +#define SDVO_PIPE_SEL_CHV(pipe) ((pipe) << 24) + +/* Video Data Island Packet control */ +#define VIDEO_DIP_DATA _MMIO(0x61178) +/* Read the description of VIDEO_DIP_DATA (before Haswell) or VIDEO_DIP_ECC + * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte + * of the infoframe structure specified by CEA-861. */ +#define VIDEO_DIP_DATA_SIZE 32 +#define VIDEO_DIP_ASYNC_DATA_SIZE 36 +#define VIDEO_DIP_GMP_DATA_SIZE 36 +#define VIDEO_DIP_VSC_DATA_SIZE 36 +#define VIDEO_DIP_PPS_DATA_SIZE 132 +#define VIDEO_DIP_CTL _MMIO(0x61170) +/* Pre HSW: */ +#define VIDEO_DIP_ENABLE (1 << 31) +#define VIDEO_DIP_PORT(port) ((port) << 29) +#define VIDEO_DIP_PORT_MASK (3 << 29) +#define VIDEO_DIP_ENABLE_GCP (1 << 25) /* ilk+ */ +#define VIDEO_DIP_ENABLE_AVI (1 << 21) +#define VIDEO_DIP_ENABLE_VENDOR (2 << 21) +#define VIDEO_DIP_ENABLE_GAMUT (4 << 21) /* ilk+ */ +#define VIDEO_DIP_ENABLE_SPD (8 << 21) +#define VIDEO_DIP_SELECT_AVI (0 << 19) +#define VIDEO_DIP_SELECT_VENDOR (1 << 19) +#define VIDEO_DIP_SELECT_GAMUT (2 << 19) +#define VIDEO_DIP_SELECT_SPD (3 << 19) +#define VIDEO_DIP_SELECT_MASK (3 << 19) +#define VIDEO_DIP_FREQ_ONCE (0 << 16) +#define VIDEO_DIP_FREQ_VSYNC (1 << 16) +#define VIDEO_DIP_FREQ_2VSYNC (2 << 16) +#define VIDEO_DIP_FREQ_MASK (3 << 16) +/* HSW and later: */ +#define VIDEO_DIP_ENABLE_DRM_GLK (1 << 28) +#define PSR_VSC_BIT_7_SET (1 << 27) +#define VSC_SELECT_MASK (0x3 << 25) +#define VSC_SELECT_SHIFT 25 +#define VSC_DIP_HW_HEA_DATA (0 << 25) +#define VSC_DIP_HW_HEA_SW_DATA (1 << 25) +#define VSC_DIP_HW_DATA_SW_HEA (2 << 25) +#define VSC_DIP_SW_HEA_DATA (3 << 25) +#define VDIP_ENABLE_PPS (1 << 24) +#define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) +#define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) +#define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) +#define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) +#define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) +#define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) +/* ADL and later: */ +#define VIDEO_DIP_ENABLE_AS_ADL REG_BIT(23) + +#define PCH_GTC_CTL _MMIO(0xe7000) +#define PCH_GTC_ENABLE (1 << 31) + +/* Display Port */ +#define DP_A _MMIO(0x64000) /* eDP */ +#define DP_B _MMIO(0x64100) +#define DP_C _MMIO(0x64200) +#define DP_D _MMIO(0x64300) +#define VLV_DP_B _MMIO(VLV_DISPLAY_BASE + 0x64100) +#define VLV_DP_C _MMIO(VLV_DISPLAY_BASE + 0x64200) +#define CHV_DP_D _MMIO(VLV_DISPLAY_BASE + 0x64300) +#define DP_PORT_EN REG_BIT(31) +#define DP_PIPE_SEL_MASK REG_GENMASK(30, 30) +#define DP_PIPE_SEL(pipe) REG_FIELD_PREP(DP_PIPE_SEL_MASK, (pipe)) +#define DP_PIPE_SEL_MASK_IVB REG_GENMASK(30, 29) +#define DP_PIPE_SEL_IVB(pipe) REG_FIELD_PREP(DP_PIPE_SEL_MASK_IVB, (pipe)) +#define DP_PIPE_SEL_SHIFT_CHV 16 +#define DP_PIPE_SEL_MASK_CHV REG_GENMASK(17, 16) +#define DP_PIPE_SEL_CHV(pipe) REG_FIELD_PREP(DP_PIPE_SEL_MASK_CHV, (pipe)) +#define DP_LINK_TRAIN_MASK REG_GENMASK(29, 28) +#define DP_LINK_TRAIN_PAT_1 REG_FIELD_PREP(DP_LINK_TRAIN_MASK, 0) +#define DP_LINK_TRAIN_PAT_2 REG_FIELD_PREP(DP_LINK_TRAIN_MASK, 1) +#define DP_LINK_TRAIN_PAT_IDLE REG_FIELD_PREP(DP_LINK_TRAIN_MASK, 2) +#define DP_LINK_TRAIN_OFF REG_FIELD_PREP(DP_LINK_TRAIN_MASK, 3) +#define DP_LINK_TRAIN_MASK_CPT REG_GENMASK(10, 8) +#define DP_LINK_TRAIN_PAT_1_CPT REG_FIELD_PREP(DP_LINK_TRAIN_MASK_CPT, 0) +#define DP_LINK_TRAIN_PAT_2_CPT REG_FIELD_PREP(DP_LINK_TRAIN_MASK_CPT, 1) +#define DP_LINK_TRAIN_PAT_IDLE_CPT REG_FIELD_PREP(DP_LINK_TRAIN_MASK_CPT, 2) +#define DP_LINK_TRAIN_OFF_CPT REG_FIELD_PREP(DP_LINK_TRAIN_MASK_CPT, 3) +#define DP_VOLTAGE_MASK REG_GENMASK(27, 25) +#define DP_VOLTAGE_0_4 REG_FIELD_PREP(DP_VOLTAGE_MASK, 0) +#define DP_VOLTAGE_0_6 REG_FIELD_PREP(DP_VOLTAGE_MASK, 1) +#define DP_VOLTAGE_0_8 REG_FIELD_PREP(DP_VOLTAGE_MASK, 2) +#define DP_VOLTAGE_1_2 REG_FIELD_PREP(DP_VOLTAGE_MASK, 3) +#define DP_PRE_EMPHASIS_MASK REG_GENMASK(24, 22) +#define DP_PRE_EMPHASIS_0 REG_FIELD_PREP(DP_PRE_EMPHASIS_MASK, 0) +#define DP_PRE_EMPHASIS_3_5 REG_FIELD_PREP(DP_PRE_EMPHASIS_MASK, 1) +#define DP_PRE_EMPHASIS_6 REG_FIELD_PREP(DP_PRE_EMPHASIS_MASK, 2) +#define DP_PRE_EMPHASIS_9_5 REG_FIELD_PREP(DP_PRE_EMPHASIS_MASK, 3) +#define DP_PORT_WIDTH_MASK REG_GENMASK(21, 19) +#define DP_PORT_WIDTH(width) REG_FIELD_PREP(DP_PORT_WIDTH_MASK, (width) - 1) +#define DP_ENHANCED_FRAMING REG_BIT(18) +#define EDP_PLL_FREQ_MASK REG_GENMASK(17, 16) +#define EDP_PLL_FREQ_270MHZ REG_FIELD_PREP(EDP_PLL_FREQ_MASK, 0) +#define EDP_PLL_FREQ_162MHZ REG_FIELD_PREP(EDP_PLL_FREQ_MASK, 1) +#define DP_PORT_REVERSAL REG_BIT(15) +#define EDP_PLL_ENABLE REG_BIT(14) +#define DP_CLOCK_OUTPUT_ENABLE REG_BIT(13) +#define DP_SCRAMBLING_DISABLE REG_BIT(12) +#define DP_SCRAMBLING_DISABLE_ILK REG_BIT(7) +#define DP_COLOR_RANGE_16_235 REG_BIT(8) +#define DP_AUDIO_OUTPUT_ENABLE REG_BIT(6) +#define DP_SYNC_VS_HIGH REG_BIT(4) +#define DP_SYNC_HS_HIGH REG_BIT(3) +#define DP_DETECTED REG_BIT(2) + +/* + * Computing GMCH M and N values for the Display Port link + * + * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes + * + * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz) + * + * The GMCH value is used internally + * + * bytes_per_pixel is the number of bytes coming out of the plane, + * which is after the LUTs, so we want the bytes for our color format. + * For our current usage, this is always 3, one byte for R, G and B. + */ +#define _PIPEA_DATA_M_G4X 0x70050 +#define _PIPEB_DATA_M_G4X 0x71050 +#define PIPE_DATA_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X) +/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ +#define TU_SIZE_MASK REG_GENMASK(30, 25) +#define TU_SIZE(x) REG_FIELD_PREP(TU_SIZE_MASK, (x) - 1) /* default size 64 */ +#define DATA_LINK_M_N_MASK REG_GENMASK(23, 0) +#define DATA_LINK_N_MAX (0x800000) + +#define _PIPEA_DATA_N_G4X 0x70054 +#define _PIPEB_DATA_N_G4X 0x71054 +#define PIPE_DATA_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X) + +/* + * Computing Link M and N values for the Display Port link + * + * Link M / N = pixel_clock / ls_clk + * + * (the DP spec calls pixel_clock the 'strm_clk') + * + * The Link value is transmitted in the Main Stream + * Attributes and VB-ID. + */ +#define _PIPEA_LINK_M_G4X 0x70060 +#define _PIPEB_LINK_M_G4X 0x71060 +#define PIPE_LINK_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X) + +#define _PIPEA_LINK_N_G4X 0x70064 +#define _PIPEB_LINK_N_G4X 0x71064 +#define PIPE_LINK_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X) + +/* Pipe A */ +#define _PIPEADSL 0x70000 +#define PIPEDSL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEADSL) +#define PIPEDSL_CURR_FIELD REG_BIT(31) /* ctg+ */ +#define PIPEDSL_LINE_MASK REG_GENMASK(19, 0) + +#define _TRANSACONF 0x70008 +#define TRANSCONF(dev_priv, trans) _MMIO_PIPE2(dev_priv, (trans), _TRANSACONF) +#define TRANSCONF_ENABLE REG_BIT(31) +#define TRANSCONF_DOUBLE_WIDE REG_BIT(30) /* pre-i965 */ +#define TRANSCONF_STATE_ENABLE REG_BIT(30) /* i965+ */ +#define TRANSCONF_DSI_PLL_LOCKED REG_BIT(29) /* vlv & pipe A only */ +#define TRANSCONF_FRAME_START_DELAY_MASK REG_GENMASK(28, 27) /* pre-hsw */ +#define TRANSCONF_FRAME_START_DELAY(x) REG_FIELD_PREP(TRANSCONF_FRAME_START_DELAY_MASK, (x)) /* pre-hsw: 0-3 */ +#define TRANSCONF_PIPE_LOCKED REG_BIT(25) +#define TRANSCONF_FORCE_BORDER REG_BIT(25) +#define TRANSCONF_GAMMA_MODE_MASK_I9XX REG_BIT(24) /* gmch */ +#define TRANSCONF_GAMMA_MODE_MASK_ILK REG_GENMASK(25, 24) /* ilk-ivb */ +#define TRANSCONF_GAMMA_MODE_8BIT REG_FIELD_PREP(TRANSCONF_GAMMA_MODE_MASK, 0) +#define TRANSCONF_GAMMA_MODE_10BIT REG_FIELD_PREP(TRANSCONF_GAMMA_MODE_MASK, 1) +#define TRANSCONF_GAMMA_MODE_12BIT REG_FIELD_PREP(TRANSCONF_GAMMA_MODE_MASK_ILK, 2) /* ilk-ivb */ +#define TRANSCONF_GAMMA_MODE_SPLIT REG_FIELD_PREP(TRANSCONF_GAMMA_MODE_MASK_ILK, 3) /* ivb */ +#define TRANSCONF_GAMMA_MODE(x) REG_FIELD_PREP(TRANSCONF_GAMMA_MODE_MASK_ILK, (x)) /* pass in GAMMA_MODE_MODE_* */ +#define TRANSCONF_INTERLACE_MASK REG_GENMASK(23, 21) /* gen3+ */ +#define TRANSCONF_INTERLACE_PROGRESSIVE REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK, 0) +#define TRANSCONF_INTERLACE_W_SYNC_SHIFT_PANEL REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK, 4) /* gen4 only */ +#define TRANSCONF_INTERLACE_W_SYNC_SHIFT REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK, 5) /* gen4 only */ +#define TRANSCONF_INTERLACE_W_FIELD_INDICATION REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK, 6) +#define TRANSCONF_INTERLACE_FIELD_0_ONLY REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK, 7) /* gen3 only */ +/* + * ilk+: PF/D=progressive fetch/display, IF/D=interlaced fetch/display, + * DBL=power saving pixel doubling, PF-ID* requires panel fitter + */ +#define TRANSCONF_INTERLACE_MASK_ILK REG_GENMASK(23, 21) /* ilk+ */ +#define TRANSCONF_INTERLACE_MASK_HSW REG_GENMASK(22, 21) /* hsw+ */ +#define TRANSCONF_INTERLACE_PF_PD_ILK REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK_ILK, 0) +#define TRANSCONF_INTERLACE_PF_ID_ILK REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK_ILK, 1) +#define TRANSCONF_INTERLACE_IF_ID_ILK REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK_ILK, 3) +#define TRANSCONF_INTERLACE_IF_ID_DBL_ILK REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK_ILK, 4) /* ilk/snb only */ +#define TRANSCONF_INTERLACE_PF_ID_DBL_ILK REG_FIELD_PREP(TRANSCONF_INTERLACE_MASK_ILK, 5) /* ilk/snb only */ +#define TRANSCONF_REFRESH_RATE_ALT_ILK REG_BIT(20) +#define TRANSCONF_MSA_TIMING_DELAY_MASK REG_GENMASK(19, 18) /* ilk/snb/ivb */ +#define TRANSCONF_MSA_TIMING_DELAY(x) REG_FIELD_PREP(TRANSCONF_MSA_TIMING_DELAY_MASK, (x)) +#define TRANSCONF_CXSR_DOWNCLOCK REG_BIT(16) +#define TRANSCONF_WGC_ENABLE REG_BIT(15) /* vlv/chv only */ +#define TRANSCONF_REFRESH_RATE_ALT_VLV REG_BIT(14) +#define TRANSCONF_COLOR_RANGE_SELECT REG_BIT(13) +#define TRANSCONF_OUTPUT_COLORSPACE_MASK REG_GENMASK(12, 11) /* ilk-ivb */ +#define TRANSCONF_OUTPUT_COLORSPACE_RGB REG_FIELD_PREP(TRANSCONF_OUTPUT_COLORSPACE_MASK, 0) /* ilk-ivb */ +#define TRANSCONF_OUTPUT_COLORSPACE_YUV601 REG_FIELD_PREP(TRANSCONF_OUTPUT_COLORSPACE_MASK, 1) /* ilk-ivb */ +#define TRANSCONF_OUTPUT_COLORSPACE_YUV709 REG_FIELD_PREP(TRANSCONF_OUTPUT_COLORSPACE_MASK, 2) /* ilk-ivb */ +#define TRANSCONF_OUTPUT_COLORSPACE_YUV_HSW REG_BIT(11) /* hsw only */ +#define TRANSCONF_BPC_MASK REG_GENMASK(7, 5) /* ctg-ivb */ +#define TRANSCONF_BPC_8 REG_FIELD_PREP(TRANSCONF_BPC_MASK, 0) +#define TRANSCONF_BPC_10 REG_FIELD_PREP(TRANSCONF_BPC_MASK, 1) +#define TRANSCONF_BPC_6 REG_FIELD_PREP(TRANSCONF_BPC_MASK, 2) +#define TRANSCONF_BPC_12 REG_FIELD_PREP(TRANSCONF_BPC_MASK, 3) +#define TRANSCONF_DITHER_EN REG_BIT(4) +#define TRANSCONF_DITHER_TYPE_MASK REG_GENMASK(3, 2) +#define TRANSCONF_DITHER_TYPE_SP REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 0) +#define TRANSCONF_DITHER_TYPE_ST1 REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 1) +#define TRANSCONF_DITHER_TYPE_ST2 REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 2) +#define TRANSCONF_DITHER_TYPE_TEMP REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 3) +#define TRANSCONF_PIXEL_COUNT_SCALING_MASK REG_GENMASK(1, 0) +#define TRANSCONF_PIXEL_COUNT_SCALING_X4 1 + +#define _PIPEASTAT 0x70024 +#define PIPESTAT(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEASTAT) +#define PIPE_FIFO_UNDERRUN_STATUS (1UL << 31) +#define SPRITE1_FLIP_DONE_INT_EN_VLV (1UL << 30) +#define PIPE_CRC_ERROR_ENABLE (1UL << 29) +#define PIPE_CRC_DONE_ENABLE (1UL << 28) +#define PERF_COUNTER2_INTERRUPT_EN (1UL << 27) +#define PIPE_GMBUS_EVENT_ENABLE (1UL << 27) +#define PLANE_FLIP_DONE_INT_EN_VLV (1UL << 26) +#define PIPE_HOTPLUG_INTERRUPT_ENABLE (1UL << 26) +#define PIPE_VSYNC_INTERRUPT_ENABLE (1UL << 25) +#define PIPE_DISPLAY_LINE_COMPARE_ENABLE (1UL << 24) +#define PIPE_DPST_EVENT_ENABLE (1UL << 23) +#define SPRITE0_FLIP_DONE_INT_EN_VLV (1UL << 22) +#define PIPE_LEGACY_BLC_EVENT_ENABLE (1UL << 22) +#define PIPE_ODD_FIELD_INTERRUPT_ENABLE (1UL << 21) +#define PIPE_EVEN_FIELD_INTERRUPT_ENABLE (1UL << 20) +#define PIPE_B_PSR_INTERRUPT_ENABLE_VLV (1UL << 19) +#define PERF_COUNTER_INTERRUPT_EN (1UL << 19) +#define PIPE_HOTPLUG_TV_INTERRUPT_ENABLE (1UL << 18) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) /* 965 or later */ +#define PIPE_FRAMESTART_INTERRUPT_ENABLE (1UL << 17) +#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) +#define PIPEA_HBLANK_INT_EN_VLV (1UL << 16) +#define PIPE_OVERLAY_UPDATED_ENABLE (1UL << 16) +#define SPRITE1_FLIP_DONE_INT_STATUS_VLV (1UL << 15) +#define SPRITE0_FLIP_DONE_INT_STATUS_VLV (1UL << 14) +#define PIPE_CRC_ERROR_INTERRUPT_STATUS (1UL << 13) +#define PIPE_CRC_DONE_INTERRUPT_STATUS (1UL << 12) +#define PERF_COUNTER2_INTERRUPT_STATUS (1UL << 11) +#define PIPE_GMBUS_INTERRUPT_STATUS (1UL << 11) +#define PLANE_FLIP_DONE_INT_STATUS_VLV (1UL << 10) +#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) +#define PIPE_VSYNC_INTERRUPT_STATUS (1UL << 9) +#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL << 8) +#define PIPE_DPST_EVENT_STATUS (1UL << 7) +#define PIPE_A_PSR_STATUS_VLV (1UL << 6) +#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL << 6) +#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL << 5) +#define PIPE_EVEN_FIELD_INTERRUPT_STATUS (1UL << 4) +#define PIPE_B_PSR_STATUS_VLV (1UL << 3) +#define PERF_COUNTER_INTERRUPT_STATUS (1UL << 3) +#define PIPE_HOTPLUG_TV_INTERRUPT_STATUS (1UL << 2) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) /* 965 or later */ +#define PIPE_FRAMESTART_INTERRUPT_STATUS (1UL << 1) +#define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) +#define PIPE_HBLANK_INT_STATUS (1UL << 0) +#define PIPE_OVERLAY_UPDATED_STATUS (1UL << 0) +#define PIPESTAT_INT_ENABLE_MASK 0x7fff0000 +#define PIPESTAT_INT_STATUS_MASK 0x0000ffff + +#define _PIPE_ARB_CTL_A 0x70028 /* icl+ */ +#define PIPE_ARB_CTL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPE_ARB_CTL_A) +#define PIPE_ARB_USE_PROG_SLOTS REG_BIT(13) + +#define _PIPE_MISC_A 0x70030 +#define _PIPE_MISC_B 0x71030 +#define PIPE_MISC(pipe) _MMIO_PIPE(pipe, _PIPE_MISC_A, _PIPE_MISC_B) +#define PIPE_MISC_YUV420_ENABLE REG_BIT(27) /* glk+ */ +#define PIPE_MISC_YUV420_MODE_FULL_BLEND REG_BIT(26) /* glk+ */ +#define PIPE_MISC_HDR_MODE_PRECISION REG_BIT(23) /* icl+ */ +#define PIPE_MISC_PSR_MASK_PRIMARY_FLIP REG_BIT(23) /* bdw */ +#define PIPE_MISC_PSR_MASK_SPRITE_ENABLE REG_BIT(22) /* bdw */ +#define PIPE_MISC_PSR_MASK_PIPE_REG_WRITE REG_BIT(21) /* skl+ */ +#define PIPE_MISC_PSR_MASK_CURSOR_MOVE REG_BIT(21) /* bdw */ +#define PIPE_MISC_PSR_MASK_VBLANK_VSYNC_INT REG_BIT(20) +#define PIPE_MISC_OUTPUT_COLORSPACE_YUV REG_BIT(11) +#define PIPE_MISC_PIXEL_ROUNDING_TRUNC REG_BIT(8) /* tgl+ */ +/* + * For Display < 13, Bits 5-7 of PIPE MISC represent DITHER BPC with + * valid values of: 6, 8, 10 BPC. + * ADLP+, the bits 5-7 represent PORT OUTPUT BPC with valid values of: + * 6, 8, 10, 12 BPC. + */ +#define PIPE_MISC_BPC_MASK REG_GENMASK(7, 5) +#define PIPE_MISC_BPC_8 REG_FIELD_PREP(PIPE_MISC_BPC_MASK, 0) +#define PIPE_MISC_BPC_10 REG_FIELD_PREP(PIPE_MISC_BPC_MASK, 1) +#define PIPE_MISC_BPC_6 REG_FIELD_PREP(PIPE_MISC_BPC_MASK, 2) +#define PIPE_MISC_BPC_12_ADLP REG_FIELD_PREP(PIPE_MISC_BPC_MASK, 4) /* adlp+ */ +#define PIPE_MISC_DITHER_ENABLE REG_BIT(4) +#define PIPE_MISC_DITHER_TYPE_MASK REG_GENMASK(3, 2) +#define PIPE_MISC_DITHER_TYPE_SP REG_FIELD_PREP(PIPE_MISC_DITHER_TYPE_MASK, 0) +#define PIPE_MISC_DITHER_TYPE_ST1 REG_FIELD_PREP(PIPE_MISC_DITHER_TYPE_MASK, 1) +#define PIPE_MISC_DITHER_TYPE_ST2 REG_FIELD_PREP(PIPE_MISC_DITHER_TYPE_MASK, 2) +#define PIPE_MISC_DITHER_TYPE_TEMP REG_FIELD_PREP(PIPE_MISC_DITHER_TYPE_MASK, 3) + +#define _PIPE_MISC2_A 0x7002C +#define _PIPE_MISC2_B 0x7102C +#define PIPE_MISC2(pipe) _MMIO_PIPE(pipe, _PIPE_MISC2_A, _PIPE_MISC2_B) +#define PIPE_MISC2_BUBBLE_COUNTER_MASK REG_GENMASK(31, 24) +#define PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN REG_FIELD_PREP(PIPE_MISC2_BUBBLE_COUNTER_MASK, 80) +#define PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS REG_FIELD_PREP(PIPE_MISC2_BUBBLE_COUNTER_MASK, 20) +#define PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK REG_GENMASK(2, 0) /* tgl+ */ +#define PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id) REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id)) + +#define DPINVGTT _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */ +#define DPINVGTT_EN_MASK_CHV REG_GENMASK(27, 16) +#define DPINVGTT_EN_MASK_VLV REG_GENMASK(23, 16) +#define SPRITEF_INVALID_GTT_INT_EN REG_BIT(27) +#define SPRITEE_INVALID_GTT_INT_EN REG_BIT(26) +#define PLANEC_INVALID_GTT_INT_EN REG_BIT(25) +#define CURSORC_INVALID_GTT_INT_EN REG_BIT(24) +#define CURSORB_INVALID_GTT_INT_EN REG_BIT(23) +#define CURSORA_INVALID_GTT_INT_EN REG_BIT(22) +#define SPRITED_INVALID_GTT_INT_EN REG_BIT(21) +#define SPRITEC_INVALID_GTT_INT_EN REG_BIT(20) +#define PLANEB_INVALID_GTT_INT_EN REG_BIT(19) +#define SPRITEB_INVALID_GTT_INT_EN REG_BIT(18) +#define SPRITEA_INVALID_GTT_INT_EN REG_BIT(17) +#define PLANEA_INVALID_GTT_INT_EN REG_BIT(16) +#define DPINVGTT_STATUS_MASK_CHV REG_GENMASK(11, 0) +#define DPINVGTT_STATUS_MASK_VLV REG_GENMASK(7, 0) +#define SPRITEF_INVALID_GTT_STATUS REG_BIT(11) +#define SPRITEE_INVALID_GTT_STATUS REG_BIT(10) +#define PLANEC_INVALID_GTT_STATUS REG_BIT(9) +#define CURSORC_INVALID_GTT_STATUS REG_BIT(8) +#define CURSORB_INVALID_GTT_STATUS REG_BIT(7) +#define CURSORA_INVALID_GTT_STATUS REG_BIT(6) +#define SPRITED_INVALID_GTT_STATUS REG_BIT(5) +#define SPRITEC_INVALID_GTT_STATUS REG_BIT(4) +#define PLANEB_INVALID_GTT_STATUS REG_BIT(3) +#define SPRITEB_INVALID_GTT_STATUS REG_BIT(2) +#define SPRITEA_INVALID_GTT_STATUS REG_BIT(1) +#define PLANEA_INVALID_GTT_STATUS REG_BIT(0) + +#define CBR1_VLV _MMIO(VLV_DISPLAY_BASE + 0x70400) +#define CBR_PND_DEADLINE_DISABLE (1 << 31) +#define CBR_PWM_CLOCK_MUX_SELECT (1 << 30) + +#define CBR4_VLV _MMIO(VLV_DISPLAY_BASE + 0x70450) +#define CBR_DPLLBMD_PIPE(pipe) (1 << (7 + (pipe) * 11)) /* pipes B and C */ + +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> + * PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define _PIPEAFRAMEHIGH 0x70040 +#define PIPEFRAME(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEHIGH) +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 + +#define _PIPEAFRAMEPIXEL 0x70044 +#define PIPEFRAMEPIXEL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEPIXEL) +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 + +/* GM45+ just has to be different */ +#define _PIPEA_FRMCOUNT_G4X 0x70040 +#define PIPE_FRMCOUNT_G4X(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FRMCOUNT_G4X) + +#define _PIPEA_FLIPCOUNT_G4X 0x70044 +#define PIPE_FLIPCOUNT_G4X(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FLIPCOUNT_G4X) + +/* CHV pipe B blender */ +#define _CHV_BLEND_A 0x60a00 +#define CHV_BLEND(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_BLEND_A) +#define CHV_BLEND_MASK REG_GENMASK(31, 30) +#define CHV_BLEND_LEGACY REG_FIELD_PREP(CHV_BLEND_MASK, 0) +#define CHV_BLEND_ANDROID REG_FIELD_PREP(CHV_BLEND_MASK, 1) +#define CHV_BLEND_MPO REG_FIELD_PREP(CHV_BLEND_MASK, 2) + +#define _CHV_CANVAS_A 0x60a04 +#define CHV_CANVAS(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_CANVAS_A) +#define CHV_CANVAS_RED_MASK REG_GENMASK(29, 20) +#define CHV_CANVAS_GREEN_MASK REG_GENMASK(19, 10) +#define CHV_CANVAS_BLUE_MASK REG_GENMASK(9, 0) + +/* Display/Sprite base address macros */ +#define DISP_BASEADDR_MASK (0xfffff000) +#define I915_LO_DISPBASE(val) ((val) & ~DISP_BASEADDR_MASK) +#define I915_HI_DISPBASE(val) ((val) & DISP_BASEADDR_MASK) + +/* + * VBIOS flags + * gen2: + * [00:06] alm,mgm + * [10:16] all + * [30:32] alm,mgm + * gen3+: + * [00:0f] all + * [10:1f] all + * [30:32] all + */ +#define SWF0(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70410 + (i) * 4) +#define SWF1(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x71410 + (i) * 4) +#define SWF3(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4) +#define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4) + +#define DIGITAL_PORT_HOTPLUG_CNTRL _MMIO(0x44030) +#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) +#define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_4_5ms (1 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_6ms (2 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_100ms (3 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_PULSE_DURATION_MASK (3 << 2) /* pre-HSW */ +#define DIGITAL_PORTA_HOTPLUG_STATUS_MASK (3 << 0) +#define DIGITAL_PORTA_HOTPLUG_NO_DETECT (0 << 0) +#define DIGITAL_PORTA_HOTPLUG_SHORT_DETECT (1 << 0) +#define DIGITAL_PORTA_HOTPLUG_LONG_DETECT (2 << 0) + +/* refresh rate hardware control */ +#define RR_HW_CTL _MMIO(0x45300) +#define RR_HW_LOW_POWER_FRAMES_MASK 0xff +#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 + +#define _PIPEA_DATA_M1 0x60030 +#define _PIPEB_DATA_M1 0x61030 +#define PIPE_DATA_M1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M1) + +#define _PIPEA_DATA_N1 0x60034 +#define _PIPEB_DATA_N1 0x61034 +#define PIPE_DATA_N1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N1) + +#define _PIPEA_DATA_M2 0x60038 +#define _PIPEB_DATA_M2 0x61038 +#define PIPE_DATA_M2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M2) + +#define _PIPEA_DATA_N2 0x6003c +#define _PIPEB_DATA_N2 0x6103c +#define PIPE_DATA_N2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N2) + +#define _PIPEA_LINK_M1 0x60040 +#define _PIPEB_LINK_M1 0x61040 +#define PIPE_LINK_M1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M1) + +#define _PIPEA_LINK_N1 0x60044 +#define _PIPEB_LINK_N1 0x61044 +#define PIPE_LINK_N1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N1) + +#define _PIPEA_LINK_M2 0x60048 +#define _PIPEB_LINK_M2 0x61048 +#define PIPE_LINK_M2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M2) + +#define _PIPEA_LINK_N2 0x6004c +#define _PIPEB_LINK_N2 0x6104c +#define PIPE_LINK_N2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N2) + +/* + * Skylake scalers + */ +#define _ID(id, a, b) _PICK_EVEN(id, a, b) +#define _PS_1A_CTRL 0x68180 +#define _PS_2A_CTRL 0x68280 +#define _PS_1B_CTRL 0x68980 +#define _PS_2B_CTRL 0x68A80 +#define _PS_1C_CTRL 0x69180 +#define SKL_PS_CTRL(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_1A_CTRL, _PS_2A_CTRL), \ + _ID(id, _PS_1B_CTRL, _PS_2B_CTRL)) +#define PS_SCALER_EN REG_BIT(31) +#define PS_SCALER_TYPE_MASK REG_BIT(30) /* icl+ */ +#define PS_SCALER_TYPE_NON_LINEAR REG_FIELD_PREP(PS_SCALER_TYPE_MASK, 0) +#define PS_SCALER_TYPE_LINEAR REG_FIELD_PREP(PS_SCALER_TYPE_MASK, 1) +#define SKL_PS_SCALER_MODE_MASK REG_GENMASK(29, 28) /* skl/bxt */ +#define SKL_PS_SCALER_MODE_DYN REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 0) +#define SKL_PS_SCALER_MODE_HQ REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 1) +#define SKL_PS_SCALER_MODE_NV12 REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 2) +#define PS_SCALER_MODE_MASK REG_BIT(29) /* glk-tgl */ +#define PS_SCALER_MODE_NORMAL REG_FIELD_PREP(PS_SCALER_MODE_MASK, 0) +#define PS_SCALER_MODE_PLANAR REG_FIELD_PREP(PS_SCALER_MODE_MASK, 1) +#define PS_ADAPTIVE_FILTERING_EN REG_BIT(28) /* icl+ */ +#define PS_BINDING_MASK REG_GENMASK(27, 25) +#define PS_BINDING_PIPE REG_FIELD_PREP(PS_BINDING_MASK, 0) +#define PS_BINDING_PLANE(plane_id) REG_FIELD_PREP(PS_BINDING_MASK, (plane_id) + 1) +#define PS_FILTER_MASK REG_GENMASK(24, 23) +#define PS_FILTER_MEDIUM REG_FIELD_PREP(PS_FILTER_MASK, 0) +#define PS_FILTER_PROGRAMMED REG_FIELD_PREP(PS_FILTER_MASK, 1) +#define PS_FILTER_EDGE_ENHANCE REG_FIELD_PREP(PS_FILTER_MASK, 2) +#define PS_FILTER_BILINEAR REG_FIELD_PREP(PS_FILTER_MASK, 3) +#define PS_ADAPTIVE_FILTER_MASK REG_BIT(22) /* icl+ */ +#define PS_ADAPTIVE_FILTER_MEDIUM REG_FIELD_PREP(PS_ADAPTIVE_FILTER_MASK, 0) +#define PS_ADAPTIVE_FILTER_EDGE_ENHANCE REG_FIELD_PREP(PS_ADAPTIVE_FILTER_MASK, 1) +#define PS_PIPE_SCALER_LOC_MASK REG_BIT(21) /* icl+ */ +#define PS_PIPE_SCALER_LOC_AFTER_OUTPUT_CSC REG_FIELD_PREP(PS_SCALER_LOCATION_MASK, 0) /* non-linear */ +#define PS_PIPE_SCALER_LOC_AFTER_CSC REG_FIELD_PREP(PS_SCALER_LOCATION_MASK, 1) /* linear */ +#define PS_VERT3TAP REG_BIT(21) /* skl/bxt */ +#define PS_VERT_INT_INVERT_FIELD REG_BIT(20) +#define PS_PROG_SCALE_FACTOR REG_BIT(19) /* tgl+ */ +#define PS_PWRUP_PROGRESS REG_BIT(17) +#define PS_V_FILTER_BYPASS REG_BIT(8) +#define PS_VADAPT_EN REG_BIT(7) /* skl/bxt */ +#define PS_VADAPT_MODE_MASK REG_GENMASK(6, 5) /* skl/bxt */ +#define PS_VADAPT_MODE_LEAST_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 0) +#define PS_VADAPT_MODE_MOD_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 1) +#define PS_VADAPT_MODE_MOST_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 3) +#define PS_BINDING_Y_MASK REG_GENMASK(7, 5) /* icl-tgl */ +#define PS_BINDING_Y_PLANE(plane_id) REG_FIELD_PREP(PS_BINDING_Y_MASK, (plane_id) + 1) +#define PS_Y_VERT_FILTER_SELECT_MASK REG_BIT(4) /* glk+ */ +#define PS_Y_VERT_FILTER_SELECT(set) REG_FIELD_PREP(PS_Y_VERT_FILTER_SELECT_MASK, (set)) +#define PS_Y_HORZ_FILTER_SELECT_MASK REG_BIT(3) /* glk+ */ +#define PS_Y_HORZ_FILTER_SELECT(set) REG_FIELD_PREP(PS_Y_HORZ_FILTER_SELECT_MASK, (set)) +#define PS_UV_VERT_FILTER_SELECT_MASK REG_BIT(2) /* glk+ */ +#define PS_UV_VERT_FILTER_SELECT(set) REG_FIELD_PREP(PS_UV_VERT_FILTER_SELECT_MASK, (set)) +#define PS_UV_HORZ_FILTER_SELECT_MASK REG_BIT(1) /* glk+ */ +#define PS_UV_HORZ_FILTER_SELECT(set) REG_FIELD_PREP(PS_UV_HORZ_FILTER_SELECT_MASK, (set)) + +#define _PS_PWR_GATE_1A 0x68160 +#define _PS_PWR_GATE_2A 0x68260 +#define _PS_PWR_GATE_1B 0x68960 +#define _PS_PWR_GATE_2B 0x68A60 +#define _PS_PWR_GATE_1C 0x69160 +#define SKL_PS_PWR_GATE(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_PWR_GATE_1A, _PS_PWR_GATE_2A), \ + _ID(id, _PS_PWR_GATE_1B, _PS_PWR_GATE_2B)) +#define PS_PWR_GATE_DIS_OVERRIDE REG_BIT(31) +#define PS_PWR_GATE_SETTLING_TIME_MASK REG_GENMASK(4, 3) +#define PS_PWR_GATE_SETTLING_TIME_32 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 0) +#define PS_PWR_GATE_SETTLING_TIME_64 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 1) +#define PS_PWR_GATE_SETTLING_TIME_96 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 2) +#define PS_PWR_GATE_SETTLING_TIME_128 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 3) +#define PS_PWR_GATE_SLPEN_MASK REG_GENMASK(1, 0) +#define PS_PWR_GATE_SLPEN_8 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 0) +#define PS_PWR_GATE_SLPEN_16 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 1) +#define PS_PWR_GATE_SLPEN_24 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 2) +#define PS_PWR_GATE_SLPEN_32 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 3) + +#define _PS_WIN_POS_1A 0x68170 +#define _PS_WIN_POS_2A 0x68270 +#define _PS_WIN_POS_1B 0x68970 +#define _PS_WIN_POS_2B 0x68A70 +#define _PS_WIN_POS_1C 0x69170 +#define SKL_PS_WIN_POS(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_WIN_POS_1A, _PS_WIN_POS_2A), \ + _ID(id, _PS_WIN_POS_1B, _PS_WIN_POS_2B)) +#define PS_WIN_XPOS_MASK REG_GENMASK(31, 16) +#define PS_WIN_XPOS(x) REG_FIELD_PREP(PS_WIN_XPOS_MASK, (x)) +#define PS_WIN_YPOS_MASK REG_GENMASK(15, 0) +#define PS_WIN_YPOS(y) REG_FIELD_PREP(PS_WIN_YPOS_MASK, (y)) + +#define _PS_WIN_SZ_1A 0x68174 +#define _PS_WIN_SZ_2A 0x68274 +#define _PS_WIN_SZ_1B 0x68974 +#define _PS_WIN_SZ_2B 0x68A74 +#define _PS_WIN_SZ_1C 0x69174 +#define SKL_PS_WIN_SZ(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_WIN_SZ_1A, _PS_WIN_SZ_2A), \ + _ID(id, _PS_WIN_SZ_1B, _PS_WIN_SZ_2B)) +#define PS_WIN_XSIZE_MASK REG_GENMASK(31, 16) +#define PS_WIN_XSIZE(w) REG_FIELD_PREP(PS_WIN_XSIZE_MASK, (w)) +#define PS_WIN_YSIZE_MASK REG_GENMASK(15, 0) +#define PS_WIN_YSIZE(h) REG_FIELD_PREP(PS_WIN_YSIZE_MASK, (h)) + +#define _PS_VSCALE_1A 0x68184 +#define _PS_VSCALE_2A 0x68284 +#define _PS_VSCALE_1B 0x68984 +#define _PS_VSCALE_2B 0x68A84 +#define _PS_VSCALE_1C 0x69184 +#define SKL_PS_VSCALE(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_VSCALE_1A, _PS_VSCALE_2A), \ + _ID(id, _PS_VSCALE_1B, _PS_VSCALE_2B)) + +#define _PS_HSCALE_1A 0x68190 +#define _PS_HSCALE_2A 0x68290 +#define _PS_HSCALE_1B 0x68990 +#define _PS_HSCALE_2B 0x68A90 +#define _PS_HSCALE_1C 0x69190 +#define SKL_PS_HSCALE(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_HSCALE_1A, _PS_HSCALE_2A), \ + _ID(id, _PS_HSCALE_1B, _PS_HSCALE_2B)) + +#define _PS_VPHASE_1A 0x68188 +#define _PS_VPHASE_2A 0x68288 +#define _PS_VPHASE_1B 0x68988 +#define _PS_VPHASE_2B 0x68A88 +#define _PS_VPHASE_1C 0x69188 +#define SKL_PS_VPHASE(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_VPHASE_1A, _PS_VPHASE_2A), \ + _ID(id, _PS_VPHASE_1B, _PS_VPHASE_2B)) +#define PS_Y_PHASE_MASK REG_GENMASK(31, 16) +#define PS_Y_PHASE(x) REG_FIELD_PREP(PS_Y_PHASE_MASK, (x)) +#define PS_UV_RGB_PHASE_MASK REG_GENMASK(15, 0) +#define PS_UV_RGB_PHASE(x) REG_FIELD_PREP(PS_UV_RGB_PHASE_MASK, (x)) +#define PS_PHASE_MASK (0x7fff << 1) /* u2.13 */ +#define PS_PHASE_TRIP (1 << 0) + +#define _PS_HPHASE_1A 0x68194 +#define _PS_HPHASE_2A 0x68294 +#define _PS_HPHASE_1B 0x68994 +#define _PS_HPHASE_2B 0x68A94 +#define _PS_HPHASE_1C 0x69194 +#define SKL_PS_HPHASE(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_HPHASE_1A, _PS_HPHASE_2A), \ + _ID(id, _PS_HPHASE_1B, _PS_HPHASE_2B)) + +#define _PS_ECC_STAT_1A 0x681D0 +#define _PS_ECC_STAT_2A 0x682D0 +#define _PS_ECC_STAT_1B 0x689D0 +#define _PS_ECC_STAT_2B 0x68AD0 +#define _PS_ECC_STAT_1C 0x691D0 +#define SKL_PS_ECC_STAT(pipe, id) _MMIO_PIPE(pipe, \ + _ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \ + _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B)) + +#define _PS_COEF_SET0_INDEX_1A 0x68198 +#define _PS_COEF_SET0_INDEX_2A 0x68298 +#define _PS_COEF_SET0_INDEX_1B 0x68998 +#define _PS_COEF_SET0_INDEX_2B 0x68A98 +#define GLK_PS_COEF_INDEX_SET(pipe, id, set) _MMIO_PIPE(pipe, \ + _ID(id, _PS_COEF_SET0_INDEX_1A, _PS_COEF_SET0_INDEX_2A) + (set) * 8, \ + _ID(id, _PS_COEF_SET0_INDEX_1B, _PS_COEF_SET0_INDEX_2B) + (set) * 8) +#define PS_COEF_INDEX_AUTO_INC REG_BIT(10) + +#define _PS_COEF_SET0_DATA_1A 0x6819C +#define _PS_COEF_SET0_DATA_2A 0x6829C +#define _PS_COEF_SET0_DATA_1B 0x6899C +#define _PS_COEF_SET0_DATA_2B 0x68A9C +#define GLK_PS_COEF_DATA_SET(pipe, id, set) _MMIO_PIPE(pipe, \ + _ID(id, _PS_COEF_SET0_DATA_1A, _PS_COEF_SET0_DATA_2A) + (set) * 8, \ + _ID(id, _PS_COEF_SET0_DATA_1B, _PS_COEF_SET0_DATA_2B) + (set) * 8) + +/* More Ivybridge lolz */ +#define DE_ERR_INT_IVB (1 << 30) +#define DE_GSE_IVB (1 << 29) +#define DE_PCH_EVENT_IVB (1 << 28) +#define DE_DP_A_HOTPLUG_IVB (1 << 27) +#define DE_AUX_CHANNEL_A_IVB (1 << 26) +#define DE_EDP_PSR_INT_HSW (1 << 19) +#define DE_SPRITEC_FLIP_DONE_IVB (1 << 14) +#define DE_PLANEC_FLIP_DONE_IVB (1 << 13) +#define DE_PIPEC_VBLANK_IVB (1 << 10) +#define DE_SPRITEB_FLIP_DONE_IVB (1 << 9) +#define DE_PLANEB_FLIP_DONE_IVB (1 << 8) +#define DE_PIPEB_VBLANK_IVB (1 << 5) +#define DE_SPRITEA_FLIP_DONE_IVB (1 << 4) +#define DE_PLANEA_FLIP_DONE_IVB (1 << 3) +#define DE_PLANE_FLIP_DONE_IVB(plane) (1 << (3 + 5 * (plane))) +#define DE_PIPEA_VBLANK_IVB (1 << 0) +#define DE_PIPE_VBLANK_IVB(pipe) (1 << ((pipe) * 5)) + +#define XELPD_DISPLAY_ERR_FATAL_MASK _MMIO(0x4421c) + +#define GEN8_DE_PIPE_ISR(pipe) _MMIO(0x44400 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IMR(pipe) _MMIO(0x44404 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IIR(pipe) _MMIO(0x44408 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IER(pipe) _MMIO(0x4440c + (0x10 * (pipe))) +#define GEN8_PIPE_FIFO_UNDERRUN REG_BIT(31) +#define GEN8_PIPE_CDCLK_CRC_ERROR REG_BIT(29) +#define GEN8_PIPE_CDCLK_CRC_DONE REG_BIT(28) +#define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */ +#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl-mtl */ +#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl */ +#define GEN12_PIPEDMC_FLIPQ_DONE REG_BIT(24) /* tgl-adl */ +#define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */ +#define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */ +#define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */ +#define GEN12_PIPE_VBLANK_UNMOD REG_BIT(19) /* tgl+ */ +#define MTL_PLANE_ATS_FAULT REG_BIT(18) /* mtl+ */ +#define GEN11_PIPE_PLANE7_FLIP_DONE REG_BIT(18) /* icl/tgl */ +#define MTL_PIPEDMC_FLIPQ_DONE REG_BIT(17) /* mtl */ +#define GEN11_PIPE_PLANE6_FLIP_DONE REG_BIT(17) /* icl/tgl */ +#define GEN11_PIPE_PLANE5_FLIP_DONE REG_BIT(16) /* icl+ */ +#define GEN12_DSB_2_INT REG_BIT(15) /* tgl+ */ +#define GEN12_DSB_1_INT REG_BIT(14) /* tgl+ */ +#define GEN12_DSB_0_INT REG_BIT(13) /* tgl+ */ +#define GEN12_DSB_INT(dsb_id) REG_BIT(13 + (dsb_id)) +#define GEN9_PIPE_CURSOR_FAULT REG_BIT(11) /* skl+ */ +#define GEN9_PIPE_PLANE4_FAULT REG_BIT(10) /* skl+ */ +#define GEN8_PIPE_CURSOR_FAULT REG_BIT(10) /* bdw */ +#define GEN9_PIPE_PLANE3_FAULT REG_BIT(9) /* skl+ */ +#define GEN8_PIPE_SPRITE_FAULT REG_BIT(9) /* bdw */ +#define GEN9_PIPE_PLANE2_FAULT REG_BIT(8) /* skl+ */ +#define GEN8_PIPE_PRIMARY_FAULT REG_BIT(8) /* bdw */ +#define GEN9_PIPE_PLANE1_FAULT REG_BIT(7) /* skl+ */ +#define GEN9_PIPE_PLANE4_FLIP_DONE REG_BIT(6) /* skl+ */ +#define GEN9_PIPE_PLANE3_FLIP_DONE REG_BIT(5) /* skl+ */ +#define GEN8_PIPE_SPRITE_FLIP_DONE REG_BIT(5) /* bdw */ +#define GEN9_PIPE_PLANE2_FLIP_DONE REG_BIT(4) /* skl+ */ +#define GEN8_PIPE_PRIMARY_FLIP_DONE REG_BIT(4) /* bdw */ +#define GEN9_PIPE_PLANE1_FLIP_DONE REG_BIT(3) /* skl+ */ +#define GEN9_PIPE_PLANE_FLIP_DONE(plane_id) \ + REG_BIT(((plane_id) >= PLANE_5 ? 16 - PLANE_5 : 3 - PLANE_1) + (plane_id)) /* skl+ */ +#define GEN8_PIPE_SCAN_LINE_EVENT REG_BIT(2) +#define GEN8_PIPE_VSYNC REG_BIT(1) +#define GEN8_PIPE_VBLANK REG_BIT(0) + +#define GEN8_DE_PIPE_IRQ_REGS(pipe) I915_IRQ_REGS(GEN8_DE_PIPE_IMR(pipe), \ + GEN8_DE_PIPE_IER(pipe), \ + GEN8_DE_PIPE_IIR(pipe)) + +#define _HPD_PIN_DDI(hpd_pin) ((hpd_pin) - HPD_PORT_A) +#define _HPD_PIN_TC(hpd_pin) ((hpd_pin) - HPD_PORT_TC1) + +#define GEN8_DE_PORT_ISR _MMIO(0x44440) +#define GEN8_DE_PORT_IMR _MMIO(0x44444) +#define GEN8_DE_PORT_IIR _MMIO(0x44448) +#define GEN8_DE_PORT_IER _MMIO(0x4444c) +#define DSI1_NON_TE (1 << 31) +#define DSI0_NON_TE (1 << 30) +#define ICL_AUX_CHANNEL_E (1 << 29) +#define ICL_AUX_CHANNEL_F (1 << 28) +#define GEN9_AUX_CHANNEL_D (1 << 27) +#define GEN9_AUX_CHANNEL_C (1 << 26) +#define GEN9_AUX_CHANNEL_B (1 << 25) +#define DSI1_TE (1 << 24) +#define DSI0_TE (1 << 23) +#define GEN8_DE_PORT_HOTPLUG(hpd_pin) REG_BIT(3 + _HPD_PIN_DDI(hpd_pin)) +#define BXT_DE_PORT_HOTPLUG_MASK (GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) | \ + GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) | \ + GEN8_DE_PORT_HOTPLUG(HPD_PORT_C)) +#define BDW_DE_PORT_HOTPLUG_MASK GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) +#define BXT_DE_PORT_GMBUS (1 << 1) +#define GEN8_AUX_CHANNEL_A (1 << 0) +#define TGL_DE_PORT_AUX_USBC6 REG_BIT(13) +#define XELPD_DE_PORT_AUX_DDIE REG_BIT(13) +#define TGL_DE_PORT_AUX_USBC5 REG_BIT(12) +#define XELPD_DE_PORT_AUX_DDID REG_BIT(12) +#define TGL_DE_PORT_AUX_USBC4 REG_BIT(11) +#define TGL_DE_PORT_AUX_USBC3 REG_BIT(10) +#define TGL_DE_PORT_AUX_USBC2 REG_BIT(9) +#define TGL_DE_PORT_AUX_USBC1 REG_BIT(8) +#define TGL_DE_PORT_AUX_DDIC REG_BIT(2) +#define TGL_DE_PORT_AUX_DDIB REG_BIT(1) +#define TGL_DE_PORT_AUX_DDIA REG_BIT(0) + +#define GEN8_DE_PORT_IRQ_REGS I915_IRQ_REGS(GEN8_DE_PORT_IMR, \ + GEN8_DE_PORT_IER, \ + GEN8_DE_PORT_IIR) + +#define GEN8_DE_MISC_ISR _MMIO(0x44460) +#define GEN8_DE_MISC_IMR _MMIO(0x44464) +#define GEN8_DE_MISC_IIR _MMIO(0x44468) +#define GEN8_DE_MISC_IER _MMIO(0x4446c) +#define XELPDP_RM_TIMEOUT REG_BIT(29) +#define XELPDP_PMDEMAND_RSPTOUT_ERR REG_BIT(27) +#define GEN8_DE_MISC_GSE REG_BIT(27) +#define GEN8_DE_EDP_PSR REG_BIT(19) +#define XELPDP_PMDEMAND_RSP REG_BIT(3) +#define XE2LPD_DBUF_OVERLAP_DETECTED REG_BIT(1) + +#define GEN8_DE_MISC_IRQ_REGS I915_IRQ_REGS(GEN8_DE_MISC_IMR, \ + GEN8_DE_MISC_IER, \ + GEN8_DE_MISC_IIR) + +#define GEN11_DISPLAY_INT_CTL _MMIO(0x44200) +#define GEN11_DISPLAY_IRQ_ENABLE (1 << 31) +#define GEN11_AUDIO_CODEC_IRQ (1 << 24) +#define GEN11_DE_PCH_IRQ (1 << 23) +#define GEN11_DE_MISC_IRQ (1 << 22) +#define GEN11_DE_HPD_IRQ (1 << 21) +#define GEN11_DE_PORT_IRQ (1 << 20) +#define GEN11_DE_PIPE_C (1 << 18) +#define GEN11_DE_PIPE_B (1 << 17) +#define GEN11_DE_PIPE_A (1 << 16) + +#define GEN11_DE_HPD_ISR _MMIO(0x44470) +#define GEN11_DE_HPD_IMR _MMIO(0x44474) +#define GEN11_DE_HPD_IIR _MMIO(0x44478) +#define GEN11_DE_HPD_IER _MMIO(0x4447c) +#define GEN11_TC_HOTPLUG(hpd_pin) REG_BIT(16 + _HPD_PIN_TC(hpd_pin)) +#define GEN11_DE_TC_HOTPLUG_MASK (GEN11_TC_HOTPLUG(HPD_PORT_TC6) | \ + GEN11_TC_HOTPLUG(HPD_PORT_TC5) | \ + GEN11_TC_HOTPLUG(HPD_PORT_TC4) | \ + GEN11_TC_HOTPLUG(HPD_PORT_TC3) | \ + GEN11_TC_HOTPLUG(HPD_PORT_TC2) | \ + GEN11_TC_HOTPLUG(HPD_PORT_TC1)) +#define GEN11_TBT_HOTPLUG(hpd_pin) REG_BIT(_HPD_PIN_TC(hpd_pin)) +#define GEN11_DE_TBT_HOTPLUG_MASK (GEN11_TBT_HOTPLUG(HPD_PORT_TC6) | \ + GEN11_TBT_HOTPLUG(HPD_PORT_TC5) | \ + GEN11_TBT_HOTPLUG(HPD_PORT_TC4) | \ + GEN11_TBT_HOTPLUG(HPD_PORT_TC3) | \ + GEN11_TBT_HOTPLUG(HPD_PORT_TC2) | \ + GEN11_TBT_HOTPLUG(HPD_PORT_TC1)) + +#define GEN11_DE_HPD_IRQ_REGS I915_IRQ_REGS(GEN11_DE_HPD_IMR, \ + GEN11_DE_HPD_IER, \ + GEN11_DE_HPD_IIR) + +#define GEN11_TBT_HOTPLUG_CTL _MMIO(0x44030) +#define GEN11_TC_HOTPLUG_CTL _MMIO(0x44038) +#define GEN11_HOTPLUG_CTL_ENABLE(hpd_pin) (8 << (_HPD_PIN_TC(hpd_pin) * 4)) +#define GEN11_HOTPLUG_CTL_LONG_DETECT(hpd_pin) (2 << (_HPD_PIN_TC(hpd_pin) * 4)) +#define GEN11_HOTPLUG_CTL_SHORT_DETECT(hpd_pin) (1 << (_HPD_PIN_TC(hpd_pin) * 4)) +#define GEN11_HOTPLUG_CTL_NO_DETECT(hpd_pin) (0 << (_HPD_PIN_TC(hpd_pin) * 4)) + +#define PICAINTERRUPT_ISR _MMIO(0x16FE50) +#define PICAINTERRUPT_IMR _MMIO(0x16FE54) +#define PICAINTERRUPT_IIR _MMIO(0x16FE58) +#define PICAINTERRUPT_IER _MMIO(0x16FE5C) +#define XELPDP_DP_ALT_HOTPLUG(hpd_pin) REG_BIT(16 + _HPD_PIN_TC(hpd_pin)) +#define XELPDP_DP_ALT_HOTPLUG_MASK REG_GENMASK(19, 16) +#define XELPDP_AUX_TC(hpd_pin) REG_BIT(8 + _HPD_PIN_TC(hpd_pin)) +#define XELPDP_AUX_TC_MASK REG_GENMASK(11, 8) +#define XE2LPD_AUX_DDI(hpd_pin) REG_BIT(6 + _HPD_PIN_DDI(hpd_pin)) +#define XE2LPD_AUX_DDI_MASK REG_GENMASK(7, 6) +#define XELPDP_TBT_HOTPLUG(hpd_pin) REG_BIT(_HPD_PIN_TC(hpd_pin)) +#define XELPDP_TBT_HOTPLUG_MASK REG_GENMASK(3, 0) + +#define PICAINTERRUPT_IRQ_REGS I915_IRQ_REGS(PICAINTERRUPT_IMR, \ + PICAINTERRUPT_IER, \ + PICAINTERRUPT_IIR) + +#define XELPDP_PORT_HOTPLUG_CTL(hpd_pin) _MMIO(0x16F270 + (_HPD_PIN_TC(hpd_pin) * 0x200)) +#define XELPDP_TBT_HOTPLUG_ENABLE REG_BIT(6) +#define XELPDP_TBT_HPD_LONG_DETECT REG_BIT(5) +#define XELPDP_TBT_HPD_SHORT_DETECT REG_BIT(4) +#define XELPDP_DP_ALT_HOTPLUG_ENABLE REG_BIT(2) +#define XELPDP_DP_ALT_HPD_LONG_DETECT REG_BIT(1) +#define XELPDP_DP_ALT_HPD_SHORT_DETECT REG_BIT(0) + +#define XELPDP_INITIATE_PMDEMAND_REQUEST(dword) _MMIO(0x45230 + 4 * (dword)) +#define XELPDP_PMDEMAND_QCLK_GV_BW_MASK REG_GENMASK(31, 16) +#define XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK REG_GENMASK(14, 12) +#define XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK REG_GENMASK(11, 8) +#define XE3_PMDEMAND_PIPES_MASK REG_GENMASK(7, 4) +#define XELPDP_PMDEMAND_PIPES_MASK REG_GENMASK(7, 6) +#define XELPDP_PMDEMAND_DBUFS_MASK REG_GENMASK(5, 4) +#define XELPDP_PMDEMAND_PHYS_MASK REG_GENMASK(2, 0) + +#define XELPDP_PMDEMAND_REQ_ENABLE REG_BIT(31) +#define XELPDP_PMDEMAND_CDCLK_FREQ_MASK REG_GENMASK(30, 20) +#define XELPDP_PMDEMAND_DDICLK_FREQ_MASK REG_GENMASK(18, 8) +#define XELPDP_PMDEMAND_SCALERS_MASK REG_GENMASK(6, 4) +#define XELPDP_PMDEMAND_PLLS_MASK REG_GENMASK(2, 0) + +#define GEN12_DCPR_STATUS_1 _MMIO(0x46440) +#define XELPDP_PMDEMAND_INFLIGHT_STATUS REG_BIT(26) + +#define FUSE_STRAP _MMIO(0x42014) +#define ILK_INTERNAL_GRAPHICS_DISABLE REG_BIT(31) +#define ILK_INTERNAL_DISPLAY_DISABLE REG_BIT(30) +#define ILK_DISPLAY_DEBUG_DISABLE REG_BIT(29) +#define IVB_PIPE_C_DISABLE REG_BIT(28) +#define ILK_HDCP_DISABLE REG_BIT(25) +#define ILK_eDP_A_DISABLE REG_BIT(24) +#define HSW_CDCLK_LIMIT REG_BIT(24) +#define ILK_DESKTOP REG_BIT(23) +#define HSW_CPU_SSC_ENABLE REG_BIT(21) + +#define FUSE_STRAP3 _MMIO(0x42020) +#define HSW_REF_CLK_SELECT REG_BIT(1) + +#define CHICKEN_MISC_2 _MMIO(0x42084) +#define CHICKEN_MISC_DISABLE_DPT REG_BIT(30) /* adl,dg2 */ +#define BMG_DARB_HALF_BLK_END_BURST REG_BIT(27) +#define KBL_ARB_FILL_SPARE_14 REG_BIT(14) +#define KBL_ARB_FILL_SPARE_13 REG_BIT(13) +#define GLK_CL2_PWR_DOWN REG_BIT(12) +#define GLK_CL1_PWR_DOWN REG_BIT(11) +#define GLK_CL0_PWR_DOWN REG_BIT(10) + +#define CHICKEN_MISC_3 _MMIO(0x42088) +#define DP_MST_DPT_DPTP_ALIGN_WA(trans) REG_BIT(9 + (trans) - TRANSCODER_A) +#define DP_MST_SHORT_HBLANK_WA(trans) REG_BIT(5 + (trans) - TRANSCODER_A) +#define DP_MST_FEC_BS_JITTER_WA(trans) REG_BIT(0 + (trans) - TRANSCODER_A) + +#define CHICKEN_MISC_4 _MMIO(0x4208c) +#define CHICKEN_FBC_STRIDE_OVERRIDE REG_BIT(13) +#define CHICKEN_FBC_STRIDE_MASK REG_GENMASK(12, 0) +#define CHICKEN_FBC_STRIDE(x) REG_FIELD_PREP(CHICKEN_FBC_STRIDE_MASK, (x)) + +#define _CHICKEN_TRANS_A 0x420c0 +#define _CHICKEN_TRANS_B 0x420c4 +#define _CHICKEN_TRANS_C 0x420c8 +#define _CHICKEN_TRANS_EDP 0x420cc +#define _CHICKEN_TRANS_D 0x420d8 +#define _CHICKEN_TRANS(trans) _MMIO(_PICK((trans), \ + [TRANSCODER_EDP] = _CHICKEN_TRANS_EDP, \ + [TRANSCODER_A] = _CHICKEN_TRANS_A, \ + [TRANSCODER_B] = _CHICKEN_TRANS_B, \ + [TRANSCODER_C] = _CHICKEN_TRANS_C, \ + [TRANSCODER_D] = _CHICKEN_TRANS_D)) +#define _MTL_CHICKEN_TRANS_A 0x604e0 +#define _MTL_CHICKEN_TRANS_B 0x614e0 +#define _MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \ + _MTL_CHICKEN_TRANS_A, \ + _MTL_CHICKEN_TRANS_B) +#define CHICKEN_TRANS(display, trans) (DISPLAY_VER(display) >= 14 ? _MTL_CHICKEN_TRANS(trans) : _CHICKEN_TRANS(trans)) +#define PIPE_VBLANK_WITH_DELAY REG_BIT(31) /* tgl+ */ +#define SKL_UNMASK_VBL_TO_PIPE_IN_SRD REG_BIT(30) /* skl+ */ +#define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27) +#define HSW_FRAME_START_DELAY(x) REG_FIELD_PREP(HSW_FRAME_START_DELAY_MASK, x) +#define VSC_DATA_SEL_SOFTWARE_CONTROL REG_BIT(25) /* GLK */ +#define FECSTALL_DIS_DPTSTREAM_DPTTG REG_BIT(23) +#define DDI_TRAINING_OVERRIDE_ENABLE REG_BIT(19) +#define ADLP_1_BASED_X_GRANULARITY REG_BIT(18) +#define DDI_TRAINING_OVERRIDE_VALUE REG_BIT(18) +#define DDIE_TRAINING_OVERRIDE_ENABLE REG_BIT(17) /* CHICKEN_TRANS_A only */ +#define DDIE_TRAINING_OVERRIDE_VALUE REG_BIT(16) /* CHICKEN_TRANS_A only */ +#define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15) +#define DP_FEC_BS_JITTER_WA REG_BIT(15) +#define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) +#define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) +#define HDCP_LINE_REKEY_DISABLE REG_BIT(0) + +#define DISP_ARB_CTL2 _MMIO(0x45004) +#define DISP_DATA_PARTITION_5_6 REG_BIT(6) +#define DISP_IPC_ENABLE REG_BIT(3) + +#define GEN7_MSG_CTL _MMIO(0x45010) +#define WAIT_FOR_PCH_RESET_ACK (1 << 1) +#define WAIT_FOR_PCH_FLR_ACK (1 << 0) + +#define _BW_BUDDY0_CTL 0x45130 +#define _BW_BUDDY1_CTL 0x45140 +#define BW_BUDDY_CTL(x) _MMIO(_PICK_EVEN(x, \ + _BW_BUDDY0_CTL, \ + _BW_BUDDY1_CTL)) +#define BW_BUDDY_DISABLE REG_BIT(31) +#define BW_BUDDY_TLB_REQ_TIMER_MASK REG_GENMASK(21, 16) +#define BW_BUDDY_TLB_REQ_TIMER(x) REG_FIELD_PREP(BW_BUDDY_TLB_REQ_TIMER_MASK, x) + +#define _BW_BUDDY0_PAGE_MASK 0x45134 +#define _BW_BUDDY1_PAGE_MASK 0x45144 +#define BW_BUDDY_PAGE_MASK(x) _MMIO(_PICK_EVEN(x, \ + _BW_BUDDY0_PAGE_MASK, \ + _BW_BUDDY1_PAGE_MASK)) + +#define HSW_NDE_RSTWRN_OPT _MMIO(0x46408) +#define MTL_RESET_PICA_HANDSHAKE_EN REG_BIT(6) +#define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4) + +#define GEN11_CHICKEN_DCPR_2 _MMIO(0x46434) +#define DCPR_MASK_MAXLATENCY_MEMUP_CLR REG_BIT(27) +#define DCPR_MASK_LPMODE REG_BIT(26) +#define DCPR_SEND_RESP_IMM REG_BIT(25) +#define DCPR_CLEAR_MEMSTAT_DIS REG_BIT(24) + +#define XELPD_CHICKEN_DCPR_3 _MMIO(0x46438) +#define DMD_RSP_TIMEOUT_DISABLE REG_BIT(19) + +#define SKL_DFSM _MMIO(0x51000) +#define SKL_DFSM_DISPLAY_PM_DISABLE (1 << 27) +#define SKL_DFSM_DISPLAY_HDCP_DISABLE (1 << 25) +#define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23) +#define SKL_DFSM_CDCLK_LIMIT_675 (0 << 23) +#define SKL_DFSM_CDCLK_LIMIT_540 (1 << 23) +#define SKL_DFSM_CDCLK_LIMIT_450 (2 << 23) +#define SKL_DFSM_CDCLK_LIMIT_337_5 (3 << 23) +#define ICL_DFSM_DMC_DISABLE (1 << 23) +#define SKL_DFSM_PIPE_A_DISABLE (1 << 30) +#define SKL_DFSM_PIPE_B_DISABLE (1 << 21) +#define SKL_DFSM_PIPE_C_DISABLE (1 << 28) +#define TGL_DFSM_PIPE_D_DISABLE (1 << 22) +#define GLK_DFSM_DISPLAY_DSC_DISABLE (1 << 7) +#define XE2LPD_DFSM_DBUF_OVERLAP_DISABLE (1 << 3) + +#define XE2LPD_DE_CAP _MMIO(0x41100) +#define XE2LPD_DE_CAP_3DLUT_MASK REG_GENMASK(31, 30) +#define XE2LPD_DE_CAP_DSC_MASK REG_GENMASK(29, 28) +#define XE2LPD_DE_CAP_DSC_REMOVED 1 +#define XE2LPD_DE_CAP_SCALER_MASK REG_GENMASK(27, 26) +#define XE2LPD_DE_CAP_SCALER_SINGLE 1 + +#define SKL_DSSM _MMIO(0x51004) +#define ICL_DSSM_CDCLK_PLL_REFCLK_MASK (7 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_24MHz (0 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29) + +/*GEN11 chicken */ +#define _PIPEA_CHICKEN 0x70038 +#define _PIPEB_CHICKEN 0x71038 +#define _PIPEC_CHICKEN 0x72038 +#define PIPE_CHICKEN(pipe) _MMIO_PIPE(pipe, _PIPEA_CHICKEN,\ + _PIPEB_CHICKEN) +#define UNDERRUN_RECOVERY_DISABLE_ADLP REG_BIT(30) +#define UNDERRUN_RECOVERY_ENABLE_DG2 REG_BIT(30) +#define PIXEL_ROUNDING_TRUNC_FB_PASSTHRU REG_BIT(15) +#define DG2_RENDER_CCSTAG_4_3_EN REG_BIT(12) +#define PER_PIXEL_ALPHA_BYPASS_EN REG_BIT(7) + +#define PCH_DISPLAY_BASE 0xc0000u + +/* south display engine interrupt: IBX */ +#define SDE_AUDIO_POWER_D (1 << 27) +#define SDE_AUDIO_POWER_C (1 << 26) +#define SDE_AUDIO_POWER_B (1 << 25) +#define SDE_AUDIO_POWER_SHIFT (25) +#define SDE_AUDIO_POWER_MASK (7 << SDE_AUDIO_POWER_SHIFT) +#define SDE_GMBUS (1 << 24) +#define SDE_AUDIO_HDCP_TRANSB (1 << 23) +#define SDE_AUDIO_HDCP_TRANSA (1 << 22) +#define SDE_AUDIO_HDCP_MASK (3 << 22) +#define SDE_AUDIO_TRANSB (1 << 21) +#define SDE_AUDIO_TRANSA (1 << 20) +#define SDE_AUDIO_TRANS_MASK (3 << 20) +#define SDE_POISON (1 << 19) +/* 18 reserved */ +#define SDE_FDI_RXB (1 << 17) +#define SDE_FDI_RXA (1 << 16) +#define SDE_FDI_MASK (3 << 16) +#define SDE_AUXD (1 << 15) +#define SDE_AUXC (1 << 14) +#define SDE_AUXB (1 << 13) +#define SDE_AUX_MASK (7 << 13) +/* 12 reserved */ +#define SDE_CRT_HOTPLUG (1 << 11) +#define SDE_PORTD_HOTPLUG (1 << 10) +#define SDE_PORTC_HOTPLUG (1 << 9) +#define SDE_PORTB_HOTPLUG (1 << 8) +#define SDE_SDVOB_HOTPLUG (1 << 6) +#define SDE_HOTPLUG_MASK (SDE_CRT_HOTPLUG | \ + SDE_SDVOB_HOTPLUG | \ + SDE_PORTB_HOTPLUG | \ + SDE_PORTC_HOTPLUG | \ + SDE_PORTD_HOTPLUG) +#define SDE_TRANSB_CRC_DONE (1 << 5) +#define SDE_TRANSB_CRC_ERR (1 << 4) +#define SDE_TRANSB_FIFO_UNDER (1 << 3) +#define SDE_TRANSA_CRC_DONE (1 << 2) +#define SDE_TRANSA_CRC_ERR (1 << 1) +#define SDE_TRANSA_FIFO_UNDER (1 << 0) +#define SDE_TRANS_MASK (0x3f) + +/* south display engine interrupt: CPT - CNP */ +#define SDE_AUDIO_POWER_D_CPT (1 << 31) +#define SDE_AUDIO_POWER_C_CPT (1 << 30) +#define SDE_AUDIO_POWER_B_CPT (1 << 29) +#define SDE_AUDIO_POWER_SHIFT_CPT 29 +#define SDE_AUDIO_POWER_MASK_CPT (7 << 29) +#define SDE_AUXD_CPT (1 << 27) +#define SDE_AUXC_CPT (1 << 26) +#define SDE_AUXB_CPT (1 << 25) +#define SDE_AUX_MASK_CPT (7 << 25) +#define SDE_PORTE_HOTPLUG_SPT (1 << 25) +#define SDE_PORTA_HOTPLUG_SPT (1 << 24) +#define SDE_PORTD_HOTPLUG_CPT (1 << 23) +#define SDE_PORTC_HOTPLUG_CPT (1 << 22) +#define SDE_PORTB_HOTPLUG_CPT (1 << 21) +#define SDE_CRT_HOTPLUG_CPT (1 << 19) +#define SDE_SDVOB_HOTPLUG_CPT (1 << 18) +#define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \ + SDE_SDVOB_HOTPLUG_CPT | \ + SDE_PORTD_HOTPLUG_CPT | \ + SDE_PORTC_HOTPLUG_CPT | \ + SDE_PORTB_HOTPLUG_CPT) +#define SDE_HOTPLUG_MASK_SPT (SDE_PORTE_HOTPLUG_SPT | \ + SDE_PORTD_HOTPLUG_CPT | \ + SDE_PORTC_HOTPLUG_CPT | \ + SDE_PORTB_HOTPLUG_CPT | \ + SDE_PORTA_HOTPLUG_SPT) +#define SDE_GMBUS_CPT (1 << 17) +#define SDE_ERROR_CPT (1 << 16) +#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) +#define SDE_AUDIO_CP_CHG_C_CPT (1 << 9) +#define SDE_FDI_RXC_CPT (1 << 8) +#define SDE_AUDIO_CP_REQ_B_CPT (1 << 6) +#define SDE_AUDIO_CP_CHG_B_CPT (1 << 5) +#define SDE_FDI_RXB_CPT (1 << 4) +#define SDE_AUDIO_CP_REQ_A_CPT (1 << 2) +#define SDE_AUDIO_CP_CHG_A_CPT (1 << 1) +#define SDE_FDI_RXA_CPT (1 << 0) +#define SDE_AUDIO_CP_REQ_CPT (SDE_AUDIO_CP_REQ_C_CPT | \ + SDE_AUDIO_CP_REQ_B_CPT | \ + SDE_AUDIO_CP_REQ_A_CPT) +#define SDE_AUDIO_CP_CHG_CPT (SDE_AUDIO_CP_CHG_C_CPT | \ + SDE_AUDIO_CP_CHG_B_CPT | \ + SDE_AUDIO_CP_CHG_A_CPT) +#define SDE_FDI_MASK_CPT (SDE_FDI_RXC_CPT | \ + SDE_FDI_RXB_CPT | \ + SDE_FDI_RXA_CPT) + +/* south display engine interrupt: ICP/TGP/MTP */ +#define SDE_PICAINTERRUPT REG_BIT(31) +#define SDE_GMBUS_ICP (1 << 23) +#define SDE_TC_HOTPLUG_ICP(hpd_pin) REG_BIT(24 + _HPD_PIN_TC(hpd_pin)) +#define SDE_TC_HOTPLUG_DG2(hpd_pin) REG_BIT(25 + _HPD_PIN_TC(hpd_pin)) /* sigh */ +#define SDE_DDI_HOTPLUG_ICP(hpd_pin) REG_BIT(16 + _HPD_PIN_DDI(hpd_pin)) +#define SDE_DDI_HOTPLUG_MASK_ICP (SDE_DDI_HOTPLUG_ICP(HPD_PORT_D) | \ + SDE_DDI_HOTPLUG_ICP(HPD_PORT_C) | \ + SDE_DDI_HOTPLUG_ICP(HPD_PORT_B) | \ + SDE_DDI_HOTPLUG_ICP(HPD_PORT_A)) +#define SDE_TC_HOTPLUG_MASK_ICP (SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6) | \ + SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5) | \ + SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4) | \ + SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3) | \ + SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2) | \ + SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1)) + +#define SDE_IRQ_REGS I915_IRQ_REGS(SDEIMR, \ + SDEIER, \ + SDEIIR) + +#define SERR_INT _MMIO(0xc4040) +#define SERR_INT_POISON (1 << 31) +#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1 << ((pipe) * 3)) + +/* digital port hotplug */ +#define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */ +#define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */ +#define BXT_DDIA_HPD_INVERT (1 << 27) +#define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */ +#define PORTA_HOTPLUG_LONG_DETECT (2 << 24) /* SPT+ & BXT */ +#define PORTD_HOTPLUG_ENABLE (1 << 20) +#define PORTD_PULSE_DURATION_2ms (0 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_4_5ms (1 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_6ms (2 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_100ms (3 << 18) /* pre-LPT */ +#define PORTD_PULSE_DURATION_MASK (3 << 18) /* pre-LPT */ +#define PORTD_HOTPLUG_STATUS_MASK (3 << 16) +#define PORTD_HOTPLUG_NO_DETECT (0 << 16) +#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) +#define PORTD_HOTPLUG_LONG_DETECT (2 << 16) +#define PORTC_HOTPLUG_ENABLE (1 << 12) +#define BXT_DDIC_HPD_INVERT (1 << 11) +#define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_100ms (3 << 10) /* pre-LPT */ +#define PORTC_PULSE_DURATION_MASK (3 << 10) /* pre-LPT */ +#define PORTC_HOTPLUG_STATUS_MASK (3 << 8) +#define PORTC_HOTPLUG_NO_DETECT (0 << 8) +#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) +#define PORTC_HOTPLUG_LONG_DETECT (2 << 8) +#define PORTB_HOTPLUG_ENABLE (1 << 4) +#define BXT_DDIB_HPD_INVERT (1 << 3) +#define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_100ms (3 << 2) /* pre-LPT */ +#define PORTB_PULSE_DURATION_MASK (3 << 2) /* pre-LPT */ +#define PORTB_HOTPLUG_STATUS_MASK (3 << 0) +#define PORTB_HOTPLUG_NO_DETECT (0 << 0) +#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) +#define PORTB_HOTPLUG_LONG_DETECT (2 << 0) +#define BXT_DDI_HPD_INVERT_MASK (BXT_DDIA_HPD_INVERT | \ + BXT_DDIB_HPD_INVERT | \ + BXT_DDIC_HPD_INVERT) + +#define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */ +#define PORTE_HOTPLUG_ENABLE (1 << 4) +#define PORTE_HOTPLUG_STATUS_MASK (3 << 0) +#define PORTE_HOTPLUG_NO_DETECT (0 << 0) +#define PORTE_HOTPLUG_SHORT_DETECT (1 << 0) +#define PORTE_HOTPLUG_LONG_DETECT (2 << 0) + +/* This register is a reuse of PCH_PORT_HOTPLUG register. The + * functionality covered in PCH_PORT_HOTPLUG is split into + * SHOTPLUG_CTL_DDI and SHOTPLUG_CTL_TC. + */ +#define SHOTPLUG_CTL_DDI _MMIO(0xc4030) +#define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(hpd_pin) (0x4 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_STATUS_MASK(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_NO_DETECT(hpd_pin) (0x0 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_SHORT_DETECT(hpd_pin) (0x1 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(hpd_pin) (0x2 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_SHORT_LONG_DETECT(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4)) + +#define SHOTPLUG_CTL_TC _MMIO(0xc4034) +#define ICP_TC_HPD_ENABLE(hpd_pin) (8 << (_HPD_PIN_TC(hpd_pin) * 4)) +#define ICP_TC_HPD_LONG_DETECT(hpd_pin) (2 << (_HPD_PIN_TC(hpd_pin) * 4)) +#define ICP_TC_HPD_SHORT_DETECT(hpd_pin) (1 << (_HPD_PIN_TC(hpd_pin) * 4)) + +#define SHPD_FILTER_CNT _MMIO(0xc4038) +#define SHPD_FILTER_CNT_500_ADJ 0x001D9 +#define SHPD_FILTER_CNT_250 0x000F8 + +#define _PCH_DPLL_A 0xc6014 +#define _PCH_DPLL_B 0xc6018 +#define PCH_DPLL(pll) _MMIO((pll) == 0 ? _PCH_DPLL_A : _PCH_DPLL_B) + +#define _PCH_FPA0 0xc6040 +#define _PCH_FPB0 0xc6048 +#define PCH_FP0(pll) _MMIO((pll) == 0 ? _PCH_FPA0 : _PCH_FPB0) +#define FP_CB_TUNE (0x3 << 22) + +#define _PCH_FPA1 0xc6044 +#define _PCH_FPB1 0xc604c +#define PCH_FP1(pll) _MMIO((pll) == 0 ? _PCH_FPA1 : _PCH_FPB1) + +#define PCH_DPLL_TEST _MMIO(0xc606c) + +#define PCH_DREF_CONTROL _MMIO(0xC6200) +#define DREF_CONTROL_MASK 0x7fc3 +#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0 << 13) +#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2 << 13) +#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3 << 13) +#define DREF_CPU_SOURCE_OUTPUT_MASK (3 << 13) +#define DREF_SSC_SOURCE_DISABLE (0 << 11) +#define DREF_SSC_SOURCE_ENABLE (2 << 11) +#define DREF_SSC_SOURCE_MASK (3 << 11) +#define DREF_NONSPREAD_SOURCE_DISABLE (0 << 9) +#define DREF_NONSPREAD_CK505_ENABLE (1 << 9) +#define DREF_NONSPREAD_SOURCE_ENABLE (2 << 9) +#define DREF_NONSPREAD_SOURCE_MASK (3 << 9) +#define DREF_SUPERSPREAD_SOURCE_DISABLE (0 << 7) +#define DREF_SUPERSPREAD_SOURCE_ENABLE (2 << 7) +#define DREF_SUPERSPREAD_SOURCE_MASK (3 << 7) +#define DREF_SSC4_DOWNSPREAD (0 << 6) +#define DREF_SSC4_CENTERSPREAD (1 << 6) +#define DREF_SSC1_DISABLE (0 << 1) +#define DREF_SSC1_ENABLE (1 << 1) +#define DREF_SSC4_DISABLE (0) +#define DREF_SSC4_ENABLE (1) + +#define PCH_RAWCLK_FREQ _MMIO(0xc6204) +#define FDL_TP1_TIMER_SHIFT 12 +#define FDL_TP1_TIMER_MASK (3 << 12) +#define FDL_TP2_TIMER_SHIFT 10 +#define FDL_TP2_TIMER_MASK (3 << 10) +#define RAWCLK_FREQ_MASK 0x3ff +#define CNP_RAWCLK_DIV_MASK (0x3ff << 16) +#define CNP_RAWCLK_DIV(div) ((div) << 16) +#define CNP_RAWCLK_FRAC_MASK (0xf << 26) +#define CNP_RAWCLK_DEN(den) ((den) << 26) +#define ICP_RAWCLK_NUM(num) ((num) << 11) + +#define PCH_DPLL_TMR_CFG _MMIO(0xc6208) + +#define PCH_SSC4_PARMS _MMIO(0xc6210) +#define PCH_SSC4_AUX_PARMS _MMIO(0xc6214) + +#define PCH_DPLL_SEL _MMIO(0xc7000) +#define TRANS_DPLLB_SEL(pipe) (1 << ((pipe) * 4)) +#define TRANS_DPLLA_SEL(pipe) 0 +#define TRANS_DPLL_ENABLE(pipe) (1 << ((pipe) * 4 + 3)) + +/* transcoder */ +#define _PCH_TRANS_HTOTAL_A 0xe0000 +#define _PCH_TRANS_HTOTAL_B 0xe1000 +#define PCH_TRANS_HTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B) +#define TRANS_HTOTAL_SHIFT 16 +#define TRANS_HACTIVE_SHIFT 0 + +#define _PCH_TRANS_HBLANK_A 0xe0004 +#define _PCH_TRANS_HBLANK_B 0xe1004 +#define PCH_TRANS_HBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B) +#define TRANS_HBLANK_END_SHIFT 16 +#define TRANS_HBLANK_START_SHIFT 0 + +#define _PCH_TRANS_HSYNC_A 0xe0008 +#define _PCH_TRANS_HSYNC_B 0xe1008 +#define PCH_TRANS_HSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B) +#define TRANS_HSYNC_END_SHIFT 16 +#define TRANS_HSYNC_START_SHIFT 0 + +#define _PCH_TRANS_VTOTAL_A 0xe000c +#define _PCH_TRANS_VTOTAL_B 0xe100c +#define PCH_TRANS_VTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B) +#define TRANS_VTOTAL_SHIFT 16 +#define TRANS_VACTIVE_SHIFT 0 + +#define _PCH_TRANS_VBLANK_A 0xe0010 +#define _PCH_TRANS_VBLANK_B 0xe1010 +#define PCH_TRANS_VBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B) +#define TRANS_VBLANK_END_SHIFT 16 +#define TRANS_VBLANK_START_SHIFT 0 + +#define _PCH_TRANS_VSYNC_A 0xe0014 +#define _PCH_TRANS_VSYNC_B 0xe1014 +#define PCH_TRANS_VSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B) +#define TRANS_VSYNC_END_SHIFT 16 +#define TRANS_VSYNC_START_SHIFT 0 + +#define _PCH_TRANS_VSYNCSHIFT_A 0xe0028 +#define _PCH_TRANS_VSYNCSHIFT_B 0xe1028 +#define PCH_TRANS_VSYNCSHIFT(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, _PCH_TRANS_VSYNCSHIFT_B) + +#define _PCH_TRANSA_DATA_M1 0xe0030 +#define _PCH_TRANSB_DATA_M1 0xe1030 +#define PCH_TRANS_DATA_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1) + +#define _PCH_TRANSA_DATA_N1 0xe0034 +#define _PCH_TRANSB_DATA_N1 0xe1034 +#define PCH_TRANS_DATA_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1) + +#define _PCH_TRANSA_DATA_M2 0xe0038 +#define _PCH_TRANSB_DATA_M2 0xe1038 +#define PCH_TRANS_DATA_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2) + +#define _PCH_TRANSA_DATA_N2 0xe003c +#define _PCH_TRANSB_DATA_N2 0xe103c +#define PCH_TRANS_DATA_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2) + +#define _PCH_TRANSA_LINK_M1 0xe0040 +#define _PCH_TRANSB_LINK_M1 0xe1040 +#define PCH_TRANS_LINK_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1) + +#define _PCH_TRANSA_LINK_N1 0xe0044 +#define _PCH_TRANSB_LINK_N1 0xe1044 +#define PCH_TRANS_LINK_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1) + +#define _PCH_TRANSA_LINK_M2 0xe0048 +#define _PCH_TRANSB_LINK_M2 0xe1048 +#define PCH_TRANS_LINK_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2) + +#define _PCH_TRANSA_LINK_N2 0xe004c +#define _PCH_TRANSB_LINK_N2 0xe104c +#define PCH_TRANS_LINK_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2) + +/* Per-transcoder DIP controls (PCH) */ +#define _VIDEO_DIP_CTL_A 0xe0200 +#define _VIDEO_DIP_CTL_B 0xe1200 +#define TVIDEO_DIP_CTL(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B) + +#define _VIDEO_DIP_DATA_A 0xe0208 +#define _VIDEO_DIP_DATA_B 0xe1208 +#define TVIDEO_DIP_DATA(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B) + +#define _VIDEO_DIP_GCP_A 0xe0210 +#define _VIDEO_DIP_GCP_B 0xe1210 +#define TVIDEO_DIP_GCP(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B) +#define GCP_COLOR_INDICATION (1 << 2) +#define GCP_DEFAULT_PHASE_ENABLE (1 << 1) +#define GCP_AV_MUTE (1 << 0) + +/* Per-transcoder DIP controls (VLV) */ +#define _VLV_VIDEO_DIP_CTL_A 0x60200 +#define _VLV_VIDEO_DIP_CTL_B 0x61170 +#define _CHV_VIDEO_DIP_CTL_C 0x611f0 +#define VLV_TVIDEO_DIP_CTL(pipe) _MMIO_BASE_PIPE3(VLV_DISPLAY_BASE, (pipe), \ + _VLV_VIDEO_DIP_CTL_A, \ + _VLV_VIDEO_DIP_CTL_B, \ + _CHV_VIDEO_DIP_CTL_C) + +#define _VLV_VIDEO_DIP_DATA_A 0x60208 +#define _VLV_VIDEO_DIP_DATA_B 0x61174 +#define _CHV_VIDEO_DIP_DATA_C 0x611f4 +#define VLV_TVIDEO_DIP_DATA(pipe) _MMIO_BASE_PIPE3(VLV_DISPLAY_BASE, (pipe), \ + _VLV_VIDEO_DIP_DATA_A, \ + _VLV_VIDEO_DIP_DATA_B, \ + _CHV_VIDEO_DIP_DATA_C) + +#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_A 0x60210 +#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_B 0x61178 +#define _CHV_VIDEO_DIP_GDCP_PAYLOAD_C 0x611f8 +#define VLV_TVIDEO_DIP_GCP(pipe) _MMIO_BASE_PIPE3(VLV_DISPLAY_BASE, (pipe), \ + _VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \ + _VLV_VIDEO_DIP_GDCP_PAYLOAD_B, \ + _CHV_VIDEO_DIP_GDCP_PAYLOAD_C) + +/* Haswell DIP controls */ +#define _HSW_VIDEO_DIP_CTL_A 0x60200 +#define _HSW_VIDEO_DIP_CTL_B 0x61200 +#define HSW_TVIDEO_DIP_CTL(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_CTL_A) + +#define _HSW_VIDEO_DIP_AVI_DATA_A 0x60220 +#define _HSW_VIDEO_DIP_AVI_DATA_B 0x61220 +#define HSW_TVIDEO_DIP_AVI_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_AVI_DATA_A + (i) * 4) + +#define _HSW_VIDEO_DIP_VS_DATA_A 0x60260 +#define _HSW_VIDEO_DIP_VS_DATA_B 0x61260 +#define HSW_TVIDEO_DIP_VS_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VS_DATA_A + (i) * 4) + +#define _HSW_VIDEO_DIP_SPD_DATA_A 0x602A0 +#define _HSW_VIDEO_DIP_SPD_DATA_B 0x612A0 +#define HSW_TVIDEO_DIP_SPD_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_SPD_DATA_A + (i) * 4) + +#define _HSW_VIDEO_DIP_GMP_DATA_A 0x602E0 +#define _HSW_VIDEO_DIP_GMP_DATA_B 0x612E0 +#define HSW_TVIDEO_DIP_GMP_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GMP_DATA_A + (i) * 4) + +#define _HSW_VIDEO_DIP_VSC_DATA_A 0x60320 +#define _HSW_VIDEO_DIP_VSC_DATA_B 0x61320 +#define HSW_TVIDEO_DIP_VSC_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VSC_DATA_A + (i) * 4) + +/*ADLP and later: */ +#define _ADL_VIDEO_DIP_AS_DATA_A 0x60484 +#define _ADL_VIDEO_DIP_AS_DATA_B 0x61484 +#define ADL_TVIDEO_DIP_AS_SDP_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans,\ + _ADL_VIDEO_DIP_AS_DATA_A + (i) * 4) + +#define _GLK_VIDEO_DIP_DRM_DATA_A 0x60440 +#define _GLK_VIDEO_DIP_DRM_DATA_B 0x61440 +#define GLK_TVIDEO_DIP_DRM_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _GLK_VIDEO_DIP_DRM_DATA_A + (i) * 4) + +#define _HSW_VIDEO_DIP_AVI_ECC_A 0x60240 +#define _HSW_VIDEO_DIP_BVI_ECC_B 0x61240 +#define _HSW_VIDEO_DIP_VS_ECC_A 0x60280 +#define _HSW_VIDEO_DIP_VS_ECC_B 0x61280 +#define _HSW_VIDEO_DIP_SPD_ECC_A 0x602C0 +#define _HSW_VIDEO_DIP_SPD_ECC_B 0x612C0 +#define _HSW_VIDEO_DIP_GMP_ECC_A 0x60300 +#define _HSW_VIDEO_DIP_GMP_ECC_B 0x61300 +#define _HSW_VIDEO_DIP_VSC_ECC_A 0x60344 +#define _HSW_VIDEO_DIP_VSC_ECC_B 0x61344 + +#define _HSW_VIDEO_DIP_GCP_A 0x60210 +#define _HSW_VIDEO_DIP_GCP_B 0x61210 +#define HSW_TVIDEO_DIP_GCP(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GCP_A) + +#define _ICL_VIDEO_DIP_PPS_DATA_A 0x60350 +#define _ICL_VIDEO_DIP_PPS_DATA_B 0x61350 +#define ICL_VIDEO_DIP_PPS_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_DATA_A + (i) * 4) + +#define _ICL_VIDEO_DIP_PPS_ECC_A 0x603D4 +#define _ICL_VIDEO_DIP_PPS_ECC_B 0x613D4 +#define ICL_VIDEO_DIP_PPS_ECC(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_ECC_A + (i) * 4) + +#define _HSW_STEREO_3D_CTL_A 0x70020 +#define _HSW_STEREO_3D_CTL_B 0x71020 +#define HSW_STEREO_3D_CTL(dev_priv, trans) _MMIO_PIPE2(dev_priv, trans, _HSW_STEREO_3D_CTL_A) +#define S3D_ENABLE (1 << 31) + +#define _PCH_TRANSACONF 0xf0008 +#define _PCH_TRANSBCONF 0xf1008 +#define PCH_TRANSCONF(pipe) _MMIO_PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF) +#define LPT_TRANSCONF PCH_TRANSCONF(PIPE_A) /* lpt has only one transcoder */ +#define TRANS_ENABLE REG_BIT(31) +#define TRANS_STATE_ENABLE REG_BIT(30) +#define TRANS_FRAME_START_DELAY_MASK REG_GENMASK(28, 27) /* ibx */ +#define TRANS_FRAME_START_DELAY(x) REG_FIELD_PREP(TRANS_FRAME_START_DELAY_MASK, (x)) /* ibx: 0-3 */ +#define TRANS_INTERLACE_MASK REG_GENMASK(23, 21) +#define TRANS_INTERLACE_PROGRESSIVE REG_FIELD_PREP(TRANS_INTERLACE_MASK, 0) +#define TRANS_INTERLACE_LEGACY_VSYNC_IBX REG_FIELD_PREP(TRANS_INTERLACE_MASK, 2) /* ibx */ +#define TRANS_INTERLACE_INTERLACED REG_FIELD_PREP(TRANS_INTERLACE_MASK, 3) +#define TRANS_BPC_MASK REG_GENMASK(7, 5) /* ibx */ +#define TRANS_BPC_8 REG_FIELD_PREP(TRANS_BPC_MASK, 0) +#define TRANS_BPC_10 REG_FIELD_PREP(TRANS_BPC_MASK, 1) +#define TRANS_BPC_6 REG_FIELD_PREP(TRANS_BPC_MASK, 2) +#define TRANS_BPC_12 REG_FIELD_PREP(TRANS_BPC_MASK, 3) + +#define PCH_DP_B _MMIO(0xe4100) +#define PCH_DP_C _MMIO(0xe4200) +#define PCH_DP_D _MMIO(0xe4300) + +/* CPT */ +#define _TRANS_DP_CTL_A 0xe0300 +#define _TRANS_DP_CTL_B 0xe1300 +#define _TRANS_DP_CTL_C 0xe2300 +#define TRANS_DP_CTL(pipe) _MMIO_PIPE(pipe, _TRANS_DP_CTL_A, _TRANS_DP_CTL_B) +#define TRANS_DP_OUTPUT_ENABLE REG_BIT(31) +#define TRANS_DP_PORT_SEL_MASK REG_GENMASK(30, 29) +#define TRANS_DP_PORT_SEL_NONE REG_FIELD_PREP(TRANS_DP_PORT_SEL_MASK, 3) +#define TRANS_DP_PORT_SEL(port) REG_FIELD_PREP(TRANS_DP_PORT_SEL_MASK, (port) - PORT_B) +#define TRANS_DP_AUDIO_ONLY REG_BIT(26) +#define TRANS_DP_ENH_FRAMING REG_BIT(18) +#define TRANS_DP_BPC_MASK REG_GENMASK(10, 9) +#define TRANS_DP_BPC_8 REG_FIELD_PREP(TRANS_DP_BPC_MASK, 0) +#define TRANS_DP_BPC_10 REG_FIELD_PREP(TRANS_DP_BPC_MASK, 1) +#define TRANS_DP_BPC_6 REG_FIELD_PREP(TRANS_DP_BPC_MASK, 2) +#define TRANS_DP_BPC_12 REG_FIELD_PREP(TRANS_DP_BPC_MASK, 3) +#define TRANS_DP_VSYNC_ACTIVE_HIGH REG_BIT(4) +#define TRANS_DP_HSYNC_ACTIVE_HIGH REG_BIT(3) + +#define _TRANS_DP2_CTL_A 0x600a0 +#define _TRANS_DP2_CTL_B 0x610a0 +#define _TRANS_DP2_CTL_C 0x620a0 +#define _TRANS_DP2_CTL_D 0x630a0 +#define TRANS_DP2_CTL(trans) _MMIO_TRANS(trans, _TRANS_DP2_CTL_A, _TRANS_DP2_CTL_B) +#define TRANS_DP2_128B132B_CHANNEL_CODING REG_BIT(31) +#define TRANS_DP2_PANEL_REPLAY_ENABLE REG_BIT(30) +#define TRANS_DP2_DEBUG_ENABLE REG_BIT(23) + +#define _TRANS_DP2_VFREQHIGH_A 0x600a4 +#define _TRANS_DP2_VFREQHIGH_B 0x610a4 +#define _TRANS_DP2_VFREQHIGH_C 0x620a4 +#define _TRANS_DP2_VFREQHIGH_D 0x630a4 +#define TRANS_DP2_VFREQHIGH(trans) _MMIO_TRANS(trans, _TRANS_DP2_VFREQHIGH_A, _TRANS_DP2_VFREQHIGH_B) +#define TRANS_DP2_VFREQ_PIXEL_CLOCK_MASK REG_GENMASK(31, 8) +#define TRANS_DP2_VFREQ_PIXEL_CLOCK(clk_hz) REG_FIELD_PREP(TRANS_DP2_VFREQ_PIXEL_CLOCK_MASK, (clk_hz)) + +#define _TRANS_DP2_VFREQLOW_A 0x600a8 +#define _TRANS_DP2_VFREQLOW_B 0x610a8 +#define _TRANS_DP2_VFREQLOW_C 0x620a8 +#define _TRANS_DP2_VFREQLOW_D 0x630a8 +#define TRANS_DP2_VFREQLOW(trans) _MMIO_TRANS(trans, _TRANS_DP2_VFREQLOW_A, _TRANS_DP2_VFREQLOW_B) + +#define _DP_MIN_HBLANK_CTL_A 0x600ac +#define _DP_MIN_HBLANK_CTL_B 0x610ac +#define DP_MIN_HBLANK_CTL(trans) _MMIO_TRANS(trans, _DP_MIN_HBLANK_CTL_A, _DP_MIN_HBLANK_CTL_B) + +/* SNB eDP training params */ +/* SNB A-stepping */ +#define EDP_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) +#define EDP_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) +#define EDP_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) +#define EDP_LINK_TRAIN_800MV_0DB_SNB_A (0x0 << 22) +/* SNB B-stepping */ +#define EDP_LINK_TRAIN_400_600MV_0DB_SNB_B (0x0 << 22) +#define EDP_LINK_TRAIN_400MV_3_5DB_SNB_B (0x1 << 22) +#define EDP_LINK_TRAIN_400_600MV_6DB_SNB_B (0x3a << 22) +#define EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B (0x39 << 22) +#define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38 << 22) +#define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f << 22) + +/* IVB */ +#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 << 22) +#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a << 22) +#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f << 22) +#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 << 22) +#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 << 22) +#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 << 22) +#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x3e << 22) + +/* legacy values */ +#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 << 22) +#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 << 22) +#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 << 22) +#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 << 22) +#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 << 22) + +#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f << 22) + +#define VLV_CHICKEN_3 _MMIO(VLV_DISPLAY_BASE + 0x7040C) +#define PIXEL_OVERLAP_CNT_MASK (3 << 30) +#define PIXEL_OVERLAP_CNT_SHIFT 30 + +/* + * HSW - ICL power wells + * + * Platforms have up to 3 power well control register sets, each set + * controlling up to 16 power wells via a request/status HW flag tuple: + * - main (HSW_PWR_WELL_CTL[1-4]) + * - AUX (ICL_PWR_WELL_CTL_AUX[1-4]) + * - DDI (ICL_PWR_WELL_CTL_DDI[1-4]) + * Each control register set consists of up to 4 registers used by different + * sources that can request a power well to be enabled: + * - BIOS (HSW_PWR_WELL_CTL1/ICL_PWR_WELL_CTL_AUX1/ICL_PWR_WELL_CTL_DDI1) + * - DRIVER (HSW_PWR_WELL_CTL2/ICL_PWR_WELL_CTL_AUX2/ICL_PWR_WELL_CTL_DDI2) + * - KVMR (HSW_PWR_WELL_CTL3) (only in the main register set) + * - DEBUG (HSW_PWR_WELL_CTL4/ICL_PWR_WELL_CTL_AUX4/ICL_PWR_WELL_CTL_DDI4) + */ +#define HSW_PWR_WELL_CTL1 _MMIO(0x45400) +#define HSW_PWR_WELL_CTL2 _MMIO(0x45404) +#define HSW_PWR_WELL_CTL3 _MMIO(0x45408) +#define HSW_PWR_WELL_CTL4 _MMIO(0x4540C) +#define HSW_PWR_WELL_CTL_REQ(pw_idx) (0x2 << ((pw_idx) * 2)) +#define HSW_PWR_WELL_CTL_STATE(pw_idx) (0x1 << ((pw_idx) * 2)) + +/* HSW/BDW power well */ +#define HSW_PW_CTL_IDX_GLOBAL 15 + +/* SKL/BXT/GLK power wells */ +#define SKL_PW_CTL_IDX_PW_2 15 +#define SKL_PW_CTL_IDX_PW_1 14 +#define GLK_PW_CTL_IDX_AUX_C 10 +#define GLK_PW_CTL_IDX_AUX_B 9 +#define GLK_PW_CTL_IDX_AUX_A 8 +#define SKL_PW_CTL_IDX_DDI_D 4 +#define SKL_PW_CTL_IDX_DDI_C 3 +#define SKL_PW_CTL_IDX_DDI_B 2 +#define SKL_PW_CTL_IDX_DDI_A_E 1 +#define GLK_PW_CTL_IDX_DDI_A 1 +#define SKL_PW_CTL_IDX_MISC_IO 0 + +/* ICL/TGL - power wells */ +#define TGL_PW_CTL_IDX_PW_5 4 +#define ICL_PW_CTL_IDX_PW_4 3 +#define ICL_PW_CTL_IDX_PW_3 2 +#define ICL_PW_CTL_IDX_PW_2 1 +#define ICL_PW_CTL_IDX_PW_1 0 + +/* XE_LPD - power wells */ +#define XELPD_PW_CTL_IDX_PW_D 8 +#define XELPD_PW_CTL_IDX_PW_C 7 +#define XELPD_PW_CTL_IDX_PW_B 6 +#define XELPD_PW_CTL_IDX_PW_A 5 + +#define ICL_PWR_WELL_CTL_AUX1 _MMIO(0x45440) +#define ICL_PWR_WELL_CTL_AUX2 _MMIO(0x45444) +#define ICL_PWR_WELL_CTL_AUX4 _MMIO(0x4544C) +#define TGL_PW_CTL_IDX_AUX_TBT6 14 +#define TGL_PW_CTL_IDX_AUX_TBT5 13 +#define TGL_PW_CTL_IDX_AUX_TBT4 12 +#define ICL_PW_CTL_IDX_AUX_TBT4 11 +#define TGL_PW_CTL_IDX_AUX_TBT3 11 +#define ICL_PW_CTL_IDX_AUX_TBT3 10 +#define TGL_PW_CTL_IDX_AUX_TBT2 10 +#define ICL_PW_CTL_IDX_AUX_TBT2 9 +#define TGL_PW_CTL_IDX_AUX_TBT1 9 +#define ICL_PW_CTL_IDX_AUX_TBT1 8 +#define TGL_PW_CTL_IDX_AUX_TC6 8 +#define XELPD_PW_CTL_IDX_AUX_E 8 +#define TGL_PW_CTL_IDX_AUX_TC5 7 +#define XELPD_PW_CTL_IDX_AUX_D 7 +#define TGL_PW_CTL_IDX_AUX_TC4 6 +#define ICL_PW_CTL_IDX_AUX_F 5 +#define TGL_PW_CTL_IDX_AUX_TC3 5 +#define ICL_PW_CTL_IDX_AUX_E 4 +#define TGL_PW_CTL_IDX_AUX_TC2 4 +#define ICL_PW_CTL_IDX_AUX_D 3 +#define TGL_PW_CTL_IDX_AUX_TC1 3 +#define ICL_PW_CTL_IDX_AUX_C 2 +#define ICL_PW_CTL_IDX_AUX_B 1 +#define ICL_PW_CTL_IDX_AUX_A 0 + +#define ICL_PWR_WELL_CTL_DDI1 _MMIO(0x45450) +#define ICL_PWR_WELL_CTL_DDI2 _MMIO(0x45454) +#define ICL_PWR_WELL_CTL_DDI4 _MMIO(0x4545C) +#define XELPD_PW_CTL_IDX_DDI_E 8 +#define TGL_PW_CTL_IDX_DDI_TC6 8 +#define XELPD_PW_CTL_IDX_DDI_D 7 +#define TGL_PW_CTL_IDX_DDI_TC5 7 +#define TGL_PW_CTL_IDX_DDI_TC4 6 +#define ICL_PW_CTL_IDX_DDI_F 5 +#define TGL_PW_CTL_IDX_DDI_TC3 5 +#define ICL_PW_CTL_IDX_DDI_E 4 +#define TGL_PW_CTL_IDX_DDI_TC2 4 +#define ICL_PW_CTL_IDX_DDI_D 3 +#define TGL_PW_CTL_IDX_DDI_TC1 3 +#define ICL_PW_CTL_IDX_DDI_C 2 +#define ICL_PW_CTL_IDX_DDI_B 1 +#define ICL_PW_CTL_IDX_DDI_A 0 + +/* HSW - power well misc debug registers */ +#define HSW_PWR_WELL_CTL5 _MMIO(0x45410) +#define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1 << 31) +#define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1 << 20) +#define HSW_PWR_WELL_FORCE_ON (1 << 19) +#define HSW_PWR_WELL_CTL6 _MMIO(0x45414) + +#define SKL_FUSE_STATUS _MMIO(0x42000) +#define SKL_FUSE_DOWNLOAD_STATUS (1 << 31) +/* + * PG0 is HW controlled, so doesn't have a corresponding power well control knob + * SKL_DISP_PW1_IDX..SKL_DISP_PW2_IDX -> PG1..PG2 + */ +#define SKL_PW_CTL_IDX_TO_PG(pw_idx) \ + ((pw_idx) - SKL_PW_CTL_IDX_PW_1 + SKL_PG1) +/* + * PG0 is HW controlled, so doesn't have a corresponding power well control knob + * ICL_DISP_PW1_IDX..ICL_DISP_PW4_IDX -> PG1..PG4 + */ +#define ICL_PW_CTL_IDX_TO_PG(pw_idx) \ + ((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1) +#define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - (pg))) + +/* Per-pipe DDI Function Control */ +#define _TRANS_DDI_FUNC_CTL_A 0x60400 +#define _TRANS_DDI_FUNC_CTL_B 0x61400 +#define _TRANS_DDI_FUNC_CTL_C 0x62400 +#define _TRANS_DDI_FUNC_CTL_D 0x63400 +#define _TRANS_DDI_FUNC_CTL_EDP 0x6F400 +#define _TRANS_DDI_FUNC_CTL_DSI0 0x6b400 +#define _TRANS_DDI_FUNC_CTL_DSI1 0x6bc00 +#define TRANS_DDI_FUNC_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL_A) + +#define TRANS_DDI_FUNC_ENABLE (1 << 31) +/* Those bits are ignored by pipe EDP since it can only connect to DDI A */ +#define TRANS_DDI_PORT_SHIFT 28 +#define TGL_TRANS_DDI_PORT_SHIFT 27 +#define TRANS_DDI_PORT_MASK (7 << TRANS_DDI_PORT_SHIFT) +#define TGL_TRANS_DDI_PORT_MASK (0xf << TGL_TRANS_DDI_PORT_SHIFT) +#define TRANS_DDI_SELECT_PORT(x) ((x) << TRANS_DDI_PORT_SHIFT) +#define TGL_TRANS_DDI_SELECT_PORT(x) (((x) + 1) << TGL_TRANS_DDI_PORT_SHIFT) +#define TRANS_DDI_MODE_SELECT_MASK (7 << 24) +#define TRANS_DDI_MODE_SELECT_HDMI (0 << 24) +#define TRANS_DDI_MODE_SELECT_DVI (1 << 24) +#define TRANS_DDI_MODE_SELECT_DP_SST (2 << 24) +#define TRANS_DDI_MODE_SELECT_DP_MST (3 << 24) +#define TRANS_DDI_MODE_SELECT_FDI_OR_128B132B (4 << 24) +#define TRANS_DDI_BPC_MASK (7 << 20) +#define TRANS_DDI_BPC_8 (0 << 20) +#define TRANS_DDI_BPC_10 (1 << 20) +#define TRANS_DDI_BPC_6 (2 << 20) +#define TRANS_DDI_BPC_12 (3 << 20) +#define TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK REG_GENMASK(19, 18) +#define TRANS_DDI_PORT_SYNC_MASTER_SELECT(x) REG_FIELD_PREP(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, (x)) +#define TRANS_DDI_PVSYNC (1 << 17) +#define TRANS_DDI_PHSYNC (1 << 16) +#define TRANS_DDI_PORT_SYNC_ENABLE REG_BIT(15) +#define XE3_TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(15) +#define TRANS_DDI_EDP_INPUT_MASK (7 << 12) +#define TRANS_DDI_EDP_INPUT_A_ON (0 << 12) +#define TRANS_DDI_EDP_INPUT_A_ONOFF (4 << 12) +#define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) +#define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) +#define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) +#define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) +#define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ + REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) +#define TRANS_DDI_HDCP_SIGNALLING (1 << 9) +#define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1 << 8) +#define TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE (1 << 7) +#define TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ (1 << 6) +#define TRANS_DDI_HDCP_SELECT REG_BIT(5) +#define TRANS_DDI_BFI_ENABLE (1 << 4) +#define TRANS_DDI_HIGH_TMDS_CHAR_RATE (1 << 4) +#define TRANS_DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1) +#define TRANS_DDI_PORT_WIDTH(width) REG_FIELD_PREP(TRANS_DDI_PORT_WIDTH_MASK, (width) - 1) +#define TRANS_DDI_HDMI_SCRAMBLING (1 << 0) +#define TRANS_DDI_HDMI_SCRAMBLING_MASK (TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE \ + | TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ \ + | TRANS_DDI_HDMI_SCRAMBLING) + +#define _TRANS_DDI_FUNC_CTL2_A 0x60404 +#define _TRANS_DDI_FUNC_CTL2_B 0x61404 +#define _TRANS_DDI_FUNC_CTL2_C 0x62404 +#define _TRANS_DDI_FUNC_CTL2_EDP 0x6f404 +#define _TRANS_DDI_FUNC_CTL2_DSI0 0x6b404 +#define _TRANS_DDI_FUNC_CTL2_DSI1 0x6bc04 +#define TRANS_DDI_FUNC_CTL2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL2_A) +#define PORT_SYNC_MODE_ENABLE REG_BIT(4) +#define CMTG_SECONDARY_MODE REG_BIT(3) +#define PORT_SYNC_MODE_MASTER_SELECT_MASK REG_GENMASK(2, 0) +#define PORT_SYNC_MODE_MASTER_SELECT(x) REG_FIELD_PREP(PORT_SYNC_MODE_MASTER_SELECT_MASK, (x)) + +#define TRANS_CMTG_CHICKEN _MMIO(0x6fa90) +#define DISABLE_DPT_CLK_GATING REG_BIT(1) + +/* DisplayPort Transport Control */ +#define _DP_TP_CTL_A 0x64040 +#define _DP_TP_CTL_B 0x64140 +#define _TGL_DP_TP_CTL_A 0x60540 +#define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B) +#define TGL_DP_TP_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_CTL_A) +#define DP_TP_CTL_ENABLE REG_BIT(31) +#define DP_TP_CTL_FEC_ENABLE REG_BIT(30) +#define DP_TP_CTL_MODE_MASK REG_BIT(27) +#define DP_TP_CTL_MODE_SST REG_FIELD_PREP(DP_TP_CTL_MODE_MASK, 0) +#define DP_TP_CTL_MODE_MST REG_FIELD_PREP(DP_TP_CTL_MODE_MASK, 1) +#define DP_TP_CTL_FORCE_ACT REG_BIT(25) +#define DP_TP_CTL_TRAIN_PAT4_SEL_MASK REG_GENMASK(20, 19) +#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4A REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 0) +#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4B REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 1) +#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4C REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 2) +#define DP_TP_CTL_ENHANCED_FRAME_ENABLE REG_BIT(18) +#define DP_TP_CTL_FDI_AUTOTRAIN REG_BIT(15) +#define DP_TP_CTL_LINK_TRAIN_MASK REG_GENMASK(10, 8) +#define DP_TP_CTL_LINK_TRAIN_PAT1 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 0) +#define DP_TP_CTL_LINK_TRAIN_PAT2 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 1) +#define DP_TP_CTL_LINK_TRAIN_PAT3 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 4) +#define DP_TP_CTL_LINK_TRAIN_PAT4 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 5) +#define DP_TP_CTL_LINK_TRAIN_IDLE REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 2) +#define DP_TP_CTL_LINK_TRAIN_NORMAL REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 3) +#define DP_TP_CTL_SCRAMBLE_DISABLE REG_BIT(7) + +/* DisplayPort Transport Status */ +#define _DP_TP_STATUS_A 0x64044 +#define _DP_TP_STATUS_B 0x64144 +#define _TGL_DP_TP_STATUS_A 0x60544 +#define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B) +#define TGL_DP_TP_STATUS(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_STATUS_A) +#define DP_TP_STATUS_FEC_ENABLE_LIVE REG_BIT(28) +#define DP_TP_STATUS_IDLE_DONE REG_BIT(25) +#define DP_TP_STATUS_ACT_SENT REG_BIT(24) +#define DP_TP_STATUS_MODE_STATUS_MST REG_BIT(23) +#define DP_TP_STATUS_STREAMS_ENABLED_MASK REG_GENMASK(18, 16) /* 17:16 on hsw but bit 18 mbz */ +#define DP_TP_STATUS_AUTOTRAIN_DONE REG_BIT(12) +#define DP_TP_STATUS_PAYLOAD_MAPPING_VC2_MASK REG_GENMASK(9, 8) +#define DP_TP_STATUS_PAYLOAD_MAPPING_VC1_MASK REG_GENMASK(5, 4) +#define DP_TP_STATUS_PAYLOAD_MAPPING_VC0_MASK REG_GENMASK(1, 0) + +/* DDI Buffer Control */ +#define _DDI_BUF_CTL_A 0x64000 +#define _DDI_BUF_CTL_B 0x64100 +/* Known as DDI_CTL_DE in MTL+ */ +#define DDI_BUF_CTL(port) _MMIO_PORT(port, _DDI_BUF_CTL_A, _DDI_BUF_CTL_B) +#define DDI_BUF_CTL_ENABLE REG_BIT(31) +#define XE2LPD_DDI_BUF_D2D_LINK_ENABLE REG_BIT(29) +#define XE2LPD_DDI_BUF_D2D_LINK_STATE REG_BIT(28) +#define DDI_BUF_EMP_MASK REG_GENMASK(27, 24) +#define DDI_BUF_TRANS_SELECT(n) REG_FIELD_PREP(DDI_BUF_EMP_MASK, (n)) +#define DDI_BUF_PHY_LINK_RATE_MASK REG_GENMASK(23, 20) +#define DDI_BUF_PHY_LINK_RATE(r) REG_FIELD_PREP(DDI_BUF_PHY_LINK_RATE_MASK, (r)) +#define DDI_BUF_PORT_DATA_MASK REG_GENMASK(19, 18) +#define DDI_BUF_PORT_DATA_10BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 0) +#define DDI_BUF_PORT_DATA_20BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 1) +#define DDI_BUF_PORT_DATA_40BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 2) +#define DDI_BUF_PORT_REVERSAL REG_BIT(16) +#define DDI_BUF_LANE_STAGGER_DELAY_MASK REG_GENMASK(15, 8) +#define DDI_BUF_LANE_STAGGER_DELAY(symbols) REG_FIELD_PREP(DDI_BUF_LANE_STAGGER_DELAY_MASK, \ + (symbols)) +#define DDI_BUF_IS_IDLE REG_BIT(7) +#define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6) +#define DDI_A_4_LANES REG_BIT(4) +#define DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1) +#define DDI_PORT_WIDTH(width) REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, \ + ((width) == 3 ? 4 : (width) - 1)) +#define DDI_PORT_WIDTH_SHIFT 1 +#define DDI_INIT_DISPLAY_DETECTED REG_BIT(0) + +/* DDI Buffer Translations */ +#define _DDI_BUF_TRANS_A 0x64E00 +#define _DDI_BUF_TRANS_B 0x64E60 +#define DDI_BUF_TRANS_LO(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8) +#define DDI_BUF_BALANCE_LEG_ENABLE (1 << 31) +#define DDI_BUF_TRANS_HI(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8 + 4) + +/* DDI DP Compliance Control */ +#define _DDI_DP_COMP_CTL_A 0x605F0 +#define _DDI_DP_COMP_CTL_B 0x615F0 +#define DDI_DP_COMP_CTL(pipe) _MMIO_PIPE(pipe, _DDI_DP_COMP_CTL_A, _DDI_DP_COMP_CTL_B) +#define DDI_DP_COMP_CTL_ENABLE (1 << 31) +#define DDI_DP_COMP_CTL_D10_2 (0 << 28) +#define DDI_DP_COMP_CTL_SCRAMBLED_0 (1 << 28) +#define DDI_DP_COMP_CTL_PRBS7 (2 << 28) +#define DDI_DP_COMP_CTL_CUSTOM80 (3 << 28) +#define DDI_DP_COMP_CTL_HBR2 (4 << 28) +#define DDI_DP_COMP_CTL_SCRAMBLED_1 (5 << 28) +#define DDI_DP_COMP_CTL_HBR2_RESET (0xFC << 0) + +/* DDI DP Compliance Pattern */ +#define _DDI_DP_COMP_PAT_A 0x605F4 +#define _DDI_DP_COMP_PAT_B 0x615F4 +#define DDI_DP_COMP_PAT(pipe, i) _MMIO(_PIPE(pipe, _DDI_DP_COMP_PAT_A, _DDI_DP_COMP_PAT_B) + (i) * 4) + +/* LPT PIXCLK_GATE */ +#define PIXCLK_GATE _MMIO(0xC6020) +#define PIXCLK_GATE_UNGATE (1 << 0) +#define PIXCLK_GATE_GATE (0 << 0) + +/* SPLL */ +#define SPLL_CTL _MMIO(0x46020) +#define SPLL_PLL_ENABLE (1 << 31) +#define SPLL_REF_BCLK (0 << 28) +#define SPLL_REF_MUXED_SSC (1 << 28) /* CPU SSC if fused enabled, PCH SSC otherwise */ +#define SPLL_REF_NON_SSC_HSW (2 << 28) +#define SPLL_REF_PCH_SSC_BDW (2 << 28) +#define SPLL_REF_LCPLL (3 << 28) +#define SPLL_REF_MASK (3 << 28) +#define SPLL_FREQ_810MHz (0 << 26) +#define SPLL_FREQ_1350MHz (1 << 26) +#define SPLL_FREQ_2700MHz (2 << 26) +#define SPLL_FREQ_MASK (3 << 26) + +/* WRPLL */ +#define _WRPLL_CTL1 0x46040 +#define _WRPLL_CTL2 0x46060 +#define WRPLL_CTL(pll) _MMIO_PIPE(pll, _WRPLL_CTL1, _WRPLL_CTL2) +#define WRPLL_PLL_ENABLE (1 << 31) +#define WRPLL_REF_BCLK (0 << 28) +#define WRPLL_REF_PCH_SSC (1 << 28) +#define WRPLL_REF_MUXED_SSC_BDW (2 << 28) /* CPU SSC if fused enabled, PCH SSC otherwise */ +#define WRPLL_REF_SPECIAL_HSW (2 << 28) /* muxed SSC (ULT), non-SSC (non-ULT) */ +#define WRPLL_REF_LCPLL (3 << 28) +#define WRPLL_REF_MASK (3 << 28) +/* WRPLL divider programming */ +#define WRPLL_DIVIDER_REFERENCE(x) ((x) << 0) +#define WRPLL_DIVIDER_REF_MASK (0xff) +#define WRPLL_DIVIDER_POST(x) ((x) << 8) +#define WRPLL_DIVIDER_POST_MASK (0x3f << 8) +#define WRPLL_DIVIDER_POST_SHIFT 8 +#define WRPLL_DIVIDER_FEEDBACK(x) ((x) << 16) +#define WRPLL_DIVIDER_FB_SHIFT 16 +#define WRPLL_DIVIDER_FB_MASK (0xff << 16) + +/* Port clock selection */ +#define _PORT_CLK_SEL_A 0x46100 +#define _PORT_CLK_SEL_B 0x46104 +#define PORT_CLK_SEL(port) _MMIO_PORT(port, _PORT_CLK_SEL_A, _PORT_CLK_SEL_B) +#define PORT_CLK_SEL_MASK REG_GENMASK(31, 29) +#define PORT_CLK_SEL_LCPLL_2700 REG_FIELD_PREP(PORT_CLK_SEL_MASK, 0) +#define PORT_CLK_SEL_LCPLL_1350 REG_FIELD_PREP(PORT_CLK_SEL_MASK, 1) +#define PORT_CLK_SEL_LCPLL_810 REG_FIELD_PREP(PORT_CLK_SEL_MASK, 2) +#define PORT_CLK_SEL_SPLL REG_FIELD_PREP(PORT_CLK_SEL_MASK, 3) +#define PORT_CLK_SEL_WRPLL(pll) REG_FIELD_PREP(PORT_CLK_SEL_MASK, 4 + (pll)) +#define PORT_CLK_SEL_WRPLL1 REG_FIELD_PREP(PORT_CLK_SEL_MASK, 4) +#define PORT_CLK_SEL_WRPLL2 REG_FIELD_PREP(PORT_CLK_SEL_MASK, 5) +#define PORT_CLK_SEL_NONE REG_FIELD_PREP(PORT_CLK_SEL_MASK, 7) + +/* On ICL+ this is the same as PORT_CLK_SEL, but all bits change. */ +#define DDI_CLK_SEL(port) PORT_CLK_SEL(port) +#define DDI_CLK_SEL_MASK REG_GENMASK(31, 28) +#define DDI_CLK_SEL_NONE REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0x0) +#define DDI_CLK_SEL_MG REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0x8) +#define DDI_CLK_SEL_TBT_162 REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0xC) +#define DDI_CLK_SEL_TBT_270 REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0xD) +#define DDI_CLK_SEL_TBT_540 REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0xE) +#define DDI_CLK_SEL_TBT_810 REG_FIELD_PREP(DDI_CLK_SEL_MASK, 0xF) + +/* Transcoder clock selection */ +#define _TRANS_CLK_SEL_A 0x46140 +#define _TRANS_CLK_SEL_B 0x46144 +#define TRANS_CLK_SEL(tran) _MMIO_TRANS(tran, _TRANS_CLK_SEL_A, _TRANS_CLK_SEL_B) +/* For each transcoder, we need to select the corresponding port clock */ +#define TRANS_CLK_SEL_DISABLED (0x0 << 29) +#define TRANS_CLK_SEL_PORT(x) (((x) + 1) << 29) +#define TGL_TRANS_CLK_SEL_DISABLED (0x0 << 28) +#define TGL_TRANS_CLK_SEL_PORT(x) (((x) + 1) << 28) + +#define CDCLK_FREQ _MMIO(0x46200) + +#define _TRANSA_MSA_MISC 0x60410 +#define _TRANSB_MSA_MISC 0x61410 +#define _TRANSC_MSA_MISC 0x62410 +#define _TRANS_EDP_MSA_MISC 0x6f410 +#define TRANS_MSA_MISC(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANSA_MSA_MISC) +/* See DP_MSA_MISC_* for the bit definitions */ + +#define _TRANS_A_SET_CONTEXT_LATENCY 0x6007C +#define _TRANS_B_SET_CONTEXT_LATENCY 0x6107C +#define _TRANS_C_SET_CONTEXT_LATENCY 0x6207C +#define _TRANS_D_SET_CONTEXT_LATENCY 0x6307C +#define TRANS_SET_CONTEXT_LATENCY(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_A_SET_CONTEXT_LATENCY) +#define TRANS_SET_CONTEXT_LATENCY_MASK REG_GENMASK(15, 0) +#define TRANS_SET_CONTEXT_LATENCY_VALUE(x) REG_FIELD_PREP(TRANS_SET_CONTEXT_LATENCY_MASK, (x)) + +/* LCPLL Control */ +#define LCPLL_CTL _MMIO(0x130040) +#define LCPLL_PLL_DISABLE (1 << 31) +#define LCPLL_PLL_LOCK (1 << 30) +#define LCPLL_REF_NON_SSC (0 << 28) +#define LCPLL_REF_BCLK (2 << 28) +#define LCPLL_REF_PCH_SSC (3 << 28) +#define LCPLL_REF_MASK (3 << 28) +#define LCPLL_CLK_FREQ_MASK (3 << 26) +#define LCPLL_CLK_FREQ_450 (0 << 26) +#define LCPLL_CLK_FREQ_54O_BDW (1 << 26) +#define LCPLL_CLK_FREQ_337_5_BDW (2 << 26) +#define LCPLL_CLK_FREQ_675_BDW (3 << 26) +#define LCPLL_CD_CLOCK_DISABLE (1 << 25) +#define LCPLL_ROOT_CD_CLOCK_DISABLE (1 << 24) +#define LCPLL_CD2X_CLOCK_DISABLE (1 << 23) +#define LCPLL_POWER_DOWN_ALLOW (1 << 22) +#define LCPLL_CD_SOURCE_FCLK (1 << 21) +#define LCPLL_CD_SOURCE_FCLK_DONE (1 << 19) + +/* + * SKL Clocks + */ +/* CDCLK_CTL */ +#define CDCLK_CTL _MMIO(0x46000) +#define CDCLK_FREQ_SEL_MASK REG_GENMASK(27, 26) +#define CDCLK_FREQ_450_432 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 0) +#define CDCLK_FREQ_540 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 1) +#define CDCLK_FREQ_337_308 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 2) +#define CDCLK_FREQ_675_617 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 3) +#define MDCLK_SOURCE_SEL_MASK REG_GENMASK(25, 25) +#define MDCLK_SOURCE_SEL_CD2XCLK REG_FIELD_PREP(MDCLK_SOURCE_SEL_MASK, 0) +#define MDCLK_SOURCE_SEL_CDCLK_PLL REG_FIELD_PREP(MDCLK_SOURCE_SEL_MASK, 1) +#define BXT_CDCLK_CD2X_DIV_SEL_MASK REG_GENMASK(23, 22) +#define BXT_CDCLK_CD2X_DIV_SEL_1 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 0) +#define BXT_CDCLK_CD2X_DIV_SEL_1_5 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 1) +#define BXT_CDCLK_CD2X_DIV_SEL_2 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 2) +#define BXT_CDCLK_CD2X_DIV_SEL_4 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 3) +#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe) << 20) +#define CDCLK_DIVMUX_CD_OVERRIDE (1 << 19) +#define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) +#define ICL_CDCLK_CD2X_PIPE(pipe) (_PICK(pipe, 0, 2, 6) << 19) +#define ICL_CDCLK_CD2X_PIPE_NONE (7 << 19) +#define TGL_CDCLK_CD2X_PIPE(pipe) BXT_CDCLK_CD2X_PIPE(pipe) +#define TGL_CDCLK_CD2X_PIPE_NONE ICL_CDCLK_CD2X_PIPE_NONE +#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1 << 16) +#define CDCLK_FREQ_DECIMAL_MASK (0x7ff) + +/* CDCLK_SQUASH_CTL */ +#define CDCLK_SQUASH_CTL _MMIO(0x46008) +#define CDCLK_SQUASH_ENABLE REG_BIT(31) +#define CDCLK_SQUASH_WINDOW_SIZE_MASK REG_GENMASK(27, 24) +#define CDCLK_SQUASH_WINDOW_SIZE(x) REG_FIELD_PREP(CDCLK_SQUASH_WINDOW_SIZE_MASK, (x)) +#define CDCLK_SQUASH_WAVEFORM_MASK REG_GENMASK(15, 0) +#define CDCLK_SQUASH_WAVEFORM(x) REG_FIELD_PREP(CDCLK_SQUASH_WAVEFORM_MASK, (x)) + +/* LCPLL_CTL */ +#define LCPLL1_CTL _MMIO(0x46010) +#define LCPLL2_CTL _MMIO(0x46014) +#define LCPLL_PLL_ENABLE (1 << 31) + +/* DPLL control1 */ +#define DPLL_CTRL1 _MMIO(0x6C058) +#define DPLL_CTRL1_HDMI_MODE(id) (1 << ((id) * 6 + 5)) +#define DPLL_CTRL1_SSC(id) (1 << ((id) * 6 + 4)) +#define DPLL_CTRL1_LINK_RATE_MASK(id) (7 << ((id) * 6 + 1)) +#define DPLL_CTRL1_LINK_RATE_SHIFT(id) ((id) * 6 + 1) +#define DPLL_CTRL1_LINK_RATE(linkrate, id) ((linkrate) << ((id) * 6 + 1)) +#define DPLL_CTRL1_OVERRIDE(id) (1 << ((id) * 6)) +#define DPLL_CTRL1_LINK_RATE_2700 0 +#define DPLL_CTRL1_LINK_RATE_1350 1 +#define DPLL_CTRL1_LINK_RATE_810 2 +#define DPLL_CTRL1_LINK_RATE_1620 3 +#define DPLL_CTRL1_LINK_RATE_1080 4 +#define DPLL_CTRL1_LINK_RATE_2160 5 + +/* DPLL control2 */ +#define DPLL_CTRL2 _MMIO(0x6C05C) +#define DPLL_CTRL2_DDI_CLK_OFF(port) (1 << ((port) + 15)) +#define DPLL_CTRL2_DDI_CLK_SEL_MASK(port) (3 << ((port) * 3 + 1)) +#define DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port) ((port) * 3 + 1) +#define DPLL_CTRL2_DDI_CLK_SEL(clk, port) ((clk) << ((port) * 3 + 1)) +#define DPLL_CTRL2_DDI_SEL_OVERRIDE(port) (1 << ((port) * 3)) + +/* DPLL Status */ +#define DPLL_STATUS _MMIO(0x6C060) +#define DPLL_LOCK(id) (1 << ((id) * 8)) + +/* DPLL cfg */ +#define _DPLL1_CFGCR1 0x6C040 +#define _DPLL2_CFGCR1 0x6C048 +#define _DPLL3_CFGCR1 0x6C050 +#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1) +#define DPLL_CFGCR1_FREQ_ENABLE (1 << 31) +#define DPLL_CFGCR1_DCO_FRACTION_MASK (0x7fff << 9) +#define DPLL_CFGCR1_DCO_FRACTION(x) ((x) << 9) +#define DPLL_CFGCR1_DCO_INTEGER_MASK (0x1ff) + +#define _DPLL1_CFGCR2 0x6C044 +#define _DPLL2_CFGCR2 0x6C04C +#define _DPLL3_CFGCR2 0x6C054 +#define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2) +#define DPLL_CFGCR2_QDIV_RATIO_MASK (0xff << 8) +#define DPLL_CFGCR2_QDIV_RATIO(x) ((x) << 8) +#define DPLL_CFGCR2_QDIV_MODE(x) ((x) << 7) +#define DPLL_CFGCR2_KDIV_MASK (3 << 5) +#define DPLL_CFGCR2_KDIV(x) ((x) << 5) +#define DPLL_CFGCR2_KDIV_5 (0 << 5) +#define DPLL_CFGCR2_KDIV_2 (1 << 5) +#define DPLL_CFGCR2_KDIV_3 (2 << 5) +#define DPLL_CFGCR2_KDIV_1 (3 << 5) +#define DPLL_CFGCR2_PDIV_MASK (7 << 2) +#define DPLL_CFGCR2_PDIV(x) ((x) << 2) +#define DPLL_CFGCR2_PDIV_1 (0 << 2) +#define DPLL_CFGCR2_PDIV_2 (1 << 2) +#define DPLL_CFGCR2_PDIV_3 (2 << 2) +#define DPLL_CFGCR2_PDIV_7 (4 << 2) +#define DPLL_CFGCR2_PDIV_7_INVALID (5 << 2) +#define DPLL_CFGCR2_CENTRAL_FREQ_MASK (3) + +/* ICL Clocks */ +#define ICL_DPCLKA_CFGCR0 _MMIO(0x164280) +#define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) (1 << _PICK(phy, 10, 11, 24, 4, 5)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT((phy) + 10) +#define ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) < TC_PORT_4 ? \ + (tc_port) + 12 : \ + (tc_port) - TC_PORT_4 + 21)) +#define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) ((phy) * 2) +#define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (3 << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) ((pll) << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) _PICK(phy, 0, 2, 4, 27) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) \ + (3 << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) \ + ((pll) << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) + +/* + * DG1 Clocks + * First registers controls the first A and B, while the second register + * controls the phy C and D. The bits on these registers are the + * same, but refer to different phys + */ +#define _DG1_DPCLKA_CFGCR0 0x164280 +#define _DG1_DPCLKA1_CFGCR0 0x16C280 +#define _DG1_DPCLKA_PHY_IDX(phy) ((phy) % 2) +#define _DG1_DPCLKA_PLL_IDX(pll) ((pll) % 2) +#define DG1_DPCLKA_CFGCR0(phy) _MMIO_PHY((phy) / 2, \ + _DG1_DPCLKA_CFGCR0, \ + _DG1_DPCLKA1_CFGCR0) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT(_DG1_DPCLKA_PHY_IDX(phy) + 10) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) (_DG1_DPCLKA_PHY_IDX(phy) * 2) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) (_DG1_DPCLKA_PLL_IDX(pll) << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (0x3 << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) + +/* ADLS Clocks */ +#define _ADLS_DPCLKA_CFGCR0 0x164280 +#define _ADLS_DPCLKA_CFGCR1 0x1642BC +#define ADLS_DPCLKA_CFGCR(phy) _MMIO_PHY((phy) / 3, \ + _ADLS_DPCLKA_CFGCR0, \ + _ADLS_DPCLKA_CFGCR1) +#define ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy) (((phy) % 3) * 2) +/* ADLS DPCLKA_CFGCR0 DDI mask */ +#define ADLS_DPCLKA_DDII_SEL_MASK REG_GENMASK(5, 4) +#define ADLS_DPCLKA_DDIB_SEL_MASK REG_GENMASK(3, 2) +#define ADLS_DPCLKA_DDIA_SEL_MASK REG_GENMASK(1, 0) +/* ADLS DPCLKA_CFGCR1 DDI mask */ +#define ADLS_DPCLKA_DDIK_SEL_MASK REG_GENMASK(3, 2) +#define ADLS_DPCLKA_DDIJ_SEL_MASK REG_GENMASK(1, 0) +#define ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy) _PICK((phy), \ + ADLS_DPCLKA_DDIA_SEL_MASK, \ + ADLS_DPCLKA_DDIB_SEL_MASK, \ + ADLS_DPCLKA_DDII_SEL_MASK, \ + ADLS_DPCLKA_DDIJ_SEL_MASK, \ + ADLS_DPCLKA_DDIK_SEL_MASK) + +/* ICL PLL */ +#define _DPLL0_ENABLE 0x46010 +#define _DPLL1_ENABLE 0x46014 +#define _ADLS_DPLL2_ENABLE 0x46018 +#define _ADLS_DPLL3_ENABLE 0x46030 +#define PLL_ENABLE REG_BIT(31) +#define PLL_LOCK REG_BIT(30) +#define PLL_POWER_ENABLE REG_BIT(27) +#define PLL_POWER_STATE REG_BIT(26) +#define ICL_DPLL_ENABLE(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 3, \ + _DPLL0_ENABLE, _DPLL1_ENABLE, \ + _ADLS_DPLL3_ENABLE, _ADLS_DPLL3_ENABLE)) + +#define _DG2_PLL3_ENABLE 0x4601C + +#define DG2_PLL_ENABLE(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 3, \ + _DPLL0_ENABLE, _DPLL1_ENABLE, \ + _DG2_PLL3_ENABLE, _DG2_PLL3_ENABLE)) + +#define TBT_PLL_ENABLE _MMIO(0x46020) + +#define _MG_PLL1_ENABLE 0x46030 +#define _MG_PLL2_ENABLE 0x46034 +#define _MG_PLL3_ENABLE 0x46038 +#define _MG_PLL4_ENABLE 0x4603C +/* Bits are the same as _DPLL0_ENABLE */ +#define MG_PLL_ENABLE(tc_port) _MMIO_PORT((tc_port), _MG_PLL1_ENABLE, \ + _MG_PLL2_ENABLE) + +/* DG1 PLL */ +#define DG1_DPLL_ENABLE(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _DPLL0_ENABLE, _DPLL1_ENABLE, \ + _MG_PLL1_ENABLE, _MG_PLL2_ENABLE)) + +/* ADL-P Type C PLL */ +#define PORTTC1_PLL_ENABLE 0x46038 +#define PORTTC2_PLL_ENABLE 0x46040 +#define ADLP_PORTTC_PLL_ENABLE(tc_port) _MMIO_PORT((tc_port), \ + PORTTC1_PLL_ENABLE, \ + PORTTC2_PLL_ENABLE) + +#define _ICL_DPLL0_CFGCR0 0x164000 +#define _ICL_DPLL1_CFGCR0 0x164080 +#define ICL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \ + _ICL_DPLL1_CFGCR0) +#define DPLL_CFGCR0_HDMI_MODE (1 << 30) +#define DPLL_CFGCR0_SSC_ENABLE (1 << 29) +#define DPLL_CFGCR0_SSC_ENABLE_ICL (1 << 25) +#define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25) +#define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25) +#define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25) +#define DPLL_CFGCR0_LINK_RATE_810 (2 << 25) +#define DPLL_CFGCR0_LINK_RATE_1620 (3 << 25) +#define DPLL_CFGCR0_LINK_RATE_1080 (4 << 25) +#define DPLL_CFGCR0_LINK_RATE_2160 (5 << 25) +#define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25) +#define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25) +#define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10) +#define DPLL_CFGCR0_DCO_FRACTION_SHIFT (10) +#define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10) +#define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff) + +#define _ICL_DPLL0_CFGCR1 0x164004 +#define _ICL_DPLL1_CFGCR1 0x164084 +#define ICL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \ + _ICL_DPLL1_CFGCR1) +#define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10) +#define DPLL_CFGCR1_QDIV_RATIO_SHIFT (10) +#define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10) +#define DPLL_CFGCR1_QDIV_MODE_SHIFT (9) +#define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9) +#define DPLL_CFGCR1_KDIV_MASK (7 << 6) +#define DPLL_CFGCR1_KDIV_SHIFT (6) +#define DPLL_CFGCR1_KDIV(x) ((x) << 6) +#define DPLL_CFGCR1_KDIV_1 (1 << 6) +#define DPLL_CFGCR1_KDIV_2 (2 << 6) +#define DPLL_CFGCR1_KDIV_3 (4 << 6) +#define DPLL_CFGCR1_PDIV_MASK (0xf << 2) +#define DPLL_CFGCR1_PDIV_SHIFT (2) +#define DPLL_CFGCR1_PDIV(x) ((x) << 2) +#define DPLL_CFGCR1_PDIV_2 (1 << 2) +#define DPLL_CFGCR1_PDIV_3 (2 << 2) +#define DPLL_CFGCR1_PDIV_5 (4 << 2) +#define DPLL_CFGCR1_PDIV_7 (8 << 2) +#define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0) +#define DPLL_CFGCR1_CENTRAL_FREQ_8400 (3 << 0) +#define TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL (0 << 0) + +#define _TGL_DPLL0_CFGCR0 0x164284 +#define _TGL_DPLL1_CFGCR0 0x16428C +#define _TGL_TBTPLL_CFGCR0 0x16429C +#define TGL_DPLL_CFGCR0(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR0, _TGL_DPLL1_CFGCR0, \ + _TGL_TBTPLL_CFGCR0, _TGL_TBTPLL_CFGCR0)) +#define RKL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR0, \ + _TGL_DPLL1_CFGCR0) + +#define _TGL_DPLL0_DIV0 0x164B00 +#define _TGL_DPLL1_DIV0 0x164C00 +#define TGL_DPLL0_DIV0(pll) _MMIO_PLL(pll, _TGL_DPLL0_DIV0, _TGL_DPLL1_DIV0) +#define TGL_DPLL0_DIV0_AFC_STARTUP_MASK REG_GENMASK(27, 25) +#define TGL_DPLL0_DIV0_AFC_STARTUP(val) REG_FIELD_PREP(TGL_DPLL0_DIV0_AFC_STARTUP_MASK, (val)) + +#define _TGL_DPLL0_CFGCR1 0x164288 +#define _TGL_DPLL1_CFGCR1 0x164290 +#define _TGL_TBTPLL_CFGCR1 0x1642A0 +#define TGL_DPLL_CFGCR1(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR1, _TGL_DPLL1_CFGCR1, \ + _TGL_TBTPLL_CFGCR1, _TGL_TBTPLL_CFGCR1)) +#define RKL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR1, \ + _TGL_DPLL1_CFGCR1) + +#define _DG1_DPLL2_CFGCR0 0x16C284 +#define _DG1_DPLL3_CFGCR0 0x16C28C +#define DG1_DPLL_CFGCR0(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR0, _TGL_DPLL1_CFGCR0, \ + _DG1_DPLL2_CFGCR0, _DG1_DPLL3_CFGCR0)) + +#define _DG1_DPLL2_CFGCR1 0x16C288 +#define _DG1_DPLL3_CFGCR1 0x16C290 +#define DG1_DPLL_CFGCR1(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR1, _TGL_DPLL1_CFGCR1, \ + _DG1_DPLL2_CFGCR1, _DG1_DPLL3_CFGCR1)) + +/* For ADL-S DPLL4_CFGCR0/1 are used to control DPLL2 */ +#define _ADLS_DPLL4_CFGCR0 0x164294 +#define _ADLS_DPLL3_CFGCR0 0x1642C0 +#define ADLS_DPLL_CFGCR0(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR0, _TGL_DPLL1_CFGCR0, \ + _ADLS_DPLL4_CFGCR0, _ADLS_DPLL3_CFGCR0)) + +#define _ADLS_DPLL4_CFGCR1 0x164298 +#define _ADLS_DPLL3_CFGCR1 0x1642C4 +#define ADLS_DPLL_CFGCR1(pll) _MMIO(_PICK_EVEN_2RANGES(pll, 2, \ + _TGL_DPLL0_CFGCR1, _TGL_DPLL1_CFGCR1, \ + _ADLS_DPLL4_CFGCR1, _ADLS_DPLL3_CFGCR1)) + +/* BXT display engine PLL */ +#define BXT_DE_PLL_CTL _MMIO(0x6d000) +#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ +#define BXT_DE_PLL_RATIO_MASK 0xff + +#define BXT_DE_PLL_ENABLE _MMIO(0x46070) +#define BXT_DE_PLL_PLL_ENABLE (1 << 31) +#define BXT_DE_PLL_LOCK (1 << 30) +#define BXT_DE_PLL_FREQ_REQ (1 << 23) +#define BXT_DE_PLL_FREQ_REQ_ACK (1 << 22) +#define ICL_CDCLK_PLL_RATIO(x) (x) +#define ICL_CDCLK_PLL_RATIO_MASK 0xff + +/* GEN9 DC */ +#define DC_STATE_EN _MMIO(0x45504) +#define DC_STATE_DISABLE 0 +#define DC_STATE_EN_DC3CO REG_BIT(30) +#define DC_STATE_DC3CO_STATUS REG_BIT(29) +#define HOLD_PHY_CLKREQ_PG1_LATCH REG_BIT(21) +#define HOLD_PHY_PG1_LATCH REG_BIT(20) +#define DC_STATE_EN_UPTO_DC5 (1 << 0) +#define DC_STATE_EN_DC9 (1 << 3) +#define DC_STATE_EN_UPTO_DC6 (2 << 0) +#define DC_STATE_EN_UPTO_DC5_DC6_MASK 0x3 + +#define DC_STATE_DEBUG _MMIO(0x45520) +#define DC_STATE_DEBUG_MASK_CORES (1 << 0) +#define DC_STATE_DEBUG_MASK_MEMORY_UP (1 << 1) + +#define D_COMP_BDW _MMIO(0x138144) + +/* Pipe WM_LINETIME - watermark line time */ +#define _WM_LINETIME_A 0x45270 +#define _WM_LINETIME_B 0x45274 +#define WM_LINETIME(pipe) _MMIO_PIPE(pipe, _WM_LINETIME_A, _WM_LINETIME_B) +#define HSW_LINETIME_MASK REG_GENMASK(8, 0) +#define HSW_LINETIME(x) REG_FIELD_PREP(HSW_LINETIME_MASK, (x)) +#define HSW_IPS_LINETIME_MASK REG_GENMASK(24, 16) +#define HSW_IPS_LINETIME(x) REG_FIELD_PREP(HSW_IPS_LINETIME_MASK, (x)) + +/* SFUSE_STRAP */ +#define SFUSE_STRAP _MMIO(0xc2014) +#define SFUSE_STRAP_FUSE_LOCK (1 << 13) +#define SFUSE_STRAP_RAW_FREQUENCY (1 << 8) +#define SFUSE_STRAP_DISPLAY_DISABLED (1 << 7) +#define SFUSE_STRAP_CRT_DISABLED (1 << 6) +#define SFUSE_STRAP_DDIF_DETECTED (1 << 3) +#define SFUSE_STRAP_DDIB_DETECTED (1 << 2) +#define SFUSE_STRAP_DDIC_DETECTED (1 << 1) +#define SFUSE_STRAP_DDID_DETECTED (1 << 0) + +/* Gen4+ Timestamp and Pipe Frame time stamp registers */ +#define GEN4_TIMESTAMP _MMIO(0x2358) +#define ILK_TIMESTAMP_HI _MMIO(0x70070) +#define IVB_TIMESTAMP_CTR _MMIO(0x44070) + +/* g4x+, except vlv/chv! */ +#define _PIPE_FRMTMSTMP_A 0x70048 +#define _PIPE_FRMTMSTMP_B 0x71048 +#define PIPE_FRMTMSTMP(pipe) \ + _MMIO_PIPE(pipe, _PIPE_FRMTMSTMP_A, _PIPE_FRMTMSTMP_B) + +/* g4x+, except vlv/chv! */ +#define _PIPE_FLIPTMSTMP_A 0x7004C +#define _PIPE_FLIPTMSTMP_B 0x7104C +#define PIPE_FLIPTMSTMP(pipe) \ + _MMIO_PIPE(pipe, _PIPE_FLIPTMSTMP_A, _PIPE_FLIPTMSTMP_B) + +/* tgl+ */ +#define _PIPE_FLIPDONETMSTMP_A 0x70054 +#define _PIPE_FLIPDONETMSTMP_B 0x71054 +#define PIPE_FLIPDONETIMSTMP(pipe) \ + _MMIO_PIPE(pipe, _PIPE_FLIPDONETMSTMP_A, _PIPE_FLIPDONETMSTMP_B) + +#define _VLV_PIPE_MSA_MISC_A 0x70048 +#define VLV_PIPE_MSA_MISC(__display, pipe) \ + _MMIO_PIPE2(__display, pipe, _VLV_PIPE_MSA_MISC_A) +#define VLV_MSA_MISC1_HW_ENABLE REG_BIT(31) +#define VLV_MSA_MISC1_SW_S3D_MASK REG_GENMASK(2, 0) /* MSA MISC1 3:1 */ + +#define _ICL_PHY_MISC_A 0x64C00 +#define _ICL_PHY_MISC_B 0x64C04 +#define _DG2_PHY_MISC_TC1 0x64C14 /* TC1="PHY E" but offset as if "PHY F" */ +#define ICL_PHY_MISC(port) _MMIO_PORT(port, _ICL_PHY_MISC_A, _ICL_PHY_MISC_B) +#define DG2_PHY_MISC(port) ((port) == PHY_E ? _MMIO(_DG2_PHY_MISC_TC1) : \ + ICL_PHY_MISC(port)) +#define ICL_PHY_MISC_MUX_DDID (1 << 28) +#define ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN (1 << 23) +#define DG2_PHY_DP_TX_ACK_MASK REG_GENMASK(23, 20) + +#define PORT_TX_DFLEXDPSP(fia) _MMIO_FIA((fia), 0x008A0) +#define MODULAR_FIA_MASK (1 << 4) +#define TC_LIVE_STATE_TBT(idx) (1 << ((idx) * 8 + 6)) +#define TC_LIVE_STATE_TC(idx) (1 << ((idx) * 8 + 5)) +#define DP_LANE_ASSIGNMENT_SHIFT(idx) ((idx) * 8) +#define DP_LANE_ASSIGNMENT_MASK(idx) (0xf << ((idx) * 8)) +#define DP_LANE_ASSIGNMENT(idx, x) ((x) << ((idx) * 8)) + +#define PORT_TX_DFLEXDPPMS(fia) _MMIO_FIA((fia), 0x00890) +#define DP_PHY_MODE_STATUS_COMPLETED(idx) (1 << (idx)) + +#define PORT_TX_DFLEXDPCSSS(fia) _MMIO_FIA((fia), 0x00894) +#define DP_PHY_MODE_STATUS_NOT_SAFE(idx) (1 << (idx)) + +#define PORT_TX_DFLEXPA1(fia) _MMIO_FIA((fia), 0x00880) +#define DP_PIN_ASSIGNMENT_SHIFT(idx) ((idx) * 4) +#define DP_PIN_ASSIGNMENT_MASK(idx) (0xf << ((idx) * 4)) +#define DP_PIN_ASSIGNMENT(idx, x) ((x) << ((idx) * 4)) + +#define _TCSS_DDI_STATUS_1 0x161500 +#define _TCSS_DDI_STATUS_2 0x161504 +#define TCSS_DDI_STATUS(tc) _MMIO(_PICK_EVEN(tc, \ + _TCSS_DDI_STATUS_1, \ + _TCSS_DDI_STATUS_2)) +#define TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK REG_GENMASK(28, 25) +#define TCSS_DDI_STATUS_READY REG_BIT(2) +#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT REG_BIT(1) +#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT REG_BIT(0) + +#define CLKREQ_POLICY _MMIO(0x101038) +#define CLKREQ_POLICY_MEM_UP_OVRD REG_BIT(1) + +#define CLKGATE_DIS_MISC _MMIO(0x46534) +#define CLKGATE_DIS_MISC_DMASC_GATING_DIS REG_BIT(21) + +#define _MTL_CLKGATE_DIS_TRANS_A 0x604E8 +#define _MTL_CLKGATE_DIS_TRANS_B 0x614E8 +#define MTL_CLKGATE_DIS_TRANS(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _MTL_CLKGATE_DIS_TRANS_A) +#define MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS REG_BIT(7) + +#define _MTL_PIPE_CLKGATE_DIS2_A 0x60114 +#define _MTL_PIPE_CLKGATE_DIS2_B 0x61114 +#define MTL_PIPE_CLKGATE_DIS2(pipe) _MMIO_PIPE(pipe, _MTL_PIPE_CLKGATE_DIS2_A, _MTL_PIPE_CLKGATE_DIS2_B) +#define MTL_DPFC_GATING_DIS REG_BIT(6) + +#define MTL_MEM_SS_INFO_QGV_POINT_OFFSET 0x45710 +#define MTL_MEM_SS_INFO_QGV_POINT_LOW(point) _MMIO(MTL_MEM_SS_INFO_QGV_POINT_OFFSET + (point) * 8) +#define MTL_TRCD_MASK REG_GENMASK(31, 24) +#define MTL_TRP_MASK REG_GENMASK(23, 16) +#define MTL_DCLK_MASK REG_GENMASK(15, 0) + +#define MTL_MEM_SS_INFO_QGV_POINT_HIGH(point) _MMIO(MTL_MEM_SS_INFO_QGV_POINT_OFFSET + (point) * 8 + 4) +#define MTL_TRAS_MASK REG_GENMASK(16, 8) +#define MTL_TRDPRE_MASK REG_GENMASK(7, 0) + + + +#endif /* __INTEL_DISPLAY_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index da429c3329142..f57280e9d041d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -6,6 +6,7 @@ #include "i915_reg.h" #include "intel_de.h" #include "intel_display_core.h" +#include "intel_display_regs.h" #include "intel_display_wa.h" static void gen11_display_wa_apply(struct intel_display *display) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index a7ba17361d63b..a10e56e7cf312 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -29,8 +29,9 @@ #include "i915_reg.h" #include "intel_crtc.h" #include "intel_de.h" -#include "intel_display_rpm.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" +#include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dmc_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 7e2ce0c2f6c39..082cb5597c1a5 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -10,6 +10,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_dmc_regs.h" #include "intel_dmc_wl.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 208a953b04a2f..d04609460e8cf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -36,7 +36,6 @@ #include #include #include - #include #include @@ -65,6 +64,7 @@ #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_driver.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dp.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index cc312596fb77b..23ea94ba4c6c2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -14,6 +14,7 @@ #include "i915_reg.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_hdcp.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index cc00a73898f14..7d13f9e3f4c54 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -42,6 +42,7 @@ #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_driver.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_hdcp.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index bd61f3c3ec911..82b74f1093151 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -13,6 +13,7 @@ #include "i915_reg.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_link_training.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 0282c0b2440b1..339c5c50eb679 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -30,6 +30,7 @@ #include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dpio_phy.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index db98e2758271e..fa6a7d2b70752 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -14,6 +14,7 @@ #include "intel_cx0_phy.h" #include "intel_de.h" #include "intel_display.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 28b3f5ea4219a..2bcbeb7232d7f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -31,6 +31,7 @@ #include "i915_utils.h" #include "intel_cx0_phy.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" #include "intel_dkl_phy_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpt_common.c b/drivers/gpu/drm/i915/display/intel_dpt_common.c index ce5aa0ca0fa53..6914aac6a8f5f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt_common.c +++ b/drivers/gpu/drm/i915/display/intel_dpt_common.c @@ -5,6 +5,7 @@ #include "i915_reg.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_dpt_common.h" #include "skl_universal_plane_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 05cd0f6e6d71b..09ee2b157e2fd 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -9,6 +9,7 @@ #include "i915_reg.h" #include "intel_atomic.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_drrs.h" #include "intel_frontbuffer.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index a4a996018a826..1a03c0ef20540 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -11,6 +11,7 @@ #include "i915_utils.h" #include "intel_crtc.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dsb.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 29c9209834138..6e1a23cc0aadc 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -36,12 +36,12 @@ #include #include #include - #include