summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/adp/Kconfig1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c20
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c8
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c24
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c20
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c37
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c3
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_dpm.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c4
-rw-r--r--drivers/gpu/drm/ast/ast_cursor.c3
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c15
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c6
-rw-r--r--drivers/gpu/drm/drm_exec.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c44
-rw-r--r--drivers/gpu/drm/i915/i915_query.c4
-rw-r--r--drivers/gpu/drm/logicvc/Kconfig1
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c4
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig3
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c7
-rw-r--r--drivers/gpu/drm/scheduler/tests/mock_scheduler.c11
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_mode.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_plane.c4
-rw-r--r--drivers/gpu/drm/xe/instructions/xe_gpu_commands.h1
-rw-r--r--drivers/gpu/drm/xe/xe_pagefault.c10
-rw-r--r--drivers/gpu/drm/xe/xe_pagefault_types.h3
-rw-r--r--drivers/gpu/drm/xe/xe_ring_ops.c11
31 files changed, 227 insertions, 63 deletions
diff --git a/drivers/gpu/drm/adp/Kconfig b/drivers/gpu/drm/adp/Kconfig
index 9fcc27eb200d..acfa21ee06d2 100644
--- a/drivers/gpu/drm/adp/Kconfig
+++ b/drivers/gpu/drm/adp/Kconfig
@@ -6,7 +6,6 @@ config DRM_ADP
select DRM_KMS_HELPER
select DRM_BRIDGE_CONNECTOR
select DRM_DISPLAY_HELPER
- select DRM_KMS_DMA_HELPER
select DRM_GEM_DMA_HELPER
select DRM_PANEL_BRIDGE
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 5d9d137209b6..1b6c32a177fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -1701,9 +1701,8 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
if (dma_resv_trylock(bo->tbo.base.resv)) {
dma_resv_describe(bo->tbo.base.resv, m);
dma_resv_unlock(bo->tbo.base.resv);
- } else {
- seq_puts(m, "\n");
}
+ seq_puts(m, "\n");
return size;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 05abf4c31dce..016957cac1f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -191,6 +191,8 @@ amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entit
* @tmz: if we should setup a TMZ enabled mapping
* @size: in number of bytes to map, out number of bytes mapped
* @addr: resulting address inside the MC address space
+ * @vm_needs_flush: out, set true if a GART window was programmed (VMID 0 flush
+ * needed) or false for a direct address
*
* Setup one of the GART windows to access a specific piece of memory or return
* the physical address for local memory.
@@ -200,7 +202,8 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct ttm_resource *mem,
struct amdgpu_res_cursor *mm_cur,
unsigned int window,
- bool tmz, uint64_t *size, uint64_t *addr)
+ bool tmz, uint64_t *size, uint64_t *addr,
+ bool *vm_needs_flush)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
unsigned int offset, num_pages, num_dw, num_bytes;
@@ -221,9 +224,12 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
if (!tmz && mem->start != AMDGPU_BO_INVALID_OFFSET) {
*addr = amdgpu_ttm_domain_start(adev, mem->mem_type) +
mm_cur->start;
+ *vm_needs_flush = false;
return 0;
}
+ /* A GART window is programmed below, so its VMID 0 TLB needs a flush */
+ *vm_needs_flush = true;
/*
* If start begins at an offset inside the page, then adjust the size
@@ -324,6 +330,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
while (src_mm.remaining) {
uint64_t from, to, cur_size, tiling_flags;
uint32_t num_type, data_format, max_com, write_compress_disable;
+ bool src_vm_flush, dst_vm_flush;
struct dma_fence *next;
/* Never copy more than 256MiB at once to avoid a timeout */
@@ -331,12 +338,12 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
/* Map src to window 0 and dst to window 1. */
r = amdgpu_ttm_map_buffer(entity, src->bo, src->mem, &src_mm,
- 0, tmz, &cur_size, &from);
+ 0, tmz, &cur_size, &from, &src_vm_flush);
if (r)
goto error;
r = amdgpu_ttm_map_buffer(entity, dst->bo, dst->mem, &dst_mm,
- 1, tmz, &cur_size, &to);
+ 1, tmz, &cur_size, &to, &dst_vm_flush);
if (r)
goto error;
@@ -364,7 +371,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
}
r = amdgpu_copy_buffer(adev, entity, from, to, cur_size, resv,
- &next, true, copy_flags);
+ &next, src_vm_flush || dst_vm_flush, copy_flags);
if (r)
goto error;
@@ -2624,6 +2631,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct dma_fence *fence = NULL;
struct amdgpu_res_cursor dst;
+ bool vm_needs_flush = false;
int r;
if (!entity)
@@ -2645,13 +2653,13 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity,
cur_size = min(dst.size, 256ULL << 20);
r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &dst,
- 0, false, &cur_size, &to);
+ 0, false, &cur_size, &to, &vm_needs_flush);
if (r)
goto error;
r = amdgpu_ttm_fill_mem(adev, entity,
0, to, cur_size, resv,
- &next, true, k_job_id);
+ &next, vm_needs_flush, k_job_id);
if (r)
goto error;
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 2fe934036e36..08b8605029ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -747,9 +747,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
}
if (adev->dm.dc->caps.max_links > 0) {
adev->dm.hdmi_frl_status_polling_wq =
- create_singlethread_workqueue("hdmi_frl_status_polling_workqueue");
+ create_singlethread_workqueue("hdmi_frl_status_polling_wq");
if (!adev->dm.hdmi_frl_status_polling_wq)
- drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_workqueue\n");
+ drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_wq\n");
}
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
@@ -1972,6 +1972,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
/* On resume we need to rewrite the MSTM control bits to enable MST*/
s3_handle_mst(ddev, false);
+ /* Exit IPS before the detection loop's first AUX/DDC access. */
+ scoped_guard(mutex, &dm->dc_lock)
+ dc_exit_ips_for_hw_access(dm->dc);
+
/* Do detection*/
drm_connector_list_iter_begin(ddev, &iter);
drm_for_each_connector_iter(connector, &iter) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index c8a1ab8c3b16..154e1f35dcb1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -756,10 +756,14 @@ amdgpu_dm_get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
break;
case DRM_MODE_COLORIMETRY_BT2020_RGB:
case DRM_MODE_COLORIMETRY_BT2020_YCC:
- if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
- color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
- else
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) {
+ if (connector_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
+ color_space = COLOR_SPACE_2020_RGB_LIMITEDRANGE;
+ else
+ color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
+ } else {
color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
+ }
break;
case DRM_MODE_COLORIMETRY_DEFAULT: /* ITU601 */
default:
@@ -3937,17 +3941,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
}
/* Handle MCCS */
- if (do_mccs)
+ if (do_mccs) {
dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
- if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
- (!sink->edid_caps.freesync_vcp_code ||
- (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
- freesync_capable = false;
+ if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)
+ freesync_capable = false;
- if (do_mccs && sink->mccs_caps.freesync_supported && freesync_capable)
- dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
+ if (sink->mccs_caps.freesync_supported && freesync_capable)
+ dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
+ }
update:
if (dm_con_state)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index c4b2fc690fd7..2a6b48e24869 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -196,7 +196,6 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
char *rd_buf_ptr = NULL;
const uint32_t rd_buf_size = 100;
uint32_t result = 0;
- uint8_t str_len = 0;
int r;
if (*pos & 3 || size & 3)
@@ -208,29 +207,26 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
rd_buf_ptr = rd_buf;
- str_len = strlen("Current: %d 0x%x %d ");
- snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ",
+ rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+ "Current: %d 0x%x %d ",
link->cur_link_settings.lane_count,
link->cur_link_settings.link_rate,
link->cur_link_settings.link_spread);
- rd_buf_ptr += str_len;
- str_len = strlen("Verified: %d 0x%x %d ");
- snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ",
+ rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+ "Verified: %d 0x%x %d ",
link->verified_link_cap.lane_count,
link->verified_link_cap.link_rate,
link->verified_link_cap.link_spread);
- rd_buf_ptr += str_len;
- str_len = strlen("Reported: %d 0x%x %d ");
- snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ",
+ rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+ "Reported: %d 0x%x %d ",
link->reported_link_cap.lane_count,
link->reported_link_cap.link_rate,
link->reported_link_cap.link_spread);
- rd_buf_ptr += str_len;
- str_len = strlen("Preferred: %d 0x%x %d ");
- snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n",
+ rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf),
+ "Preferred: %d 0x%x %d\n",
link->preferred_link_setting.lane_count,
link->preferred_link_setting.link_rate,
link->preferred_link_setting.link_spread);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index d451082552e8..298de7b75ca8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -200,6 +200,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
edid_caps->edid_hdmi = connector->display_info.is_hdmi;
if (edid_caps->edid_hdmi) {
+ edid_caps->qs_bit = connector->display_info.rgb_quant_range_selectable;
populate_hdmi_info_from_connector(link->dc->config.enable_frl, &connector->display_info.hdmi, edid_caps);
drm_dbg_driver(connector->dev, "%s: HDMI_FRL [%s] max_frl_rate %d\n", __func__, connector->name, edid_caps->max_frl_rate);
if (edid_caps->frl_dsc_support)
@@ -1202,9 +1203,10 @@ void populate_hdmi_info_from_connector(bool enable_frl, struct drm_hdmi_info *hd
edid_caps->max_frl_rate = get_max_frl_rate(hdmi->max_lanes, hdmi->max_frl_rate_per_lane);
edid_caps->frl_dsc_support = hdmi->dsc_cap.v_1p2;
if (edid_caps->frl_dsc_support) {
- if (hdmi->dsc_cap.bpc_supported == 10)
+ /* HF-VSDB DSC max bpc is cumulative: >=12 implies 10 and 8. */
+ if (hdmi->dsc_cap.bpc_supported >= 10)
edid_caps->frl_dsc_10bpc = true;
- else if (hdmi->dsc_cap.bpc_supported == 12)
+ if (hdmi->dsc_cap.bpc_supported >= 12)
edid_caps->frl_dsc_12bpc = true;
edid_caps->frl_dsc_all_bpp = hdmi->dsc_cap.all_bpp;
edid_caps->frl_dsc_native_420 = hdmi->dsc_cap.native_420;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 0d2f9dbce0a9..212a7536e65b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -568,6 +568,23 @@ static void dm_test_output_color_space_bt2020_rgb(struct kunit *test)
}
/**
+ * dm_test_output_color_space_bt2020_rgb_limited - Test limited BT.2020 RGB
+ * @test: The KUnit test context
+ */
+static void dm_test_output_color_space_bt2020_rgb_limited(struct kunit *test)
+{
+ struct dc_crtc_timing timing = {};
+ struct drm_connector_state state = {};
+
+ timing.pixel_encoding = PIXEL_ENCODING_RGB;
+ state.colorspace = DRM_MODE_COLORIMETRY_BT2020_RGB;
+ state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
+
+ KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state),
+ (int)COLOR_SPACE_2020_RGB_LIMITEDRANGE);
+}
+
+/**
* dm_test_output_color_space_bt2020_ycc - Test Output color space bt2020 ycc
* @test: The KUnit test context
*/
@@ -639,6 +656,24 @@ static void dm_test_output_color_space_bt2020_ycc_rgb_encoding(struct kunit *tes
}
/**
+ * dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited - Test limited
+ * BT.2020 RGB output selected through the BT.2020 YCC connector colorspace
+ * @test: The KUnit test context
+ */
+static void dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited(struct kunit *test)
+{
+ struct dc_crtc_timing timing = {};
+ struct drm_connector_state state = {};
+
+ timing.pixel_encoding = PIXEL_ENCODING_RGB;
+ state.colorspace = DRM_MODE_COLORIMETRY_BT2020_YCC;
+ state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
+
+ KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state),
+ (int)COLOR_SPACE_2020_RGB_LIMITEDRANGE);
+}
+
+/**
* dm_test_output_color_space_bt2020_rgb_ycc_encoding - Test Output color space
* bt2020 rgb with non-rgb pixel encoding falls back to limited ycbcr
* @test: The KUnit test context
@@ -5422,10 +5457,12 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
KUNIT_CASE(dm_test_output_color_space_bt709_y_only),
KUNIT_CASE(dm_test_output_color_space_oprgb),
KUNIT_CASE(dm_test_output_color_space_bt2020_rgb),
+ KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_limited),
KUNIT_CASE(dm_test_output_color_space_bt2020_ycc),
KUNIT_CASE(dm_test_output_color_space_default_ycbcr709_y_only),
KUNIT_CASE(dm_test_output_color_space_default_ycbcr601),
KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding),
+ KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited),
KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_ycc_encoding),
/* Tests for amdgpu_dm_convert_dc_color_depth_into_bpc */
KUNIT_CASE(dm_test_convert_color_depth_bpc_mappings),
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
index 058e1ad15dfe..82e0c984693c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
@@ -358,12 +358,14 @@ static void dm_test_parse_edid_caps_hdmi_frl(struct kunit *test)
/* Drive the HDMI/FRL branch */
connector->display_info.is_hdmi = true;
+ connector->display_info.rgb_quant_range_selectable = true;
connector->display_info.hdmi.scdc.supported = true;
connector->display_info.hdmi.max_lanes = 4;
connector->display_info.hdmi.max_frl_rate_per_lane = 12;
KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
KUNIT_EXPECT_TRUE(test, edid_caps->edid_hdmi);
+ KUNIT_EXPECT_EQ(test, edid_caps->qs_bit, 1);
KUNIT_EXPECT_TRUE(test, edid_caps->scdc_present);
/* max_lanes 4 + max_frl_rate_per_lane 12 -> rate index 6 */
KUNIT_EXPECT_EQ(test, edid_caps->max_frl_rate, 6);
@@ -909,7 +911,7 @@ static void dm_test_populate_hdmi_frl_dsc_12bpc(struct kunit *test)
KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 2);
KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support);
- KUNIT_EXPECT_FALSE(test, caps->frl_dsc_10bpc);
+ KUNIT_EXPECT_TRUE(test, caps->frl_dsc_10bpc);
KUNIT_EXPECT_TRUE(test, caps->frl_dsc_12bpc);
KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 7);
KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 1);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index a98ed4617a03..519ac878ada1 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3198,6 +3198,7 @@ static struct dc_update_descriptor check_update_surfaces_for_stream(
}
if ((stream_update->hdr_static_metadata && !stream_update->stream->use_dynamic_meta) ||
+ stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||
@@ -4188,6 +4189,7 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
hwss_add_setup_periodic_interrupt(&seq_state, dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
+ stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||
@@ -4370,6 +4372,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
+ stream_update->output_color_space ||
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket ||
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index ce526db4d24a..808be6c425bf 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -348,7 +348,8 @@ int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret = 0;
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev) ||
+ amdgpu_in_reset(adev))
return 0;
if (pp_funcs && pp_funcs->switch_power_profile) {
@@ -367,7 +368,8 @@ int amdgpu_dpm_pause_power_profile(struct amdgpu_device *adev,
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret = 0;
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev) ||
+ amdgpu_in_reset(adev))
return 0;
if (pp_funcs && pp_funcs->pause_power_profile) {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 6e741ec4a71e..a29e76b03476 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2092,11 +2092,11 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
- if ((mp1_ver == IP_VERSION(13, 0, 0) && smu->smc_fw_version <= 0x004e1e00) ||
- (mp1_ver == IP_VERSION(13, 0, 10) && smu->smc_fw_version <= 0x00500800))
+ if ((mp1_ver == IP_VERSION(13, 0, 0) &&
+ (smu->smc_fw_version <= 0x004e1e00 || smu->smc_fw_version >= 0x004e8600)) ||
+ (mp1_ver == IP_VERSION(13, 0, 10) &&
+ smu->smc_fw_version <= 0x00500800))
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
- else
- gpu_metrics->energy_accumulator = UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index b94ae43586df..5fe409a23772 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2097,8 +2097,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
- gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ?
- metrics->EnergyAccumulator : UINT_MAX;
+ if (smu->smc_fw_version <= 0x00521400)
+ gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c
index fd19c45f2abe..690d4cd1db5e 100644
--- a/drivers/gpu/drm/ast/ast_cursor.c
+++ b/drivers/gpu/drm/ast/ast_cursor.c
@@ -25,6 +25,7 @@
#include <linux/sizes.h>
#include <drm/drm_atomic.h>
+#include <drm/drm_blend.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -355,6 +356,8 @@ int ast_cursor_plane_init(struct ast_device *ast)
}
drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(cursor_plane);
+ drm_plane_create_blend_mode_property(cursor_plane,
+ BIT(DRM_MODE_BLEND_COVERAGE));
return 0;
}
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
index d1fc6af37cc5..19b43efcf93f 100644
--- a/drivers/gpu/drm/bridge/tc358768.c
+++ b/drivers/gpu/drm/bridge/tc358768.c
@@ -1263,10 +1263,13 @@ tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
return input_fmts;
}
-static bool tc358768_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int tc358768_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+
/* Default to positive sync */
if (!(adjusted_mode->flags &
@@ -1277,13 +1280,15 @@ static bool tc358768_mode_fixup(struct drm_bridge *bridge,
(DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)))
adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC;
- return true;
+ bridge_state->input_bus_cfg.flags = bridge->timings->input_bus_flags;
+
+ return 0;
}
static const struct drm_bridge_funcs tc358768_bridge_funcs = {
.attach = tc358768_bridge_attach,
.mode_valid = tc358768_bridge_mode_valid,
- .mode_fixup = tc358768_mode_fixup,
+ .atomic_check = tc358768_bridge_atomic_check,
.atomic_pre_enable = tc358768_bridge_atomic_pre_enable,
.atomic_enable = tc358768_bridge_atomic_enable,
.atomic_disable = tc358768_bridge_atomic_disable,
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index f9fdbf48c6b3..526826ba4524 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -403,7 +403,7 @@ retry:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
- return 0;
+ return err;
}
static void sn65dsi83_reset_work(struct work_struct *ws)
@@ -419,11 +419,13 @@ static void sn65dsi83_reset_work(struct work_struct *ws)
ret = sn65dsi83_reset_pipe(ctx);
if (ret) {
dev_err(ctx->dev, "reset pipe failed %pe\n", ERR_PTR(ret));
- return;
+ goto bridge_exit;
}
+
if (ctx->irq)
enable_irq(ctx->irq);
+bridge_exit:
drm_bridge_exit(idx);
}
diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c
index 41034a5996ff..2453ec41360f 100644
--- a/drivers/gpu/drm/drm_exec.c
+++ b/drivers/gpu/drm/drm_exec.c
@@ -322,6 +322,19 @@ int drm_exec_prepare_array(struct drm_exec *exec,
{
int ret;
+ /*
+ * Make sure to lock a contended object even when no objects are
+ * given, otherwise drm_exec_retry_on_contention() would loop
+ * forever on patterns like:
+ *
+ * ret = drm_exec_prepare_array(exec, objs, num_objects, ...);
+ * drm_exec_retry_on_contention(exec);
+ *
+ * with num_objects == 0.
+ */
+ if (!num_objects)
+ return drm_exec_lock_contended(exec);
+
for (unsigned int i = 0; i < num_objects; ++i) {
ret = drm_exec_prepare_obj(exec, objects[i], num_fences);
if (unlikely(ret))
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index b7cc361fd955..43d53a98dae7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1946,6 +1946,8 @@ struct intel_dp {
bool colorimetry_support;
+ bool sst_split_sdp_support;
+
struct {
enum transcoder transcoder;
struct mutex lock;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 113d767e62e9..3152122e6aef 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3409,12 +3409,22 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
pipe_config->has_audio =
intel_dp_has_audio(encoder, conn_state) &&
intel_audio_compute_config(encoder, pipe_config, conn_state);
pipe_config->sdp_split_enable = pipe_config->has_audio &&
intel_dp_is_uhbr(pipe_config);
+
+ /*
+ * SDP splitting for UHBR audio requires explicit sink capability in
+ * SST mode, whereas in MST mode it is inherently supported.
+ */
+ if (pipe_config->sdp_split_enable &&
+ !intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST))
+ pipe_config->sdp_split_enable = intel_dp->sst_split_sdp_support;
}
void
@@ -4462,16 +4472,25 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
str_enable_disable(tmp));
}
-static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
+static u8 intel_dp_read_dprx_feature_enum(struct intel_dp *intel_dp)
{
u8 dprx = 0;
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
- &dprx) != 1)
- return false;
+ drm_dp_dpcd_read_data(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
+ &dprx, sizeof(dprx));
+ return dprx;
+}
+
+static bool intel_dp_get_colorimetry_status(u8 dprx)
+{
return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
}
+static bool intel_dp_get_sst_split_sdp_status(u8 dprx)
+{
+ return dprx & DP_SST_SPLIT_SDP_CAP;
+}
+
static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux,
u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
{
@@ -4771,6 +4790,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
{
struct intel_display *display = to_intel_display(intel_dp);
int ret;
+ u8 dprx;
/* this function is meant to be called only once */
drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0);
@@ -4782,8 +4802,13 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
drm_dp_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
+ dprx = intel_dp_read_dprx_feature_enum(intel_dp);
+
intel_dp->colorimetry_support =
- intel_dp_get_colorimetry_status(intel_dp);
+ intel_dp_get_colorimetry_status(dprx);
+
+ intel_dp->sst_split_sdp_support =
+ intel_dp_get_sst_split_sdp_status(dprx);
/*
* Read the eDP display control registers.
@@ -4874,13 +4899,20 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
* the OUI/ID since we know it won't change.
*/
if (!intel_dp_is_edp(intel_dp)) {
+ u8 dprx;
+
drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
drm_dp_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
+ dprx = intel_dp_read_dprx_feature_enum(intel_dp);
+
intel_dp->colorimetry_support =
- intel_dp_get_colorimetry_status(intel_dp);
+ intel_dp_get_colorimetry_status(dprx);
+
+ intel_dp->sst_split_sdp_support =
+ intel_dp_get_sst_split_sdp_status(dprx);
intel_dp_update_sink_caps(intel_dp);
}
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 0c55fb6e9727..11157fb14db3 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -403,8 +403,10 @@ static int query_perf_config_list(struct drm_i915_private *i915,
ids = krealloc(oa_config_ids,
n_configs * sizeof(*oa_config_ids),
GFP_KERNEL);
- if (!ids)
+ if (!ids) {
+ kfree(oa_config_ids);
return -ENOMEM;
+ }
alloc = fetch_and_zero(&n_configs);
diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig
index 579a358ed5cf..11aae1626199 100644
--- a/drivers/gpu/drm/logicvc/Kconfig
+++ b/drivers/gpu/drm/logicvc/Kconfig
@@ -4,7 +4,6 @@ config DRM_LOGICVC
depends on OF || COMPILE_TEST
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
- select DRM_KMS_DMA_HELPER
select DRM_GEM_DMA_HELPER
select REGMAP
select REGMAP_MMIO
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 2fc41fb90aaa..0719fc6a52d5 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -30,6 +30,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
@@ -993,6 +994,9 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
drm_plane_helper_add(plane, helper_funcs);
+ drm_plane_create_blend_mode_property(plane,
+ BIT(DRM_MODE_BLEND_PREMULTI));
+
return plane;
free_plane:
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index e7f49fe845ea..4e58685f58ff 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -68,6 +68,7 @@ config ROCKCHIP_CDN_DP
config ROCKCHIP_DW_DP
bool "Rockchip specific extensions for Synopsys DW DP"
+ select DRM_BRIDGE_CONNECTOR
help
This selects support for Rockchip SoC specific extensions
to enable Synopsys DesignWare Cores based DisplayPort transmit
@@ -145,6 +146,8 @@ config ROCKCHIP_RGB
config ROCKCHIP_RK3066_HDMI
bool "Rockchip specific extensions for RK3066 HDMI"
depends on DRM_ROCKCHIP
+ select DRM_DISPLAY_HELPER
+ select DRM_BRIDGE_CONNECTOR
help
This selects support for Rockchip SoC specific extensions
for the RK3066 HDMI driver. If you want to enable
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 587e60232ec7..efd5a98e80bd 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -241,10 +241,11 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
of_graph_get_remote_port(endpoint.local_node);
of_property_read_u32(remote_port, "reg", &port_id);
- sprintf(name, "%s vp%d", remote_port_parent->full_name, port_id);
+ snprintf(name, sizeof(name), "%s vp%d",
+ remote_port_parent->full_name, port_id);
} else {
- sprintf(name, "%s %s",
- remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb");
+ snprintf(name, sizeof(name), "%s %s",
+ remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb");
}
DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index 8e9ae7d980eb..2dfa3efef210 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025 Valve Corporation */
+#include <kunit/device.h>
+
#include "sched_tests.h"
/*
@@ -288,6 +290,7 @@ static const struct drm_sched_backend_ops drm_mock_scheduler_ops = {
*/
struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout)
{
+ static unsigned int instance;
struct drm_sched_init_args args = {
.ops = &drm_mock_scheduler_ops,
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
@@ -297,11 +300,19 @@ struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout)
.name = "drm-mock-scheduler",
};
struct drm_mock_scheduler *sched;
+ struct device *dev;
+ char name[64];
int ret;
sched = kunit_kzalloc(test, sizeof(*sched), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, sched);
+ snprintf(name, sizeof(name), "%s-%u", args.name, instance++);
+ dev = kunit_device_register(test, name);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ args.dev = dev;
+
ret = drm_sched_init(&sched->base, &args);
KUNIT_ASSERT_EQ(test, ret, 0);
diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c
index 8e4e5fc9d3c5..3c41238a8268 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_mode.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c
@@ -15,6 +15,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_edid.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
@@ -540,6 +541,9 @@ static struct drm_plane *vbox_create_plane(struct vbox_private *vbox,
drm_plane_helper_add(plane, helper_funcs);
+ drm_plane_create_blend_mode_property(plane,
+ BIT(DRM_MODE_BLEND_COVERAGE));
+
return plane;
free_plane:
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 1d1b27ece62a..640815af4098 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -24,6 +24,7 @@
*/
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -609,6 +610,9 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
if (type == DRM_PLANE_TYPE_PRIMARY)
drm_plane_enable_fb_damage_clips(plane);
+ else if (type == DRM_PLANE_TYPE_CURSOR)
+ drm_plane_create_blend_mode_property(plane,
+ BIT(DRM_MODE_BLEND_PREMULTI));
return plane;
}
diff --git a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
index 18d0fde8c98f..faf8d7e2c5c1 100644
--- a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
+++ b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h
@@ -46,6 +46,7 @@
#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
#define PIPE_CONTROL0_QUEUE_DRAIN_MODE BIT(12)
+#define PIPE_CONTROL0_UNTYPED_DATAPORT_CACHE_FLUSH BIT(11) /* gen12 */
#define PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE BIT(10) /* gen12 */
#define PIPE_CONTROL0_HDC_PIPELINE_FLUSH BIT(9) /* gen12 */
diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c
index dbf8f71d3328..a4986df8328d 100644
--- a/drivers/gpu/drm/xe/xe_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_pagefault.c
@@ -16,6 +16,7 @@
#include "xe_hw_engine.h"
#include "xe_pagefault.h"
#include "xe_pagefault_types.h"
+#include "xe_pm.h"
#include "xe_svm.h"
#include "xe_trace_bo.h"
#include "xe_vm.h"
@@ -292,9 +293,17 @@ static void xe_pagefault_queue_work(struct work_struct *w)
{
struct xe_pagefault_queue *pf_queue =
container_of(w, typeof(*pf_queue), worker);
+ struct xe_device *xe = pf_queue->xe;
struct xe_pagefault pf;
unsigned long threshold;
+ /*
+ * A live VM holds a PM reference, but a torn-down VM does not.
+ * Guard the entire worker loop to safely drain stale faults and
+ * prevent autosuspends from desyncing batched CT flushes.
+ */
+ guard(xe_pm_runtime)(xe);
+
#define USM_QUEUE_MAX_RUNTIME_MS 20
threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS);
@@ -365,6 +374,7 @@ static int xe_pagefault_queue_init(struct xe_device *xe,
drm_dbg(&xe->drm, "xe_pagefault_entry_size=%d, total_num_eus=%d, pf_queue->size=%u",
xe_pagefault_entry_size(), total_num_eus, pf_queue->size);
+ pf_queue->xe = xe;
spin_lock_init(&pf_queue->lock);
INIT_WORK(&pf_queue->worker, xe_pagefault_queue_work);
diff --git a/drivers/gpu/drm/xe/xe_pagefault_types.h b/drivers/gpu/drm/xe/xe_pagefault_types.h
index c4ee625b93dd..f63a12aa0d4f 100644
--- a/drivers/gpu/drm/xe/xe_pagefault_types.h
+++ b/drivers/gpu/drm/xe/xe_pagefault_types.h
@@ -8,6 +8,7 @@
#include <linux/workqueue.h>
+struct xe_device;
struct xe_gt;
struct xe_pagefault;
@@ -118,6 +119,8 @@ struct xe_pagefault {
* queue to absorb the device’s worst-case number of outstanding faults.
*/
struct xe_pagefault_queue {
+ /** @xe: Back-pointer to the Xe device */
+ struct xe_device *xe;
/**
* @data: Data in queue containing struct xe_pagefault, protected by
* @lock
diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index 39a670e91ba7..08b4a4283e96 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -212,6 +212,7 @@ static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
{
struct xe_exec_queue *q = job->q;
struct xe_gt *gt = q->gt;
+ struct xe_device *xe = gt_to_xe(gt);
bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
u32 flags0, flags1;
@@ -220,6 +221,16 @@ static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i)
LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0);
flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
+ /*
+ * Prior to MTL, HDC Pipeline Flush reliably also flushes the LSC
+ * untyped L1 dataport cache, provided HDC_CHICKEN0 is programmed
+ * correctly. Starting with MTL that coupling no longer holds
+ * regardless of how HDC_CHICKEN0 is programmed, but explicitly
+ * requesting the flush via PIPE_CONTROL is itself only reliable
+ * from Xe2 onward, so only gate it in on Xe2+.
+ */
+ if (GRAPHICS_VERx100(xe) >= 2000)
+ flags0 |= PIPE_CONTROL0_UNTYPED_DATAPORT_CACHE_FLUSH;
flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH |
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
PIPE_CONTROL_DEPTH_CACHE_FLUSH |