Hi Chris, Thanks for the patch.
On Wednesday 05 June 2013 16:50:14 Chris Wilson wrote: > 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 at chris-wilson.co.uk> > Cc: dri-devel at lists.freedesktop.org > Cc: Jakob Bornecrantz <jakob at vmware.com> > Cc: Inki Dae <inki.dae at samsung.com> > Cc: Adam Jackson <ajax at 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 +- Could you please also update Documentation/DocBook/drm.tmpl ? > 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, -- Regards, Laurent Pinchart