Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: fix page fault due to max surface definition mismatch

DC driver is using two different values to define the maximum number of
surfaces: MAX_SURFACES and MAX_SURFACE_NUM. Consolidate MAX_SURFACES as
the unique definition for surface updates across DC.

It fixes page fault faced by Cosmic users on AMD display versions that
support two overlay planes, since the introduction of cursor overlay
mode.

[Nov26 21:33] BUG: unable to handle page fault for address: 0000000051d0f08b
[ +0.000015] #PF: supervisor read access in kernel mode
[ +0.000006] #PF: error_code(0x0000) - not-present page
[ +0.000005] PGD 0 P4D 0
[ +0.000007] Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
[ +0.000006] CPU: 4 PID: 71 Comm: kworker/u32:6 Not tainted 6.10.0+ #300
[ +0.000006] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0131 01/30/2024
[ +0.000007] Workqueue: events_unbound commit_work [drm_kms_helper]
[ +0.000040] RIP: 0010:copy_stream_update_to_stream.isra.0+0x30d/0x750 [amdgpu]
[ +0.000847] Code: 8b 10 49 89 94 24 f8 00 00 00 48 8b 50 08 49 89 94 24 00 01 00 00 8b 40 10 41 89 84 24 08 01 00 00 49 8b 45 78 48 85 c0 74 0b <0f> b6 00 41 88 84 24 90 64 00 00 49 8b 45 60 48 85 c0 74 3b 48 8b
[ +0.000010] RSP: 0018:ffffc203802f79a0 EFLAGS: 00010206
[ +0.000009] RAX: 0000000051d0f08b RBX: 0000000000000004 RCX: ffff9f964f0a8070
[ +0.000004] RDX: ffff9f9710f90e40 RSI: ffff9f96600c8000 RDI: ffff9f964f000000
[ +0.000004] RBP: ffffc203802f79f8 R08: 0000000000000000 R09: 0000000000000000
[ +0.000005] R10: 0000000000000000 R11: 0000000000000000 R12: ffff9f96600c8000
[ +0.000004] R13: ffff9f9710f90e40 R14: ffff9f964f000000 R15: ffff9f96600c8000
[ +0.000004] FS: 0000000000000000(0000) GS:ffff9f9970000000(0000) knlGS:0000000000000000
[ +0.000005] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ +0.000005] CR2: 0000000051d0f08b CR3: 00000002e6a20000 CR4: 0000000000350ef0
[ +0.000005] Call Trace:
[ +0.000011] <TASK>
[ +0.000010] ? __die_body.cold+0x19/0x27
[ +0.000012] ? page_fault_oops+0x15a/0x2d0
[ +0.000014] ? exc_page_fault+0x7e/0x180
[ +0.000009] ? asm_exc_page_fault+0x26/0x30
[ +0.000013] ? copy_stream_update_to_stream.isra.0+0x30d/0x750 [amdgpu]
[ +0.000739] ? dc_commit_state_no_check+0xd6c/0xe70 [amdgpu]
[ +0.000470] update_planes_and_stream_state+0x49b/0x4f0 [amdgpu]
[ +0.000450] ? srso_return_thunk+0x5/0x5f
[ +0.000009] ? commit_minimal_transition_state+0x239/0x3d0 [amdgpu]
[ +0.000446] update_planes_and_stream_v2+0x24a/0x590 [amdgpu]
[ +0.000464] ? srso_return_thunk+0x5/0x5f
[ +0.000009] ? sort+0x31/0x50
[ +0.000007] ? amdgpu_dm_atomic_commit_tail+0x159f/0x3a30 [amdgpu]
[ +0.000508] ? srso_return_thunk+0x5/0x5f
[ +0.000009] ? amdgpu_crtc_get_scanout_position+0x28/0x40 [amdgpu]
[ +0.000377] ? srso_return_thunk+0x5/0x5f
[ +0.000009] ? drm_crtc_vblank_helper_get_vblank_timestamp_internal+0x160/0x390 [drm]
[ +0.000058] ? srso_return_thunk+0x5/0x5f
[ +0.000005] ? dma_fence_default_wait+0x8c/0x260
[ +0.000010] ? srso_return_thunk+0x5/0x5f
[ +0.000005] ? wait_for_completion_timeout+0x13b/0x170
[ +0.000006] ? srso_return_thunk+0x5/0x5f
[ +0.000005] ? dma_fence_wait_timeout+0x108/0x140
[ +0.000010] ? commit_tail+0x94/0x130 [drm_kms_helper]
[ +0.000024] ? process_one_work+0x177/0x330
[ +0.000008] ? worker_thread+0x266/0x3a0
[ +0.000006] ? __pfx_worker_thread+0x10/0x10
[ +0.000004] ? kthread+0xd2/0x100
[ +0.000006] ? __pfx_kthread+0x10/0x10
[ +0.000006] ? ret_from_fork+0x34/0x50
[ +0.000004] ? __pfx_kthread+0x10/0x10
[ +0.000005] ? ret_from_fork_asm+0x1a/0x30
[ +0.000011] </TASK>

Fixes: 1b04dcca4fb1 ("drm/amd/display: Introduce overlay cursor mode")
Suggested-by: Leo Li <sunpeng.li@amd.com>
Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3693
Signed-off-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 1c86c81a86c60f9b15d3e3f43af0363cf56063e7)
Cc: stable@vger.kernel.org

authored by

Melissa Wen and committed by
Alex Deucher
7de8d5c9 5009628d

+8 -9
+1 -1
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 4510 4510 struct pipe_split_policy_backup policy; 4511 4511 struct dc_state *intermediate_context; 4512 4512 struct dc_state *old_current_state = dc->current_state; 4513 - struct dc_surface_update srf_updates[MAX_SURFACE_NUM] = {0}; 4513 + struct dc_surface_update srf_updates[MAX_SURFACES] = {0}; 4514 4514 int surface_count; 4515 4515 4516 4516 /*
+4 -4
drivers/gpu/drm/amd/display/dc/core/dc_state.c
··· 483 483 if (stream_status == NULL) { 484 484 dm_error("Existing stream not found; failed to attach surface!\n"); 485 485 goto out; 486 - } else if (stream_status->plane_count == MAX_SURFACE_NUM) { 486 + } else if (stream_status->plane_count == MAX_SURFACES) { 487 487 dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 488 - plane_state, MAX_SURFACE_NUM); 488 + plane_state, MAX_SURFACES); 489 489 goto out; 490 490 } else if (!otg_master_pipe) { 491 491 goto out; ··· 600 600 { 601 601 int i, old_plane_count; 602 602 struct dc_stream_status *stream_status = NULL; 603 - struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 603 + struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 }; 604 604 605 605 for (i = 0; i < state->stream_count; i++) 606 606 if (state->streams[i] == stream) { ··· 875 875 { 876 876 int i, old_plane_count; 877 877 struct dc_stream_status *stream_status = NULL; 878 - struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 878 + struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 }; 879 879 880 880 for (i = 0; i < state->stream_count; i++) 881 881 if (state->streams[i] == phantom_stream) {
+1 -1
drivers/gpu/drm/amd/display/dc/dc.h
··· 1398 1398 * store current value in plane states so we can still recover 1399 1399 * a valid current state during dc update. 1400 1400 */ 1401 - struct dc_plane_state plane_states[MAX_SURFACE_NUM]; 1401 + struct dc_plane_state plane_states[MAX_SURFACES]; 1402 1402 1403 1403 struct dc_stream_state stream_state; 1404 1404 };
+1 -1
drivers/gpu/drm/amd/display/dc/dc_stream.h
··· 56 56 int plane_count; 57 57 int audio_inst; 58 58 struct timing_sync_info timing_sync_info; 59 - struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; 59 + struct dc_plane_state *plane_states[MAX_SURFACES]; 60 60 bool is_abm_supported; 61 61 struct mall_stream_config mall_stream_config; 62 62 bool fpo_in_use;
-1
drivers/gpu/drm/amd/display/dc/dc_types.h
··· 76 76 unsigned long last_entry_write; 77 77 }; 78 78 79 - #define MAX_SURFACE_NUM 6 80 79 #define NUM_PIXEL_FORMATS 10 81 80 82 81 enum tiling_mode {
+1 -1
drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
··· 813 813 { 814 814 int i, old_plane_count; 815 815 struct dc_stream_status *stream_status = NULL; 816 - struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 816 + struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 }; 817 817 818 818 for (i = 0; i < context->stream_count; i++) 819 819 if (context->streams[i] == stream) {