mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
Merge tag 'drm-intel-fixes-2026-05-27' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-fixes
- Fix potential UAF in TTM object purge (Janusz Krzysztofik) - Use polling when irqs are unavailable [aux] (Michał Grzelak) - Fix HDR pre-CSC LUT programming loop [color] (Pranay Samala) - Block DC states on vblank enable when Panel Replay supported [psr] (Jouni Högander) - Use DC_OFF wake reference to block DC6 on vblank enable [psr] (Jouni Högander) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Tvrtko Ursulin <tursulin@igalia.com> Link: https://patch.msgid.link/ahajfPMJE_qKzig5@linux
This commit is contained in:
commit
96c85df77f
|
|
@ -3976,7 +3976,7 @@ xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb,
|
|||
intel_de_write_dsb(display, dsb,
|
||||
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||
(1 << 24));
|
||||
} while (i++ > 130);
|
||||
} while (i++ < 130);
|
||||
} else {
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ struct intel_display {
|
|||
u8 vblank_enabled;
|
||||
|
||||
int vblank_enable_count;
|
||||
bool vblank_status_last_notified;
|
||||
|
||||
struct work_struct vblank_notify_work;
|
||||
|
||||
|
|
|
|||
|
|
@ -1773,8 +1773,12 @@ static void intel_display_vblank_notify_work(struct work_struct *work)
|
|||
struct intel_display *display =
|
||||
container_of(work, typeof(*display), irq.vblank_notify_work);
|
||||
int vblank_enable_count = READ_ONCE(display->irq.vblank_enable_count);
|
||||
bool vblank_status = !!vblank_enable_count;
|
||||
|
||||
intel_psr_notify_vblank_enable_disable(display, vblank_enable_count);
|
||||
if (display->irq.vblank_status_last_notified != vblank_status) {
|
||||
intel_psr_notify_vblank_enable_disable(display, vblank_status);
|
||||
display->irq.vblank_status_last_notified = vblank_status;
|
||||
}
|
||||
}
|
||||
|
||||
int bdw_enable_vblank(struct drm_crtc *_crtc)
|
||||
|
|
@ -1787,10 +1791,10 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
|
|||
if (gen11_dsi_configure_te(crtc, true))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
if (crtc->vblank_psr_notify && display->irq.vblank_enable_count++ == 0)
|
||||
schedule_work(&display->irq.vblank_notify_work);
|
||||
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
|
|
|
|||
|
|
@ -1790,6 +1790,8 @@ struct intel_psr {
|
|||
u8 active_non_psr_pipes;
|
||||
|
||||
const char *no_psr_reason;
|
||||
|
||||
struct ref_tracker *vblank_wakeref;
|
||||
};
|
||||
|
||||
struct intel_dp {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "intel_dp.h"
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_dp_aux_regs.h"
|
||||
#include "intel_parent.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_quirks.h"
|
||||
#include "intel_tc.h"
|
||||
|
|
@ -60,18 +61,29 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
|
|||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
|
||||
const unsigned int timeout_ms = 10;
|
||||
bool done = true;
|
||||
u32 status;
|
||||
bool done;
|
||||
int ret;
|
||||
|
||||
if (intel_parent_irq_enabled(display)) {
|
||||
#define C (((status = intel_de_read_notrace(display, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
|
||||
done = wait_event_timeout(display->gmbus.wait_queue, C,
|
||||
msecs_to_jiffies_timeout(timeout_ms));
|
||||
done = wait_event_timeout(display->gmbus.wait_queue, C,
|
||||
msecs_to_jiffies_timeout(timeout_ms));
|
||||
|
||||
#undef C
|
||||
} else {
|
||||
ret = intel_de_wait_ms(display, ch_ctl,
|
||||
DP_AUX_CH_CTL_SEND_BUSY, 0,
|
||||
timeout_ms, &status);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
done = false;
|
||||
}
|
||||
|
||||
if (!done)
|
||||
drm_err(display->drm,
|
||||
"%s: did not complete or timeout within %ums (status 0x%08x)\n",
|
||||
intel_dp->aux.name, timeout_ms, status);
|
||||
#undef C
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4156,27 +4156,22 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
|
|||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
if (intel_dp->psr.panel_replay_enabled) {
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
break;
|
||||
if (CAN_PANEL_REPLAY(intel_dp)) {
|
||||
if (enable)
|
||||
intel_dp->psr.vblank_wakeref =
|
||||
intel_display_power_get(display,
|
||||
POWER_DOMAIN_DC_OFF);
|
||||
else
|
||||
intel_display_power_put(display, POWER_DOMAIN_DC_OFF,
|
||||
intel_dp->psr.vblank_wakeref);
|
||||
}
|
||||
|
||||
if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
|
||||
if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
|
||||
intel_dp->psr.pkg_c_latency_used)
|
||||
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: intel_display_power_set_target_dc_state is used
|
||||
* only by PSR * code for DC3CO handling. DC3CO target
|
||||
* state is currently disabled in * PSR code. If DC3CO
|
||||
* is taken into use we need take that into account here
|
||||
* as well.
|
||||
*/
|
||||
intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
|
||||
DC_STATE_EN_UPTO_DC6);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -419,8 +419,6 @@ void i915_ttm_free_cached_io_rsgt(struct drm_i915_gem_object *obj)
|
|||
int i915_ttm_purge(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
|
||||
struct i915_ttm_tt *i915_tt =
|
||||
container_of(bo->ttm, typeof(*i915_tt), ttm);
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = false,
|
||||
|
|
@ -435,16 +433,22 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bo->ttm && i915_tt->filp) {
|
||||
/*
|
||||
* The below fput(which eventually calls shmem_truncate) might
|
||||
* be delayed by worker, so when directly called to purge the
|
||||
* pages(like by the shrinker) we should try to be more
|
||||
* aggressive and release the pages immediately.
|
||||
*/
|
||||
shmem_truncate_range(file_inode(i915_tt->filp),
|
||||
0, (loff_t)-1);
|
||||
fput(fetch_and_zero(&i915_tt->filp));
|
||||
if (bo->ttm) {
|
||||
struct i915_ttm_tt *i915_tt =
|
||||
container_of(bo->ttm, typeof(*i915_tt), ttm);
|
||||
|
||||
if (i915_tt->filp) {
|
||||
/*
|
||||
* The below fput(which eventually calls shmem_truncate)
|
||||
* might be delayed by worker, so when directly called
|
||||
* to purge the pages(like by the shrinker) we should
|
||||
* try to be more aggressive and release the pages
|
||||
* immediately.
|
||||
*/
|
||||
shmem_truncate_range(file_inode(i915_tt->filp),
|
||||
0, (loff_t)-1);
|
||||
fput(fetch_and_zero(&i915_tt->filp));
|
||||
}
|
||||
}
|
||||
|
||||
obj->write_domain = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user