Merge tag 'amd-drm-next-6.19-2025-12-02' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.19-2025-12-02:

amdgpu:
- Unified MES fix
- SMU 11 unbalanced irq fix
- Fix for driver reloading on APUs
- pp_table sysfs fix
- Fix memory leak in fence handling
- HDMI fix
- DC cursor fixes
- eDP panel parsing fix
- Brightness fix
- DC analog fixes
- EDID retry fixes
- UserQ fixes
- RAS fixes
- IP discovery fix
- Add missing locking in amdgpu_ttm_access_memory_sdma()
- Smart Power OLED fix
- PRT and page fault fixes for GC 6-8
- VMID reservation fix
- ACP platform device fix
- Add missing vm fault handling for GC 11-12
- VPE fix

amdkfd:
- Partitioning fix

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20251202220101.2039347-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2025-12-03 09:43:09 +10:00
65 changed files with 1972 additions and 184 deletions

View File

@@ -3932,6 +3932,97 @@ void amdgpu_dm_update_connector_after_detect(
mutex_unlock(&dev->mode_config.mutex);
}
static bool are_sinks_equal(const struct dc_sink *sink1, const struct dc_sink *sink2)
{
if (!sink1 || !sink2)
return false;
if (sink1->sink_signal != sink2->sink_signal)
return false;
if (sink1->dc_edid.length != sink2->dc_edid.length)
return false;
if (memcmp(sink1->dc_edid.raw_edid, sink2->dc_edid.raw_edid,
sink1->dc_edid.length) != 0)
return false;
return true;
}
/**
* DOC: hdmi_hpd_debounce_work
*
* HDMI HPD debounce delay in milliseconds. When an HDMI display toggles HPD
* (such as during power save transitions), this delay determines how long to
* wait before processing the HPD event. This allows distinguishing between a
* physical unplug (>hdmi_hpd_debounce_delay)
* and a spontaneous RX HPD toggle (<hdmi_hpd_debounce_delay).
*
* If the toggle is less than this delay, the driver compares sink capabilities
* and permits a hotplug event if they changed.
*
* The default value of 1500ms was chosen based on experimental testing with
* various monitors that exhibit spontaneous HPD toggling behavior.
*/
static void hdmi_hpd_debounce_work(struct work_struct *work)
{
struct amdgpu_dm_connector *aconnector =
container_of(to_delayed_work(work), struct amdgpu_dm_connector,
hdmi_hpd_debounce_work);
struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
struct dc *dc = aconnector->dc_link->ctx->dc;
bool fake_reconnect = false;
bool reallow_idle = false;
bool ret = false;
guard(mutex)(&aconnector->hpd_lock);
/* Re-detect the display */
scoped_guard(mutex, &adev->dm.dc_lock) {
if (dc->caps.ips_support && dc->ctx->dmub_srv->idle_allowed) {
dc_allow_idle_optimizations(dc, false);
reallow_idle = true;
}
ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
}
if (ret) {
/* Apply workaround delay for certain panels */
apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
/* Compare sinks to determine if this was a spontaneous HPD toggle */
if (are_sinks_equal(aconnector->dc_link->local_sink, aconnector->hdmi_prev_sink)) {
/*
* Sinks match - this was a spontaneous HDMI HPD toggle.
*/
drm_dbg_kms(dev, "HDMI HPD: Sink unchanged after debounce, internal re-enable\n");
fake_reconnect = true;
}
/* Update connector state */
amdgpu_dm_update_connector_after_detect(aconnector);
drm_modeset_lock_all(dev);
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
/* Only notify OS if sink actually changed */
if (!fake_reconnect && aconnector->base.force == DRM_FORCE_UNSPECIFIED)
drm_kms_helper_hotplug_event(dev);
}
/* Release the cached sink reference */
if (aconnector->hdmi_prev_sink) {
dc_sink_release(aconnector->hdmi_prev_sink);
aconnector->hdmi_prev_sink = NULL;
}
scoped_guard(mutex, &adev->dm.dc_lock) {
if (reallow_idle && dc->caps.ips_support)
dc_allow_idle_optimizations(dc, true);
}
}
static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
{
struct drm_connector *connector = &aconnector->base;
@@ -3941,6 +4032,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
struct dc *dc = aconnector->dc_link->ctx->dc;
bool ret = false;
bool debounce_required = false;
if (adev->dm.disable_hpd_irq)
return;
@@ -3963,6 +4055,14 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type))
drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
/*
* Check for HDMI disconnect with debounce enabled.
*/
debounce_required = (aconnector->hdmi_hpd_debounce_delay_ms > 0 &&
dc_is_hdmi_signal(aconnector->dc_link->connector_signal) &&
new_connection_type == dc_connection_none &&
aconnector->dc_link->local_sink != NULL);
if (aconnector->base.force && new_connection_type == dc_connection_none) {
emulated_link_detect(aconnector->dc_link);
@@ -3972,7 +4072,34 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
drm_kms_helper_connector_hotplug_event(connector);
} else if (debounce_required) {
/*
* HDMI disconnect detected - schedule delayed work instead of
* processing immediately. This allows us to coalesce spurious
* HDMI signals from physical unplugs.
*/
drm_dbg_kms(dev, "HDMI HPD: Disconnect detected, scheduling debounce work (%u ms)\n",
aconnector->hdmi_hpd_debounce_delay_ms);
/* Cache the current sink for later comparison */
if (aconnector->hdmi_prev_sink)
dc_sink_release(aconnector->hdmi_prev_sink);
aconnector->hdmi_prev_sink = aconnector->dc_link->local_sink;
if (aconnector->hdmi_prev_sink)
dc_sink_retain(aconnector->hdmi_prev_sink);
/* Schedule delayed detection. */
if (mod_delayed_work(system_wq,
&aconnector->hdmi_hpd_debounce_work,
msecs_to_jiffies(aconnector->hdmi_hpd_debounce_delay_ms)))
drm_dbg_kms(dev, "HDMI HPD: Re-scheduled debounce work\n");
} else {
/* If the aconnector->hdmi_hpd_debounce_work is scheduled, exit early */
if (delayed_work_pending(&aconnector->hdmi_hpd_debounce_work))
return;
scoped_guard(mutex, &adev->dm.dc_lock) {
dc_exit_ips_for_hw_access(dc);
ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
@@ -4998,6 +5125,21 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
struct dc_link *link;
u32 brightness;
bool rc, reallow_idle = false;
struct drm_connector *connector;
list_for_each_entry(connector, &dm->ddev->mode_config.connector_list, head) {
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->bl_idx != bl_idx)
continue;
/* if connector is off, save the brightness for next time it's on */
if (!aconnector->base.encoder) {
dm->brightness[bl_idx] = user_brightness;
dm->actual_brightness[bl_idx] = 0;
return;
}
}
amdgpu_dm_update_backlight_caps(dm, bl_idx);
caps = &dm->backlight_caps[bl_idx];
@@ -7594,6 +7736,13 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
if (aconnector->mst_mgr.dev)
drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
/* Cancel and flush any pending HDMI HPD debounce work */
cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
if (aconnector->hdmi_prev_sink) {
dc_sink_release(aconnector->hdmi_prev_sink);
aconnector->hdmi_prev_sink = NULL;
}
if (aconnector->bl_idx != -1) {
backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]);
dm->backlight_dev[aconnector->bl_idx] = NULL;
@@ -8690,8 +8839,14 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
if (!(amdgpu_freesync_vid_mode && drm_edid))
return;
if (!amdgpu_dm_connector->dc_sink || amdgpu_dm_connector->dc_sink->edid_caps.analog ||
!dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version))
if (!amdgpu_dm_connector->dc_sink || !amdgpu_dm_connector->dc_link)
return;
if (!dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version))
return;
if (dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id) &&
amdgpu_dm_connector->dc_sink->edid_caps.analog)
return;
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
@@ -8703,11 +8858,11 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
{
struct amdgpu_dm_connector *amdgpu_dm_connector =
to_amdgpu_dm_connector(connector);
struct dc_link *dc_link = amdgpu_dm_connector->dc_link;
struct drm_encoder *encoder;
const struct drm_edid *drm_edid = amdgpu_dm_connector->drm_edid;
struct dc_link_settings *verified_link_cap =
&amdgpu_dm_connector->dc_link->verified_link_cap;
const struct dc *dc = amdgpu_dm_connector->dc_link->dc;
struct dc_link_settings *verified_link_cap = &dc_link->verified_link_cap;
const struct dc *dc = dc_link->dc;
encoder = amdgpu_dm_connector_to_encoder(connector);
@@ -8718,7 +8873,9 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
amdgpu_dm_connector->num_modes +=
drm_add_modes_noedid(connector, 1920, 1080);
if (amdgpu_dm_connector->dc_sink && amdgpu_dm_connector->dc_sink->edid_caps.analog) {
if (amdgpu_dm_connector->dc_sink &&
amdgpu_dm_connector->dc_sink->edid_caps.analog &&
dc_connector_supports_analog(dc_link->link_id.id)) {
/* Analog monitor connected by DAC load detection.
* Add common modes. It will be up to the user to select one that works.
*/
@@ -8773,6 +8930,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
mutex_init(&aconnector->hpd_lock);
mutex_init(&aconnector->handle_mst_msg_ready);
aconnector->hdmi_hpd_debounce_delay_ms = AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS;
INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
aconnector->hdmi_prev_sink = NULL;
/*
* configure support HPD hot plug connector_>polled default value is 0
* which means HPD hot plug not supported