>From dfe256fc9d28f240f1a84fb4c3dfed4a4e18d5d4 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven <ar...@linux.intel.com> Date: Mon, 23 Mar 2009 13:32:47 -0700 Subject: [PATCH] KMS: Do the actual mode setting from asynchronous context
The mode setting (and the expensive part of mode detection) can take quite a bit of time, and will delay the kernel boot quite a bit. This patch puts these two parts into async context, so that the normal execution of the system continues while the slow hardware probing and poking happens. Signed-off-by: Arjan van de Ven <ar...@linux.intel.com> --- drivers/gpu/drm/drm_crtc_helper.c | 50 ++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/drm_drv.c | 4 +++ include/drm/drmP.h | 1 + 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 1c3a8c5..7aa3107 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -29,6 +29,8 @@ * Jesse Barnes <jesse.bar...@intel.com> */ +#include <linux/async.h> + #include "drmP.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" @@ -42,6 +44,8 @@ static struct drm_display_mode std_modes[] = { DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, }; +LIST_HEAD(drm_async_list); + /** * drm_helper_probe_connector_modes - get complete set of display modes * @dev: DRM device @@ -137,6 +141,26 @@ int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, } EXPORT_SYMBOL(drm_helper_probe_connector_modes); +int drm_helper_probe_connector_modes_fast(struct drm_device *dev, uint32_t maxX, + uint32_t maxY) +{ + struct drm_connector *connector; + int count = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + count += drm_helper_probe_single_connector_modes(connector, + maxX, maxY); + /* + * If we found a 'good' connector, we stop probing futher. + */ + if (count > 0) + break; + } + + return count; +} +EXPORT_SYMBOL(drm_helper_probe_connector_modes_fast); + static void drm_helper_add_std_modes(struct drm_device *dev, struct drm_connector *connector) { @@ -882,6 +906,24 @@ bool drm_helper_plugged_event(struct drm_device *dev) /* FIXME: send hotplug event */ return true; } + +static void async_notify_fb_changed(void *data, async_cookie_t cookie) +{ + struct drm_device *dev = data; + /* Need to wait for async_probe_hard be done */ + async_synchronize_cookie_domain(cookie, &drm_async_list); + dev->mode_config.funcs->fb_changed(dev); +} + +static void async_probe_hard(void *data, async_cookie_t cookie) +{ + struct drm_device *dev = data; + drm_helper_probe_connector_modes(dev, + dev->mode_config.max_width, + dev->mode_config.max_height); +} + + /** * drm_initial_config - setup a sane initial connector configuration * @dev: DRM device @@ -902,7 +944,7 @@ bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) struct drm_connector *connector; int count = 0; - count = drm_helper_probe_connector_modes(dev, + count = drm_helper_probe_connector_modes_fast(dev, dev->mode_config.max_width, dev->mode_config.max_height); @@ -920,8 +962,10 @@ bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) drm_setup_crtcs(dev); - /* alert the driver fb layer */ - dev->mode_config.funcs->fb_changed(dev); + /* probe further outputs asynchronously */ + async_schedule_domain(async_probe_hard, dev, &drm_async_list); + /* alert the driver fb layer to actually change the mode */ + async_schedule_domain(async_notify_fb_changed, dev, &drm_async_list); return 0; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 14c7a23..ef52021 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -48,6 +48,7 @@ #include "drmP.h" #include "drm_core.h" +#include <linux/async.h> static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -345,6 +346,9 @@ void drm_exit(struct drm_driver *driver) struct drm_device *dev, *tmp; DRM_DEBUG("\n"); + /* make sure all async DRM operations are finished */ + async_synchronize_full_domain(&drm_async_list); + list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) drm_cleanup(dev); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e5f4ae9..69ce4f4 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -304,6 +304,7 @@ struct drm_vma_entry { pid_t pid; }; +extern struct list_head drm_async_list; /** * DMA buffer. */ -- 1.6.0.6 -- Arjan van de Ven Intel Open Source Technology Centre For development, discussion and tips for power savings, visit http://www.lesswatts.org ------------------------------------------------------------------------------ Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are powering Web 2.0 with engaging, cross-platform capabilities. Quickly and easily build your RIAs with Flex Builder, the Eclipse(TM)based development software that enables intelligent coding and step-through debugging. Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel