All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH] drm: Avoid forcing a detection cycle following a hotplug event
Date: Wed,  5 Jun 2013 16:50:14 +0100	[thread overview]
Message-ID: <1370447414-30844-1-git-send-email-chris@chris-wilson.co.uk> (raw)

The typical procedure after a hotplug event is then to enumerate all the
new modes. In the existing code, this is achieved by performing a forced
detection cycle over all connectors. Ideally, we should just be able to
use the current detection status and only enumerate the modes on the
connectors that changed. This is a step in that direction by teaching
the hotplug path to only use the known detection status rather than
performing a second *forced* detection on every connector. As it
currently stands, the first thing userspace does upon receipt of a
hotplug uevent is call DRM_IOCTL_MODE_GETCONNECTOR on each connector,
which of course, performs another full detection cycle.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: dri-devel@lists.freedesktop.org
Cc: Jakob Bornecrantz <jakob@vmware.com>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Adam Jackson <ajax@redhat.com>
---
 drivers/gpu/drm/drm_crtc.c                    |    3 ++-
 drivers/gpu/drm/drm_crtc_helper.c             |    8 ++++++--
 drivers/gpu/drm/drm_fb_helper.c               |   14 ++++++++------
 drivers/gpu/drm/exynos/exynos_drm_connector.c |    7 ++++---
 drivers/gpu/drm/i2c/ch7006_drv.c              |    2 +-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c     |    2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c           |    3 ++-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h           |    3 ++-
 include/drm/drm_crtc.h                        |    2 +-
 include/drm/drm_crtc_helper.h                 |    2 +-
 10 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e7e9242..635276c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1537,7 +1537,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	if (out_resp->count_modes == 0) {
 		connector->funcs->fill_modes(connector,
 					     dev->mode_config.max_width,
-					     dev->mode_config.max_height);
+					     dev->mode_config.max_height,
+					     true);
 	}
 
 	/* delayed so we get modes regardless of pre-fill_modes state */
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ed1334e..7f2128c 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -96,6 +96,9 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
  * @connector: connector to probe
  * @maxX: max width for modes
  * @maxY: max height for modes
+ * @force: whether to use the cached connector status or to force a
+ *         fresh detection cycle, for instance after a hotplug event, we
+ *         want to simply use the known status.
  *
  * LOCKING:
  * Caller must hold mode config lock.
@@ -113,7 +116,8 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
  * Number of modes found on @connector.
  */
 int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
-					    uint32_t maxX, uint32_t maxY)
+					    uint32_t maxX, uint32_t maxY,
+					    bool force)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_display_mode *mode;
@@ -136,7 +140,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 			connector->status = connector_status_disconnected;
 		if (connector->funcs->force)
 			connector->funcs->force(connector);
-	} else {
+	} else if (force) {
 		connector->status = connector->funcs->detect(connector, true);
 	}
 
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b78cbe7..3e0802d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1087,8 +1087,8 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
 EXPORT_SYMBOL(drm_fb_helper_fill_var);
 
 static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
-					       uint32_t maxX,
-					       uint32_t maxY)
+					       uint32_t maxX, uint32_t maxY,
+					       bool force)
 {
 	struct drm_connector *connector;
 	int count = 0;
@@ -1096,7 +1096,7 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
 
 	for (i = 0; i < fb_helper->connector_count; i++) {
 		connector = fb_helper->connector_info[i]->connector;
-		count += connector->funcs->fill_modes(connector, maxX, maxY);
+		count += connector->funcs->fill_modes(connector, maxX, maxY, force);
 	}
 
 	return count;
@@ -1510,7 +1510,8 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 
 	count = drm_fb_helper_probe_connector_modes(fb_helper,
 						    dev->mode_config.max_width,
-						    dev->mode_config.max_height);
+						    dev->mode_config.max_height,
+						    true);
 	/*
 	 * we shouldn't end up with no modes here.
 	 */
@@ -1563,8 +1564,9 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 	max_height = fb_helper->fb->height;
 	bpp_sel = fb_helper->fb->bits_per_pixel;
 
-	count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
-						    max_height);
+	count = drm_fb_helper_probe_connector_modes(fb_helper,
+						    max_width, max_height,
+						    false);
 	mutex_unlock(&fb_helper->dev->mode_config.mutex);
 
 	drm_modeset_lock_all(dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 8bcc13a..48ef16f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -249,7 +249,8 @@ static void exynos_drm_connector_dpms(struct drm_connector *connector,
 }
 
 static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
-				unsigned int max_width, unsigned int max_height)
+				unsigned int max_width, unsigned int max_height,
+				bool force)
 {
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
@@ -267,8 +268,8 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 	if (ops && ops->get_max_resol)
 		ops->get_max_resol(manager->dev, &width, &height);
 
-	return drm_helper_probe_single_connector_modes(connector, width,
-							height);
+	return drm_helper_probe_single_connector_modes(connector,
+						       width, height, force);
 }
 
 /* get detection status of display device. */
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index 51fa323..d18237d 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -355,7 +355,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
 	}
 
 	if (modes_changed) {
-		drm_helper_probe_single_connector_modes(connector, 0, 0);
+		drm_helper_probe_single_connector_modes(connector, 0, 0, false);
 
 		/* Disable the crtc to ensure a full modeset is
 		 * performed whenever it's turned on again. */
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index acef48f..535dd14 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -759,7 +759,7 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
 	}
 
 	if (modes_changed) {
-		drm_helper_probe_single_connector_modes(connector, 0, 0);
+		drm_helper_probe_single_connector_modes(connector, 0, 0, false);
 
 		/* Disable the crtc to ensure a full modeset is
 		 * performed whenever it's turned on again. */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 3e3c7ab..d9a0768 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1924,7 +1924,8 @@ static void vmw_guess_mode_timing(struct drm_display_mode *mode)
 
 
 int vmw_du_connector_fill_modes(struct drm_connector *connector,
-				uint32_t max_width, uint32_t max_height)
+				uint32_t max_width, uint32_t max_height,
+				bool force)
 {
 	struct vmw_display_unit *du = vmw_connector_to_du(connector);
 	struct drm_device *dev = connector->dev;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 6fa89c9..19fc306 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -138,7 +138,8 @@ void vmw_du_connector_restore(struct drm_connector *connector);
 enum drm_connector_status
 vmw_du_connector_detect(struct drm_connector *connector, bool force);
 int vmw_du_connector_fill_modes(struct drm_connector *connector,
-				uint32_t max_width, uint32_t max_height);
+				uint32_t max_width, uint32_t max_height,
+				bool force);
 int vmw_du_connector_set_property(struct drm_connector *connector,
 				  struct drm_property *property,
 				  uint64_t val);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index adb3f9b..373e774 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -468,7 +468,7 @@ struct drm_connector_funcs {
 	 */
 	enum drm_connector_status (*detect)(struct drm_connector *connector,
 					    bool force);
-	int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
+	int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height, bool force);
 	int (*set_property)(struct drm_connector *connector, struct drm_property *property,
 			     uint64_t val);
 	void (*destroy)(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index f43d556..cce7221 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -125,7 +125,7 @@ struct drm_connector_helper_funcs {
 	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
 };
 
-extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
+extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY, bool force);
 extern void drm_helper_disable_unused_functions(struct drm_device *dev);
 extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
 extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
-- 
1.7.10.4

             reply	other threads:[~2013-06-05 15:50 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-05 15:50 Chris Wilson [this message]
2013-06-08  7:28 ` [PATCH] drm: Avoid forcing a detection cycle following a hotplug event Laurent Pinchart
2013-06-08  7:53   ` Chris Wilson
2013-06-18 22:37     ` Laurent Pinchart
2013-06-08 13:30 ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1370447414-30844-1-git-send-email-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.