xf86-video-amdgpu: Branch 'master' - 3 commits

Keith Packard keithp at kemper.freedesktop.org
Fri Jul 6 23:17:20 UTC 2018


 configure.ac          |   12 +++
 src/amdgpu_kms.c      |    2 
 src/drmmode_display.c |  177 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/drmmode_display.h |    5 +
 4 files changed, 195 insertions(+), 1 deletion(-)

New commits:
commit 9dd66a9949175205498e4742512a1744e23a9259
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 12 13:51:56 2018 -0800

    Add RandR leases with modesetting driver support [v6]
    
    This adds support for RandR CRTC/Output leases through the modesetting
    driver, creating a lease using new kernel infrastructure and returning
    that to a client through an fd which will have access to only those
    resources.
    
    v2:     Restore CRTC mode when leases terminate
    
            When a lease terminates for a crtc we have saved data for, go
            ahead and restore the saved mode.
    
    v3:     Report RR_Rotate_0 rotations for leased crtcs.
    
            Ignore leased CRTCs when selecting screen size.
    
            Stop leasing encoders, the kernel doesn't do that anymore.
    
            Turn off crtc->enabled while leased so that modesetting
            ignores them.
    
            Check lease status before calling any driver mode functions
    
            When starting a lease, mark leased CRTCs as disabled and hide
            their cursors. Also, check to see if there are other
            non-leased CRTCs which are driving leased Outputs and mark
            them as disabled as well. Sometimes an application will lease
            an idle crtc instead of the one already associated with the
            leased output.
    
            When terminating a lease, reset any CRTCs which are driving
            outputs that are no longer leased so that they start working
            again.
    
            This required splitting the DIX level lease termination code
            into two pieces, one to remove the lease from the system
            (RRLeaseTerminated) and a new function that frees the lease
            data structure (RRLeaseFree).
    
    v4:     Report RR_Rotate_0 rotation for leased crtcs.
    
    v5: Terminate all leases on server reset.
    
            Leases hang around after the associated client exits so that
            the client doesn't need to occupy an X server client slot and
            consume a file descriptor once it has gotten the output
            resources necessary.
    
            Any leases still hanging around when the X server resets or
            shuts down need to be cleaned up by calling the kernel to
            terminate the lease and freeing any DIX structures.
    
            Note that we cannot simply use the existing
            drmmode_terminate_lease function on each lease as that wants
            to also reset the video mode, and during server shut down that
    
       modesetting: Validate leases on VT enter
    
            The kernel doesn't allow any master ioctls to run when another
            VT is active, including simple things like listing the active
            leases. To deal with that, we check the list of leases
            whenever the X server VT is activated.
    
       xfree86: hide disabled cursors when resetting after lease termination
    
            The lessee may well have played with cursors and left one
            active on our screen. Just tell the kernel to turn it off.
    
    v6:     Add meson build infrastructure
    
    [Also bumped libdrm requirement - ajax]
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index 2593f52..2d5ac07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,14 @@ if test "x$GCC" = "xyes"; then
 	CPPFLAGS="$CPPFLAGS -Wall"
 fi
 
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <features.h>
+#ifndef __GLIBC__
+#error not glibc
+#endif
+]], [])], [AC_DEFINE(_GNU_SOURCE, 1,
+	[ Enable GNU and other extensions to the C environment for glibc])])
+
 AH_TOP([#include "xorg-server.h"])
 
 # Define a configure option for an alternate module directory
@@ -203,6 +211,8 @@ AC_CHECK_HEADERS([dri3.h], [], [],
 
 CPPFLAGS="$SAVE_CPPFLAGS"
 
+AC_CHECK_LIB([bsd], [arc4random_buf])
+
 # Checks for headers/macros for byte swapping
 # Known variants:
 #	<byteswap.h> bswap_16, bswap_32, bswap_64  (glibc)
@@ -213,6 +223,8 @@ CPPFLAGS="$SAVE_CPPFLAGS"
 # if <byteswap.h> is found, assume it's the correct version
 AC_CHECK_HEADERS([byteswap.h])
 
+AC_REPLACE_FUNCS([reallocarray])
+
 # if <sys/endian.h> is found, have to check which version
 AC_CHECK_HEADER([sys/endian.h], [HAVE_SYS_ENDIAN_H="yes"], [HAVE_SYS_ENDIAN_H="no"])
 
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index bedd020..1ac44ad 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -1703,6 +1703,8 @@ static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
 	/* Clear mask of assigned crtc's in this generation */
 	pAMDGPUEnt->assigned_crtcs = 0;
 
+	drmmode_terminate_leases(pScrn, &info->drmmode);
+
 	drmmode_uevent_fini(pScrn, &info->drmmode);
 	amdgpu_drm_queue_close(pScrn);
 
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 5e543aa..c8214b9 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2928,8 +2928,150 @@ fail:
 	return FALSE;
 }
 
+static void
+drmmode_validate_leases(ScrnInfoPtr scrn)
+{
+	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);
+}
+
+static int
+drmmode_create_lease(RRLeasePtr lease, int *fd)
+{
+	ScreenPtr screen = lease->screen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	int ncrtc = lease->numCrtcs;
+	int noutput = lease->numOutputs;
+	int nobjects;
+	int c, o;
+	int i;
+	int lease_fd;
+	uint32_t *objects;
+	drmmode_lease_private_ptr   lease_private;
+
+	nobjects = ncrtc + noutput;
+
+	if (nobjects == 0)
+		return BadValue;
+
+	lease_private = calloc(1, sizeof (drmmode_lease_private_rec));
+	if (!lease_private)
+		return BadAlloc;
+
+	objects = xallocarray(nobjects, sizeof (uint32_t));
+
+	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)
+{
+	ScreenPtr screen = lease->screen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	drmmode_lease_private_ptr lease_private = lease->devPrivate;
+
+	if (drmModeRevokeLease(pAMDGPUEnt->fd, lease_private->lessee_id) == 0) {
+		free(lease_private);
+		lease->devPrivate = NULL;
+		xf86CrtcLeaseTerminated(lease);
+	}
+}
+
+void
+drmmode_terminate_leases(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	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);
+	}
+}
+
 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
-	drmmode_xf86crtc_resize
+	.resize = drmmode_xf86crtc_resize,
+	.create_lease = drmmode_create_lease,
+	.terminate_lease = drmmode_terminate_lease
 };
 
 static void
@@ -3634,6 +3776,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 0f0227c..48e6876 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -157,6 +157,9 @@ 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 +244,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, drmmode_ptr drmmode);
+
 Bool drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb,
 		      DisplayModePtr mode, int x, int y);
 
commit c4a1a7d98966266bc7f9f39becd3e9431351bb66
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 12 13:51:55 2018 -0800

    xf86-video-modesetting: Create CONNECTOR_ID properties for outputs [v2]
    
    This lets a DRM client map between X outputs and kernel connectors.
    
    v2:
            Change CONNECTOR_ID to enum -- Adam Jackson <ajax at nwnk.net>
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at nwnk.net>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9b8eb35..5e543aa 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2229,6 +2229,29 @@ static void drmmode_output_create_resources(xf86OutputPtr output)
 	drmmode_output->tear_free = info->tear_free;
 	drmmode_output->num_props++;
 
+	/* Create CONNECTOR_ID property */
+	{
+		Atom    name = MakeAtom("CONNECTOR_ID", 12, TRUE);
+		INT32   value = mode_output->connector_id;
+
+		if (name != BAD_RESOURCE) {
+			err = RRConfigureOutputProperty(output->randr_output, name,
+							FALSE, FALSE, TRUE,
+							1, &value);
+			if (err != 0) {
+				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+					   "RRConfigureOutputProperty error, %d\n", err);
+			}
+			err = RRChangeOutputProperty(output->randr_output, name,
+						     XA_INTEGER, 32, PropModeReplace, 1,
+						     &value, FALSE, FALSE);
+			if (err != 0) {
+				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+					   "RRChangeOutputProperty error, %d\n", err);
+			}
+		}
+	}
+
 	for (i = 0; i < drmmode_output->num_props; i++) {
 		drmmode_prop_ptr p = &drmmode_output->props[i];
 		drmmode_prop = p->mode_prop;
commit 1e040bcc0a945f1d1265217fc8d63e1ee13e63ab
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 12 13:51:53 2018 -0800

    xf86-video-modesetting: Record non-desktop kernel property at PreInit time
    
    Save any value of the kernel non-desktop property in the xf86Output
    structure to avoid non-desktop outputs in the default configuration.
    
    [Also bump randrproto requirement to a version that defines
    RR_PROPERTY_NON_DESKTOP - ajax]
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at nwnk.net>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9364a88..9b8eb35 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2597,6 +2597,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 	drmModePropertyBlobPtr path_blob = NULL;
 	char name[32];
 	int i;
+	Bool nonDesktop = FALSE;
 	const char *s;
 
 	koutput =
@@ -2606,6 +2607,10 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 		return 0;
 
 	path_blob = koutput_get_prop_blob(pAMDGPUEnt->fd, koutput, "PATH");
+	i = koutput_get_prop_idx(pAMDGPUEnt->fd, koutput, DRM_MODE_PROP_RANGE, RR_PROPERTY_NON_DESKTOP);
+	if (i >= 0)
+		nonDesktop = koutput->prop_values[i] != 0;
+
 
 	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
 	if (!kencoders) {
@@ -2638,6 +2643,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 			drmmode_output = output->driver_private;
 			drmmode_output->output_id = mode_res->connectors[num];
 			drmmode_output->mode_output = koutput;
+			output->non_desktop = nonDesktop;
 			for (i = 0; i < koutput->count_encoders; i++) {
 				drmModeFreeEncoder(kencoders[i]);
 			}
@@ -2681,6 +2687,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 	output->interlaceAllowed = TRUE;
 	output->doubleScanAllowed = TRUE;
 	output->driver_private = drmmode_output;
+	output->non_desktop = nonDesktop;
 
 	output->possible_crtcs = 0xffffffff;
 	for (i = 0; i < koutput->count_encoders; i++) {


More information about the xorg-commit mailing list