NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/49645: radeon pmf hooks



>Number:         49645
>Category:       kern
>Synopsis:       radeon pmf hooks
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 05 18:15:00 +0000 2015
>Originator:     Arto Huusko
>Release:        7.99.4
>Organization:
>Environment:
7.99.4 amd64 GENERIC
>Description:
The radeon kms driver does not support suspend/resume.
>How-To-Repeat:
sysctl -w hw.acpi.sleep.state=3
...
the following drivers do not support: radeon
...
>Fix:
The following patch worked for me with vendor 1002, product 9612, or
drm: initializing kernel modesetting (RS780 0x1002:0x9612 0x1025:0x0148)

Did not try with X11 yet, but suspend/resume worked from console.

--- sys/external/bsd/drm2/radeon/radeon_pci.c
+++ sys/external/bsd/drm2/radeon/radeon_pci.c
@@ -100,6 +100,9 @@ static void	radeon_attach(device_t, device_t, void *);
 static void	radeon_attach_real(device_t);
 static int	radeon_detach(device_t, int);
 
+static bool	radeon_pmf_suspend(device_t, const pmf_qual_t *);
+static bool	radeon_pmf_resume(device_t, const pmf_qual_t *);
+
 static void	radeon_task_work(struct work *, void *);
 
 CFATTACH_DECL_NEW(radeon, sizeof(struct radeon_softc),
@@ -157,6 +160,9 @@ radeon_attach(device_t parent, device_t self, void *aux)
 
 	pci_aprint_devinfo(pa, NULL);
 
+	if (!pmf_device_register(self, &radeon_pmf_suspend, &radeon_pmf_resume))
+		aprint_error_dev(self, "unable to establish power handler\n");
+
 	/*
 	 * Trivial initialization first; the rest will come after we
 	 * have mounted the root file system and can load firmware
@@ -228,14 +234,14 @@ radeon_detach(device_t self, int flags)
 		return error;
 
 	if (sc->sc_task_state == RADEON_TASK_ATTACH)
-		return 0;
+        goto out;
 	if (sc->sc_task_u.workqueue != NULL) {
 		workqueue_destroy(sc->sc_task_u.workqueue);
 		sc->sc_task_u.workqueue = NULL;
 	}
 
 	if (sc->sc_drm_dev == NULL)
-		return 0;
+		goto out;
 	/* XXX errno Linux->NetBSD */
 	error = -drm_pci_detach(sc->sc_drm_dev, flags);
 	if (error)
@@ -243,9 +249,45 @@ radeon_detach(device_t self, int flags)
 		return error;
 	sc->sc_drm_dev = NULL;
 
+out:	pmf_device_deregister(self);
+
 	return 0;
 }
 
+static bool
+radeon_pmf_suspend(device_t self, const pmf_qual_t *qual)
+{
+	struct radeon_softc *const sc = device_private(self);
+	struct drm_device *const dev = sc->sc_drm_dev;
+	int ret;
+
+	if (dev == NULL)
+		return true;
+
+	ret = radeon_suspend_kms(dev, true, true);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+static bool
+radeon_pmf_resume(device_t self, const pmf_qual_t *qual)
+{
+	struct radeon_softc *const sc = device_private(self);
+	struct drm_device *const dev = sc->sc_drm_dev;
+	int ret;
+
+	if (dev == NULL)
+		return true;
+
+	ret = radeon_resume_kms(dev, false, true);
+	if (ret)
+		return false;
+
+	return true;
+}
+
 static void
 radeon_task_work(struct work *work, void *cookie __unused)
 {



Home | Main Index | Thread Index | Old Index