From: Keith Packard <kei...@keithp.com>

Signed-off-by: Keith Packard <kei...@keithp.com>
(Ported from xserver commit e4e3447603b5fd3a38a92c3f972396d1f81168ad)
Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
---
 configure.ac          |   2 +-
 src/amdgpu_kms.c      |   1 +
 src/drmmode_display.c | 159 +++++++++++++++++++++++++++++++++++++++++-
 src/drmmode_display.h |   6 ++
 4 files changed, 166 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index a475f3713..f4633e370 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,7 +70,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
 XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 
 # Checks for libraries.
-PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.78])
+PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.89])
 PKG_CHECK_MODULES(LIBDRM_AMDGPU, [libdrm_amdgpu >= 2.4.76])
 PKG_CHECK_MODULES(GBM, [gbm])
 
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index bedd02037..c357ab6b7 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -1703,6 +1703,7 @@ static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
        /* Clear mask of assigned crtc's in this generation */
        pAMDGPUEnt->assigned_crtcs = 0;
 
+       drmmode_terminate_leases(pScrn);
        drmmode_uevent_fini(pScrn, &info->drmmode);
        amdgpu_drm_queue_close(pScrn);
 
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 031d826af..fee6fedfb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2936,8 +2936,159 @@ fail:
        return FALSE;
 }
 
+static void
+drmmode_validate_leases(ScrnInfoPtr scrn)
+{
+#ifdef XF86_LEASE_VERSION
+       ScreenPtr screen = scrn->pScreen;
+       rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
+       AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+       drmModeLesseeListPtr lessees;
+       RRLeasePtr lease, next;
+       int l;
+
+       /* We can't talk to the kernel about leases when VT switched */
+       if (!scrn->vtSema)
+               return;
+
+       lessees = drmModeListLessees(pAMDGPUEnt->fd);
+       if (!lessees)
+               return;
+
+       xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) {
+               drmmode_lease_private_ptr lease_private = lease->devPrivate;
+
+               for (l = 0; l < lessees->count; l++) {
+                       if (lessees->lessees[l] == lease_private->lessee_id)
+                               break;
+               }
+
+               /* check to see if the lease has gone away */
+               if (l == lessees->count) {
+                       free(lease_private);
+                       lease->devPrivate = NULL;
+                       xf86CrtcLeaseTerminated(lease);
+               }
+       }
+
+       free(lessees);
+#endif
+}
+
+#ifdef XF86_LEASE_VERSION
+
+static int
+drmmode_create_lease(RRLeasePtr lease, int *fd)
+{
+       ScreenPtr screen = lease->screen;
+       ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+       AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+       drmmode_lease_private_ptr lease_private;
+       int noutput = lease->numOutputs;
+       int ncrtc = lease->numCrtcs;
+       uint32_t *objects;
+       size_t nobjects;
+       int lease_fd;
+       int c, o;
+       int i;
+
+       nobjects = ncrtc + noutput;
+       if (nobjects == 0 || nobjects > (SIZE_MAX / 4) ||
+           ncrtc > (SIZE_MAX - noutput))
+               return BadValue;
+
+       lease_private = calloc(1, sizeof (drmmode_lease_private_rec));
+       if (!lease_private)
+               return BadAlloc;
+
+       objects = malloc(nobjects * 4);
+       if (!objects) {
+               free(lease_private);
+               return BadAlloc;
+       }
+
+       i = 0;
+
+       /* Add CRTC ids */
+       for (c = 0; c < ncrtc; c++) {
+               xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate;
+               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+               objects[i++] = drmmode_crtc->mode_crtc->crtc_id;
+       }
+
+       /* Add connector ids */
+       for (o = 0; o < noutput; o++) {
+               xf86OutputPtr   output = lease->outputs[o]->devPrivate;
+               drmmode_output_private_ptr drmmode_output = 
output->driver_private;
+
+               objects[i++] = drmmode_output->mode_output->connector_id;
+       }
+
+       /* call kernel to create lease */
+       assert (i == nobjects);
+
+       lease_fd = drmModeCreateLease(pAMDGPUEnt->fd, objects, nobjects, 0,
+                                     &lease_private->lessee_id);
+
+       free(objects);
+
+       if (lease_fd < 0) {
+               free(lease_private);
+               return BadMatch;
+       }
+
+       lease->devPrivate = lease_private;
+
+       xf86CrtcLeaseStarted(lease);
+
+       *fd = lease_fd;
+       return Success;
+}
+
+static void
+drmmode_terminate_lease(RRLeasePtr lease)
+{
+       drmmode_lease_private_ptr lease_private = lease->devPrivate;
+       ScreenPtr screen = lease->screen;
+       ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+       AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+
+       if (drmModeRevokeLease(pAMDGPUEnt->fd, lease_private->lessee_id) == 0) {
+               free(lease_private);
+               lease->devPrivate = NULL;
+               xf86CrtcLeaseTerminated(lease);
+       }
+}
+
+#endif // XF86_LEASE_VERSION
+
+void
+drmmode_terminate_leases(ScrnInfoPtr pScrn)
+{
+#ifdef XF86_LEASE_VERSION
+       ScreenPtr screen = xf86ScrnToScreen(pScrn);
+       AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
+       rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
+       RRLeasePtr lease, next;
+
+       xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) {
+               drmmode_lease_private_ptr lease_private = lease->devPrivate;
+               drmModeRevokeLease(pAMDGPUEnt->fd, lease_private->lessee_id);
+               free(lease_private);
+               lease->devPrivate = NULL;
+               RRLeaseTerminated(lease);
+               RRLeaseFree(lease);
+       }
+#endif
+}
+
 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
-       drmmode_xf86crtc_resize
+       .resize = drmmode_xf86crtc_resize,
+#ifdef XF86_LEASE_VERSION
+       .create_lease = drmmode_create_lease,
+       .terminate_lease = drmmode_terminate_lease
+#endif
 };
 
 static void
@@ -3476,6 +3627,9 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, 
drmmode_ptr drmmode,
                return FALSE;
        }
 
+       /* Validate leases on VT re-entry */
+       drmmode_validate_leases(pScrn);
+
        return TRUE;
 }
 
@@ -3642,6 +3796,9 @@ restart_destroy:
                        changed = TRUE;
        }
 
+       /* Check to see if a lessee has disappeared */
+       drmmode_validate_leases(scrn);
+
        if (changed && dixPrivateKeyRegistered(rrPrivKey)) {
 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
                RRSetChanged(xf86ScrnToScreen(scrn));
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 0f0227c71..0646752c2 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -157,6 +157,10 @@ typedef struct {
        int tear_free;
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
+typedef struct {
+       uint32_t lessee_id;
+} drmmode_lease_private_rec, *drmmode_lease_private_ptr;
+
 
 enum drmmode_flip_sync {
     FLIP_VSYNC,
@@ -241,6 +245,8 @@ PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc,
 extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 
+extern void drmmode_terminate_leases(ScrnInfoPtr scrn);
+
 Bool drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb,
                      DisplayModePtr mode, int x, int y);
 
-- 
2.18.0

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

Reply via email to