Hi,

Without the attached kernel patch(es), Xorg starts consuming alot of CPU and becomes very unresponsive and unusable.

Using ktrace reveals that X-org is issuing DRM_IOCTL_MODE_GETCONNECTOR over and over again with no apparent reason. It doesn't happen when using a simple window manager like blackbox. I was not able to use XFCE4 (9-stable userland) with 11-current kernel at all, after the latest DRM2 kernel updates. It worked fine before the update.

I'm not sure what is causing it. Going through the new DRM2 code revealed that a mode sorting function did not take all parameters like interlaced or not into account, causing the mode list to be reshuffelled every time a new mode scan was done. Not sure if Xorg cares about this though.

I can test patches if you have other suggestions.

--HPS

diff --git a/sys/dev/drm2/drm_crtc.c b/sys/dev/drm2/drm_crtc.c
index 318a764..d368e83 100644
--- a/sys/dev/drm2/drm_crtc.c
+++ b/sys/dev/drm2/drm_crtc.c
@@ -1499,15 +1499,18 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 		}
 	}
 
-	if (out_resp->count_modes == 0) {
+	list_for_each_entry(mode, &connector->modes, head)
+		mode_count++;
+
+	if (mode_count == 0) {
 		connector->funcs->fill_modes(connector,
 					     dev->mode_config.max_width,
 					     dev->mode_config.max_height);
-	}
 
-	/* delayed so we get modes regardless of pre-fill_modes state */
-	list_for_each_entry(mode, &connector->modes, head)
-		mode_count++;
+		/* delayed so we get modes regardless of pre-fill_modes state */
+		list_for_each_entry(mode, &connector->modes, head)
+			mode_count++;
+	}
 
 	out_resp->connector_id = connector->base.id;
 	out_resp->connector_type = connector->connector_type;
diff --git a/sys/dev/drm2/drm_modes.c b/sys/dev/drm2/drm_modes.c
index 4df8cb1..db06176 100644
--- a/sys/dev/drm2/drm_modes.c
+++ b/sys/dev/drm2/drm_modes.c
@@ -928,6 +928,10 @@ static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head
 	if (diff)
 		return diff;
 	diff = b->clock - a->clock;
+	if (diff)
+		return diff;
+	diff = ((b->flags & DRM_MODE_FLAG_INTERLACE) != 0) -
+		((a->flags & DRM_MODE_FLAG_INTERLACE) != 0);
 	return diff;
 }
 
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to