amdgpu_do_pageflip() indexed the flipdata->fb[] array
indexing over config->num_crtc, but the flip completion
routines, e.g., drmmode_flip_handler(), index that array
via the crtc hw id from drmmode_get_crtc_id(crtc).

This is mismatched and causes indexing into the wrong
array slot at flip completion -> Server crash.

Always use drmmode_get_crtc_id(crtc) for indexing into
the array to fix this.

Tested on a dual-X-Screen setup with one video output
assigned to each X-Screen, page-flipping an OpenGL app
on either of both X-Screens. This used to crash when
flipping on X-Screen 1, now it doesn't anymore.

Fixes: 9b6782c821e0 "Store FB for each CRTC in drmmode_flipdata_rec"
(Ported from radeon commit 0058fd2ebf4c900b12f129984e98886a7ac84b2f)
Signed-off-by: Mario Kleiner <mario.kleiner...@gmail.com>
---
 src/drmmode_display.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 92cf543..fdadf89 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -4006,6 +4006,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
        xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
        xf86CrtcPtr crtc = NULL;
        drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
+       int crtc_id;
        uint32_t flip_flags = flip_sync == FLIP_ASYNC ? 
DRM_MODE_PAGE_FLIP_ASYNC : 0;
        drmmode_flipdata_ptr flipdata;
        Bool handle_deferred = FALSE;
@@ -4013,7 +4014,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
        struct drmmode_fb *fb;
        int i = 0;
 
-       flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc *
+       flipdata = calloc(1, sizeof(*flipdata) + 
drmmode_crtc->drmmode->count_crtcs *
                          sizeof(flipdata->fb[0]));
        if (!flipdata) {
                xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -4045,6 +4046,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
        for (i = 0; i < config->num_crtc; i++) {
                crtc = config->crtc[i];
                drmmode_crtc = crtc->driver_private;
+               crtc_id = drmmode_get_crtc_id(crtc);
 
                if (!drmmode_crtc_can_flip(crtc) ||
                    (drmmode_crtc->tear_free && crtc != ref_crtc))
@@ -4079,9 +4081,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
                                goto next;
                        }
 
-                       drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb[i],
+                       drmmode_fb_reference(pAMDGPUEnt->fd, 
&flipdata->fb[crtc_id],
                                             
amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
-                       if (!flipdata->fb[i]) {
+                       if (!flipdata->fb[crtc_id]) {
                                ErrorF("Failed to get FB for TearFree flip\n");
                                goto error;
                        }
@@ -4097,13 +4099,13 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
                                drmmode_crtc->scanout_update_pending = 0;
                        }
                } else {
-                       drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb[i], 
fb);
+                       drmmode_fb_reference(pAMDGPUEnt->fd, 
&flipdata->fb[crtc_id], fb);
                }
 
                if (crtc == ref_crtc) {
                        if (drmmode_page_flip_target_absolute(pAMDGPUEnt,
                                                              drmmode_crtc,
-                                                             
flipdata->fb[i]->handle,
+                                                             
flipdata->fb[crtc_id]->handle,
                                                              flip_flags,
                                                              drm_queue_seq,
                                                              target_msc) != 0)
@@ -4111,7 +4113,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
                } else {
                        if (drmmode_page_flip_target_relative(pAMDGPUEnt,
                                                              drmmode_crtc,
-                                                             
flipdata->fb[i]->handle,
+                                                             
flipdata->fb[crtc_id]->handle,
                                                              flip_flags,
                                                              drm_queue_seq, 0) 
!= 0)
                                goto flip_error;
@@ -4124,7 +4126,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
 
        next:
                drmmode_fb_reference(pAMDGPUEnt->fd, 
&drmmode_crtc->flip_pending,
-                                    flipdata->fb[i]);
+                                    flipdata->fb[crtc_id]);
                drm_queue_seq = 0;
        }
 
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to