>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

Reply via email to