diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-08-05 11:02:11 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-08-05 11:02:11 +0000 |
commit | 82ee8c07761e82d76979b285430d144da8fd844c (patch) | |
tree | 4c57919ee73e8423b136ea2a372cd9888e588e0b /sys | |
parent | 3581a42681f72970502dfe7cdbb2c13bcab8ad1c (diff) |
drm/amd/display: Clear dm_state for fast updates
From Mazin Rezk
ee27c88788b88c9c1c75e3a9ce580c79c2dba009 in linux 5.7.y/5.7.13
fde9f39ac7f1ffd799a96ffa1e06b2051f0898f1 in mainline linux
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7c92f70964e..2ca7db4a61c 100644 --- a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8503,20 +8503,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, * the same resource. If we have a new DC context as part of * the DM atomic state from validation we need to free it and * retain the existing one instead. + * + * Furthermore, since the DM atomic state only contains the DC + * context and can safely be annulled, we can free the state + * and clear the associated private object now to free + * some memory and avoid a possible use-after-free later. */ - struct dm_atomic_state *new_dm_state, *old_dm_state; - new_dm_state = dm_atomic_get_new_state(state); - old_dm_state = dm_atomic_get_old_state(state); + for (i = 0; i < state->num_private_objs; i++) { + struct drm_private_obj *obj = state->private_objs[i].ptr; - if (new_dm_state && old_dm_state) { - if (new_dm_state->context) - dc_release_state(new_dm_state->context); + if (obj->funcs == adev->dm.atomic_obj.funcs) { + int j = state->num_private_objs-1; - new_dm_state->context = old_dm_state->context; + dm_atomic_destroy_state(obj, + state->private_objs[i].state); + + /* If i is not at the end of the array then the + * last element needs to be moved to where i was + * before the array can safely be truncated. + */ + if (i != j) + state->private_objs[i] = + state->private_objs[j]; - if (old_dm_state->context) - dc_retain_state(old_dm_state->context); + state->private_objs[j].ptr = NULL; + state->private_objs[j].state = NULL; + state->private_objs[j].old_state = NULL; + state->private_objs[j].new_state = NULL; + + state->num_private_objs = j; + break; + } } } |