Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2 drm: Rework attach/detach and deferred...
details: https://anonhg.NetBSD.org/src/rev/f93cb7aa355f
branches: trunk
changeset: 1028914:f93cb7aa355f
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 12:28:12 2021 +0000
description:
drm: Rework attach/detach and deferred task logic.
- Reduce the number of states the softc can be in.
- Fix races between attach and other threads.
diffstat:
sys/external/bsd/drm2/amdgpu/amdgpu_pci.c | 150 +++++++++------------
sys/external/bsd/drm2/i915drm/i915_pci_autoconf.c | 141 +++++++++----------
sys/external/bsd/drm2/nouveau/nouveau_pci.c | 151 +++++++++------------
sys/external/bsd/drm2/radeon/radeon_pci.c | 150 +++++++++------------
4 files changed, 270 insertions(+), 322 deletions(-)
diffs (truncated from 992 to 300 lines):
diff -r 50b0a8d2ecfe -r f93cb7aa355f sys/external/bsd/drm2/amdgpu/amdgpu_pci.c
--- a/sys/external/bsd/drm2/amdgpu/amdgpu_pci.c Sun Dec 19 12:28:04 2021 +0000
+++ b/sys/external/bsd/drm2/amdgpu/amdgpu_pci.c Sun Dec 19 12:28:12 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: amdgpu_pci.c,v 1.9 2021/12/19 12:21:29 riastradh Exp $ */
+/* $NetBSD: amdgpu_pci.c,v 1.10 2021/12/19 12:28:12 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,9 +30,10 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdgpu_pci.c,v 1.9 2021/12/19 12:21:29 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amdgpu_pci.c,v 1.10 2021/12/19 12:28:12 riastradh Exp $");
#include <sys/types.h>
+#include <sys/atomic.h>
#include <sys/queue.h>
#include <sys/systm.h>
#include <sys/workqueue.h>
@@ -57,14 +58,9 @@
struct amdgpu_softc {
device_t sc_dev;
struct pci_attach_args sc_pa;
- enum {
- AMDGPU_TASK_ATTACH,
- AMDGPU_TASK_WORKQUEUE,
- } sc_task_state;
- union {
- struct workqueue *workqueue;
- struct amdgpu_task_head attach;
- } sc_task_u;
+ struct lwp *sc_task_thread;
+ struct amdgpu_task_head sc_tasks;
+ struct workqueue *sc_task_wq;
struct drm_device *sc_drm_dev;
struct pci_dev sc_pci_dev;
bool sc_pci_attached;
@@ -135,20 +131,30 @@
{
struct amdgpu_softc *const sc = device_private(self);
const struct pci_attach_args *const pa = aux;
+ int error;
pci_aprint_devinfo(pa, NULL);
- if (!pmf_device_register(self, &amdgpu_do_suspend, &amdgpu_do_resume))
- aprint_error_dev(self, "unable to establish power handler\n");
+ /* Initialize the Linux PCI device descriptor. */
+ linux_pci_dev_init(&sc->sc_pci_dev, self, device_parent(self), pa, 0);
+
+ sc->sc_dev = self;
+ sc->sc_pa = *pa;
+ sc->sc_task_thread = NULL;
+ SIMPLEQ_INIT(&sc->sc_tasks);
+ error = workqueue_create(&sc->sc_task_wq, "amdgpufb",
+ &amdgpu_task_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE);
+ if (error) {
+ aprint_error_dev(self, "unable to create workqueue: %d\n",
+ error);
+ sc->sc_task_wq = NULL;
+ return;
+ }
/*
- * Trivial initialization first; the rest will come after we
- * have mounted the root file system and can load firmware
- * images.
+ * Defer the remainder of initialization until we have mounted
+ * the root file system and can load firmware images.
*/
- sc->sc_dev = NULL;
- sc->sc_pa = *pa;
-
config_mountroot(self, &amdgpu_attach_real);
}
@@ -164,11 +170,11 @@
ok = amdgpu_pci_lookup(pa, &flags);
KASSERT(ok);
- sc->sc_task_state = AMDGPU_TASK_ATTACH;
- SIMPLEQ_INIT(&sc->sc_task_u.attach);
-
- /* Initialize the Linux PCI device descriptor. */
- linux_pci_dev_init(&sc->sc_pci_dev, self, device_parent(self), pa, 0);
+ /*
+ * Cause any tasks issued synchronously during attach to be
+ * processed at the end of this function.
+ */
+ sc->sc_task_thread = curlwp;
sc->sc_drm_dev = drm_dev_alloc(amdgpu_drm_driver, self);
if (IS_ERR(sc->sc_drm_dev)) {
@@ -190,29 +196,29 @@
error = -drm_dev_register(sc->sc_drm_dev, flags);
if (error) {
aprint_error_dev(self, "unable to register drm: %d\n", error);
- return;
+ goto out;
}
sc->sc_dev_registered = true;
- while (!SIMPLEQ_EMPTY(&sc->sc_task_u.attach)) {
- struct amdgpu_task *const task =
- SIMPLEQ_FIRST(&sc->sc_task_u.attach);
+ if (!pmf_device_register(self, &amdgpu_do_suspend, &amdgpu_do_resume))
+ aprint_error_dev(self, "unable to establish power handler\n");
- SIMPLEQ_REMOVE_HEAD(&sc->sc_task_u.attach, rt_u.queue);
+ /*
+ * Process asynchronous tasks queued synchronously during
+ * attach. This will be for display detection to attach a
+ * framebuffer, so we have the opportunity for a console device
+ * to attach before autoconf has completed, in time for init(8)
+ * to find that console without panicking.
+ */
+ while (!SIMPLEQ_EMPTY(&sc->sc_tasks)) {
+ struct amdgpu_task *const task = SIMPLEQ_FIRST(&sc->sc_tasks);
+
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_tasks, rt_u.queue);
(*task->rt_fn)(task);
}
- sc->sc_task_state = AMDGPU_TASK_WORKQUEUE;
- error = workqueue_create(&sc->sc_task_u.workqueue, "amdgpufb",
- &amdgpu_task_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE);
- if (error) {
- aprint_error_dev(self, "unable to create workqueue: %d\n",
- error);
- sc->sc_task_u.workqueue = NULL;
- goto out;
- }
-
-out: sc->sc_dev = self;
+out: /* Cause any subesquent tasks to be processed by the workqueue. */
+ atomic_store_relaxed(&sc->sc_task_thread, NULL);
}
static int
@@ -221,35 +227,29 @@
struct amdgpu_softc *const sc = device_private(self);
int error;
- if (sc->sc_dev == NULL)
- /* Not done attaching. */
- return EBUSY;
-
/* XXX Check for in-use before tearing it all down... */
error = config_detach_children(self, flags);
if (error)
return error;
- if (sc->sc_task_state == AMDGPU_TASK_ATTACH)
- goto out0;
- if (sc->sc_task_u.workqueue != NULL) {
- workqueue_destroy(sc->sc_task_u.workqueue);
- sc->sc_task_u.workqueue = NULL;
- }
+ KASSERT(sc->sc_task_thread == NULL);
+ KASSERT(SIMPLEQ_EMPTY(&sc->sc_tasks));
- if (sc->sc_drm_dev == NULL)
- goto out1;
- if (!sc->sc_pci_attached)
- goto out2;
- if (!sc->sc_dev_registered)
- goto out3;
+ pmf_device_deregister(self);
+ if (sc->sc_dev_registered)
+ drm_dev_unregister(sc->sc_drm_dev);
+ if (sc->sc_pci_attached)
+ drm_pci_detach(sc->sc_drm_dev);
+ if (sc->sc_drm_dev) {
+ drm_dev_put(sc->sc_drm_dev);
+ sc->sc_drm_dev = NULL;
+ }
+ if (sc->sc_task_wq) {
+ workqueue_destroy(sc->sc_task_wq);
+ sc->sc_task_wq = NULL;
+ }
+ linux_pci_dev_destroy(&sc->sc_pci_dev);
- drm_dev_unregister(sc->sc_drm_dev);
-out3: drm_pci_detach(sc->sc_drm_dev);
-out2: drm_dev_put(sc->sc_drm_dev);
- sc->sc_drm_dev = NULL;
-out1: linux_pci_dev_destroy(&sc->sc_pci_dev);
-out0: pmf_device_deregister(self);
return 0;
}
@@ -260,9 +260,6 @@
struct drm_device *const dev = sc->sc_drm_dev;
int ret;
- if (dev == NULL)
- return true;
-
ret = amdgpu_device_suspend(dev, /*fbcon*/true);
if (ret)
return false;
@@ -277,9 +274,6 @@
struct drm_device *const dev = sc->sc_drm_dev;
int ret;
- if (dev == NULL)
- return true;
-
ret = amdgpu_device_resume(dev, /*fbcon*/true);
if (ret)
return false;
@@ -301,20 +295,10 @@
{
struct amdgpu_softc *const sc = device_private(self);
- switch (sc->sc_task_state) {
- case AMDGPU_TASK_ATTACH:
- SIMPLEQ_INSERT_TAIL(&sc->sc_task_u.attach, task, rt_u.queue);
- return 0;
- case AMDGPU_TASK_WORKQUEUE:
- if (sc->sc_task_u.workqueue == NULL) {
- aprint_error_dev(self, "unable to schedule task\n");
- return EIO;
- }
- workqueue_enqueue(sc->sc_task_u.workqueue, &task->rt_u.work,
- NULL);
- return 0;
- default:
- panic("amdgpu in invalid task state: %d\n",
- (int)sc->sc_task_state);
- }
+ if (atomic_load_relaxed(&sc->sc_task_thread) == curlwp)
+ SIMPLEQ_INSERT_TAIL(&sc->sc_tasks, task, rt_u.queue);
+ else
+ workqueue_enqueue(sc->sc_task_wq, &task->rt_u.work, NULL);
+
+ return 0;
}
diff -r 50b0a8d2ecfe -r f93cb7aa355f sys/external/bsd/drm2/i915drm/i915_pci_autoconf.c
--- a/sys/external/bsd/drm2/i915drm/i915_pci_autoconf.c Sun Dec 19 12:28:04 2021 +0000
+++ b/sys/external/bsd/drm2/i915drm/i915_pci_autoconf.c Sun Dec 19 12:28:12 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: i915_pci_autoconf.c,v 1.9 2021/12/19 11:54:10 riastradh Exp $ */
+/* $NetBSD: i915_pci_autoconf.c,v 1.10 2021/12/19 12:28:12 riastradh Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,9 +30,10 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i915_pci_autoconf.c,v 1.9 2021/12/19 11:54:10 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i915_pci_autoconf.c,v 1.10 2021/12/19 12:28:12 riastradh Exp $");
#include <sys/types.h>
+#include <sys/atomic.h>
#include <sys/queue.h>
#include <sys/systm.h>
#include <sys/queue.h>
@@ -50,18 +51,11 @@
struct i915drmkms_softc {
device_t sc_dev;
struct pci_attach_args sc_pa;
- enum {
- I915DRMKMS_TASK_ATTACH,
- I915DRMKMS_TASK_WORKQUEUE,
- } sc_task_state;
- union {
- struct workqueue *workqueue;
- struct i915drmkms_task_head attach;
- } sc_task_u;
+ struct lwp *sc_task_thread;
+ struct i915drmkms_task_head sc_tasks;
+ struct workqueue *sc_task_wq;
struct drm_device *sc_drm_dev;
struct pci_dev sc_pci_dev;
- bool sc_pci_attached;
- bool sc_dev_registered;
};
static const struct pci_device_id *
@@ -144,21 +138,30 @@
{
struct i915drmkms_softc *const sc = device_private(self);
const struct pci_attach_args *const pa = aux;
+ int error;
pci_aprint_devinfo(pa, NULL);
- if (!pmf_device_register(self, &i915drmkms_suspend,
- &i915drmkms_resume))
- aprint_error_dev(self, "unable to establish power handler\n");
+ /* Initialize the Linux PCI device descriptor. */
+ linux_pci_dev_init(&sc->sc_pci_dev, self, parent, pa, 0);
+
+ sc->sc_dev = self;
+ sc->sc_pa = *pa;
+ sc->sc_task_thread = NULL;
Home |
Main Index |
Thread Index |
Old Index