summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-07-10 13:03:14 +1000
committerDave Airlie <airlied@redhat.com>2026-07-10 13:03:15 +1000
commit7978a34fd6e4eae91db0741b553e7682288d022c (patch)
tree7829e50ec6c98620859b0e4e35f28aabd807226b /drivers/gpu/drm
parent58570ef9dc5d0b0465346883f492f12ea1c22369 (diff)
parentcf385cf6e713eba0720651174dac0b2d2f5bb8f8 (diff)
Merge tag 'drm-misc-fixes-2026-07-09' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
drm-misc-fixes for v7.2-rc3: - Fix uaf in amdxdna mmap failure path. - A lot of deadlocks, access races and return value fixes in amdxdna. - Fix analogix_dp bitshifts during link training. - Use direct label in drm_exec. - Fix absent indirect bo handling in v3d. - Sync on first active crtc in fb_dirty, rather than first crtc. - Rework try_harder in the buddy allocator. - Make imagination function static to solve compiler warning. - Fix imagination error checking. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/71e5b48b-307f-47f5-8fd5-b60ea43e4196@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c4
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c92
-rw-r--r--drivers/gpu/drm/drm_ioctl.c14
-rw-r--r--drivers/gpu/drm/imagination/pvr_context.c4
-rw-r--r--drivers/gpu/drm/imagination/pvr_fw_trace.c2
-rw-r--r--drivers/gpu/drm/tests/drm_exec_test.c24
-rw-r--r--drivers/gpu/drm/v3d/v3d_submit.c2
8 files changed, 131 insertions, 13 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index f317f888b59f..7b6917c8a509 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -3015,6 +3015,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
is_compute_context = vm->is_compute_context;
if (is_compute_context) {
+ __label__ drm_exec_retry;
+
/* Release the root PD lock since svm_range_restore_pages
* might try to take it.
* TODO: rework svm_range_restore_pages so that this isn't
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 8cf6b73bceac..5006ac181b2d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -309,7 +309,9 @@ static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
lane_count = dp->link_train.lane_count;
for (lane = 0; lane < lane_count; lane++) {
voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+ voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+ pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
@@ -355,7 +357,9 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
for (lane = 0; lane < lane_count; lane++) {
training_lane = analogix_dp_get_lane_link_training(dp, lane);
voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+ voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+ pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 7b11a582f8ec..80ca785bdb26 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -225,16 +225,106 @@ static void drm_fb_helper_resume_worker(struct work_struct *work)
console_unlock();
}
+static int find_crtc_index_atomic(struct drm_fb_helper *helper)
+{
+ struct drm_device *dev = helper->dev;
+ int crtc_index = -EINVAL;
+ struct drm_modeset_acquire_ctx ctx;
+ struct drm_plane *plane;
+ int ret = 0;
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+ drm_for_each_plane(plane, dev) {
+ const struct drm_plane_state *plane_state;
+
+ if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+ continue;
+
+ ret = drm_modeset_lock(&plane->mutex, &ctx);
+ if (ret)
+ goto err_drm_modeset_lock;
+ plane_state = plane->state;
+
+ if (plane_state->fb == helper->fb && plane_state->crtc) {
+ struct drm_crtc *crtc = plane_state->crtc;
+
+ ret = drm_modeset_lock(&crtc->mutex, &ctx);
+ if (ret)
+ goto err_drm_modeset_lock;
+ if (crtc->state->active)
+ crtc_index = crtc->index;
+ drm_modeset_unlock(&crtc->mutex);
+ }
+ drm_modeset_unlock(&plane->mutex);
+
+ if (crtc_index >= 0)
+ break;
+ }
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
+ return crtc_index;
+
+err_drm_modeset_lock:
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+ return ret;
+}
+
+static int find_crtc_index_legacy(struct drm_fb_helper *helper)
+{
+ struct drm_device *dev = helper->dev;
+ struct drm_crtc *crtc;
+
+ drm_for_each_crtc(crtc, dev) {
+ struct drm_plane *plane = crtc->primary;
+
+ if (!crtc->enabled)
+ continue;
+ if (!plane || plane->fb != helper->fb)
+ continue; /* CRTC doesn't display fbdev emulation */
+
+ return crtc->index;
+ }
+
+ return -EINVAL;
+}
+
+static int drm_fb_helper_find_crtc_index(struct drm_fb_helper *helper)
+{
+ struct drm_device *dev = helper->dev;
+ int crtc_index;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ if (drm_drv_uses_atomic_modeset(dev))
+ crtc_index = find_crtc_index_atomic(helper);
+ else
+ crtc_index = find_crtc_index_legacy(helper);
+
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return crtc_index;
+}
+
static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)
{
struct drm_device *dev = helper->dev;
struct drm_clip_rect *clip = &helper->damage_clip;
struct drm_clip_rect clip_copy;
+ int crtc_index;
unsigned long flags;
int ret;
mutex_lock(&helper->lock);
- drm_client_modeset_wait_for_vblank(&helper->client, 0);
+ crtc_index = drm_fb_helper_find_crtc_index(helper);
+ if (crtc_index >= 0)
+ drm_client_modeset_wait_for_vblank(&helper->client, crtc_index);
mutex_unlock(&helper->lock);
if (drm_WARN_ON_ONCE(dev, !helper->funcs->fb_dirty))
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index e2df4becce62..9039a39c4324 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -373,13 +373,25 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL;
file_priv->supports_virtualized_cursor_plane = req->value;
break;
- case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:
+ case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE: {
+ struct drm_plane *plane;
+ bool has_plane_with_color_pipeline = false;
+
if (!file_priv->atomic)
return -EINVAL;
if (req->value > 1)
return -EINVAL;
+ drm_for_each_plane(plane, dev) {
+ if (plane->color_pipeline_property) {
+ has_plane_with_color_pipeline = true;
+ break;
+ }
+ }
+ if (!has_plane_with_color_pipeline)
+ return -EOPNOTSUPP;
file_priv->plane_color_pipeline = req->value;
break;
+ }
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/imagination/pvr_context.c b/drivers/gpu/drm/imagination/pvr_context.c
index 52e16c1e7af0..406e0758e860 100644
--- a/drivers/gpu/drm/imagination/pvr_context.c
+++ b/drivers/gpu/drm/imagination/pvr_context.c
@@ -309,8 +309,8 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
goto err_free_ctx;
ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
- if (IS_ERR(ctx->vm_ctx)) {
- err = PTR_ERR(ctx->vm_ctx);
+ if (!ctx->vm_ctx) {
+ err = -EINVAL;
goto err_free_ctx;
}
diff --git a/drivers/gpu/drm/imagination/pvr_fw_trace.c b/drivers/gpu/drm/imagination/pvr_fw_trace.c
index 6bb5baa6c41b..805d9f9bc1dd 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_trace.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_trace.c
@@ -71,7 +71,7 @@ pvr_fw_trace_init_mask_set(const char *val, const struct kernel_param *kp)
return 0;
}
-const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
+static const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
.set = pvr_fw_trace_init_mask_set,
.get = param_get_hexint,
};
diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/drm_exec_test.c
index 2fc47f3b463b..7a374e462348 100644
--- a/drivers/gpu/drm/tests/drm_exec_test.c
+++ b/drivers/gpu/drm/tests/drm_exec_test.c
@@ -180,19 +180,27 @@ static void test_multiple_loops(struct kunit *test)
{
struct drm_exec exec;
- drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
- drm_exec_until_all_locked(&exec)
{
- break;
+ __label__ drm_exec_retry;
+
+ drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
+ drm_exec_until_all_locked(&exec)
+ {
+ break;
+ }
+ drm_exec_fini(&exec);
}
- drm_exec_fini(&exec);
- drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
- drm_exec_until_all_locked(&exec)
{
- break;
+ __label__ drm_exec_retry;
+
+ drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
+ drm_exec_until_all_locked(&exec)
+ {
+ break;
+ }
+ drm_exec_fini(&exec);
}
- drm_exec_fini(&exec);
KUNIT_SUCCEED(test);
}
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 1db43c6a078d..7682b24f13ec 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -495,6 +495,8 @@ v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv,
sizeof(indirect_csd.wg_uniform_offsets));
info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);
+ if (!info->indirect)
+ return -ENOENT;
return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
&info->job, &info->clean_job,