aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-08-20 04:13:36 -0400
committerDave Airlie <airlied@redhat.com>2010-09-06 18:04:11 -0400
commite58f637bb96d5a0ae0919b9998b891d1ba7e47c9 (patch)
tree6c6e7d588c284f5fafce4782aad66e29f62359c9 /drivers/gpu
parent54bfe496cec7586f76f713a277435dd3ac6fd4c4 (diff)
drm/kms: Add a module parameter to disable polling
Polling for a VGA device on an old system can be quite expensive, causing latencies on the order of 600ms. As we hold the mode mutex for this time and also need the same mutex to move the cursor, we trigger a user-visible stall. The real solution would involve improving the granulatity of the locking and so perhaps performing some of the probing not under the lock or some other updates can be done under different locks. Also reducing the cost of probing for a non-existent monitor would be worthwhile. However, exposing a parameter to disable polling is a simple workaround in the meantime. In order to accommodate users turning polling on and off at runtime, the polling is potentially re-enabled on every probe. This is coupled to the user calling xrandr, which seems to be a vaild time to reset the polling timeout since the information on the connection has just been updated. (The presumption being that all connections are probed in a single xrandr pass, which is currently valid.) References: Bug 29536 - 2.6.35 causes ~600ms latency every 10s https://bugs.freedesktop.org/show_bug.cgi?id=29536 Bug 16265 - Why is kslowd accumulating so much CPU time? https://bugzilla.kernel.org/show_bug.cgi?id=16265 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reported-and-tested-by: Bruno Prémont <bonbons@linux-vserver.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 7e31d4348340..06fc0bccaff7 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -34,6 +34,9 @@
34#include "drm_crtc_helper.h" 34#include "drm_crtc_helper.h"
35#include "drm_fb_helper.h" 35#include "drm_fb_helper.h"
36 36
37static bool drm_kms_helper_poll = true;
38module_param_named(poll, drm_kms_helper_poll, bool, 0600);
39
37static void drm_mode_validate_flag(struct drm_connector *connector, 40static void drm_mode_validate_flag(struct drm_connector *connector,
38 int flags) 41 int flags)
39{ 42{
@@ -99,8 +102,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
99 connector->status = connector_status_disconnected; 102 connector->status = connector_status_disconnected;
100 if (connector->funcs->force) 103 if (connector->funcs->force)
101 connector->funcs->force(connector); 104 connector->funcs->force(connector);
102 } else 105 } else {
103 connector->status = connector->funcs->detect(connector); 106 connector->status = connector->funcs->detect(connector);
107 drm_helper_hpd_irq_event(dev);
108 }
104 109
105 if (connector->status == connector_status_disconnected) { 110 if (connector->status == connector_status_disconnected) {
106 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", 111 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
@@ -840,6 +845,9 @@ static void output_poll_execute(struct work_struct *work)
840 enum drm_connector_status old_status, status; 845 enum drm_connector_status old_status, status;
841 bool repoll = false, changed = false; 846 bool repoll = false, changed = false;
842 847
848 if (!drm_kms_helper_poll)
849 return;
850
843 mutex_lock(&dev->mode_config.mutex); 851 mutex_lock(&dev->mode_config.mutex);
844 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 852 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
845 853
@@ -890,6 +898,9 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
890 bool poll = false; 898 bool poll = false;
891 struct drm_connector *connector; 899 struct drm_connector *connector;
892 900
901 if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
902 return;
903
893 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 904 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
894 if (connector->polled) 905 if (connector->polled)
895 poll = true; 906 poll = true;
@@ -919,8 +930,10 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
919{ 930{
920 if (!dev->mode_config.poll_enabled) 931 if (!dev->mode_config.poll_enabled)
921 return; 932 return;
933
922 /* kill timer and schedule immediate execution, this doesn't block */ 934 /* kill timer and schedule immediate execution, this doesn't block */
923 cancel_delayed_work(&dev->mode_config.output_poll_work); 935 cancel_delayed_work(&dev->mode_config.output_poll_work);
924 queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); 936 if (drm_kms_helper_poll)
937 queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
925} 938}
926EXPORT_SYMBOL(drm_helper_hpd_irq_event); 939EXPORT_SYMBOL(drm_helper_hpd_irq_event);