summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-09-28 17:29:57 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-09-28 17:29:57 +0000
commit581ca1c68542b0da7cc84c10d30e5da60df1a4b2 (patch)
tree64f80842a796d7eb396dad596981f5695a3f506e
parent1dfa6daa1e242f5ab4c1bf7ed4526803ef098402 (diff)
The Linux code that handles the DPMS mode for inteldrm(4) can sleep now.
Adopt the approach taken by radeondrm(4) and hand the "burner" work off to a task. Avoids the panic reported by Gerald Hanuer, who also tested this fix.
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c29
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.h5
2 files changed, 26 insertions, 8 deletions
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 1f70e0a123a..fc84f332489 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.92 2015/09/28 06:47:23 kettenis Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.93 2015/09/28 17:29:56 kettenis Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -966,6 +966,7 @@ int inteldrm_load_font(void *, void *, struct wsdisplay_font *);
int inteldrm_list_font(void *, struct wsdisplay_font *);
int inteldrm_getchar(void *, int, int, struct wsdisplay_charcell *);
void inteldrm_burner(void *, u_int, u_int);
+void inteldrm_burner_cb(void *);
struct wsscreen_descr inteldrm_stdscreen = {
"std",
@@ -1140,19 +1141,32 @@ void
inteldrm_burner(void *v, u_int on, u_int flags)
{
struct inteldrm_softc *dev_priv = v;
- struct drm_fb_helper *helper = &dev_priv->fbdev->helper;
- int dpms_mode;
+
+ task_del(systq, &dev_priv->burner_task);
if (on)
- dpms_mode = DRM_MODE_DPMS_ON;
+ dev_priv->burner_dpms_mode = DRM_MODE_DPMS_ON;
else {
if (flags & WSDISPLAY_BURN_VBLANK)
- dpms_mode = DRM_MODE_DPMS_OFF;
+ dev_priv->burner_dpms_mode = DRM_MODE_DPMS_OFF;
else
- dpms_mode = DRM_MODE_DPMS_STANDBY;
+ dev_priv->burner_dpms_mode = DRM_MODE_DPMS_STANDBY;
}
- drm_fb_helper_dpms(helper, dpms_mode);
+ /*
+ * Setting the DPMS mode may sleep while waiting for the display
+ * to come back on so hand things off to a taskq.
+ */
+ task_add(systq, &dev_priv->burner_task);
+}
+
+void
+inteldrm_burner_cb(void *arg1)
+{
+ struct inteldrm_softc *dev_priv = arg1;
+ struct drm_fb_helper *helper = &dev_priv->fbdev->helper;
+
+ drm_fb_helper_dpms(helper, dev_priv->burner_dpms_mode);
}
int
@@ -1448,6 +1462,7 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
rasops_init(ri, 160, 160);
task_set(&dev_priv->switchtask, inteldrm_doswitch, dev_priv);
+ task_set(&dev_priv->burner_task, inteldrm_burner_cb, dev_priv);
inteldrm_stdscreen.capabilities = ri->ri_caps;
inteldrm_stdscreen.nrows = ri->ri_rows;
diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h
index da813eef5c8..a0241012474 100644
--- a/sys/dev/pci/drm/i915/i915_drv.h
+++ b/sys/dev/pci/drm/i915/i915_drv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.h,v 1.68 2015/09/26 11:17:15 kettenis Exp $ */
+/* $OpenBSD: i915_drv.h,v 1.69 2015/09/28 17:29:56 kettenis Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/*
@@ -1466,6 +1466,9 @@ typedef struct inteldrm_softc {
struct task switchtask;
struct rasops_info ro;
+ struct task burner_task;
+ int burner_dpms_mode;
+
struct backlight_device {
struct intel_connector *connector;
struct {