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 New macro DRM_SPIN_WAIT_ON better refl...
details: https://anonhg.NetBSD.org/src/rev/940bf003bc1f
branches: trunk
changeset: 806554:940bf003bc1f
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sat Feb 28 18:25:39 2015 +0000
description:
New macro DRM_SPIN_WAIT_ON better reflects DRM_WAIT_ON.
We still need to adapt all waits from upstream to use an interlock,
so we can't implement DRM_WAIT_ON verbatim, but this more closely
reflects the API of DRM_WAIT_ON than DRM_*WAIT*_UNTIL do.
Major difference is that this polls every tick, like DRM_WAIT_ON,
unlike DRM_*WAIT*_UNTIL. So it will mask missing wakeups, but it
wouldn't surprise me if there were such things upstream.
diffstat:
sys/external/bsd/drm2/dist/drm/drm_irq.c | 12 +-
sys/external/bsd/drm2/dist/drm/i915/i915_dma.c | 9 +-
sys/external/bsd/drm2/dist/drm/via/via_dmablit.c | 19 +---
sys/external/bsd/drm2/dist/drm/via/via_drv.h | 2 +-
sys/external/bsd/drm2/dist/drm/via/via_irq.c | 14 +--
sys/external/bsd/drm2/dist/drm/via/via_video.c | 22 +--
sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h | 100 +++++++++++++------
7 files changed, 88 insertions(+), 90 deletions(-)
diffs (truncated from 314 to 300 lines):
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/drm_irq.c
--- a/sys/external/bsd/drm2/dist/drm/drm_irq.c Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/drm_irq.c Sat Feb 28 18:25:39 2015 +0000
@@ -1293,20 +1293,14 @@
#ifdef __NetBSD__
{
unsigned long irqflags;
+
spin_lock_irqsave(&dev->vbl_lock, irqflags);
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev->vblank[crtc].queue,
- &dev->vbl_lock,
- (3 * HZ),
+ DRM_SPIN_WAIT_ON(ret, &dev->vblank[crtc].queue, &dev->vbl_lock,
+ 3 * HZ,
(((drm_vblank_count(dev, crtc) -
vblwait->request.sequence) <= (1 << 23)) ||
!dev->irq_enabled));
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- if (ret < 0) /* Failed: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Succeeded (ret > 0): return 0. */
- ret = 0;
}
#else
DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ,
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/i915/i915_dma.c
--- a/sys/external/bsd/drm2/dist/drm/i915/i915_dma.c Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/i915/i915_dma.c Sat Feb 28 18:25:39 2015 +0000
@@ -812,16 +812,9 @@
#ifdef __NetBSD__
unsigned long flags;
spin_lock_irqsave(&dev_priv->irq_lock, flags);
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, &ring->irq_queue,
- &dev_priv->irq_lock,
+ DRM_SPIN_WAIT_ON(ret, &ring->irq_queue, &dev_priv->irq_lock,
3 * DRM_HZ,
READ_BREADCRUMB(dev_priv) >= irq_nr);
- if (ret < 0) /* Failure: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Succeeded (ret > 0): return 0. */
- ret = 0;
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
#else
DRM_WAIT_ON(ret, ring->irq_queue, 3 * HZ,
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/via/via_dmablit.c
--- a/sys/external/bsd/drm2/dist/drm/via/via_dmablit.c Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/via/via_dmablit.c Sat Feb 28 18:25:39 2015 +0000
@@ -597,15 +597,8 @@
#ifdef __NetBSD__
spin_lock(&blitq->blit_lock);
if (via_dmablit_active(blitq, engine, handle, &queue)) {
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, queue, &blitq->blit_lock,
- 3*DRM_HZ,
+ DRM_SPIN_WAIT_ON(ret, queue, &blitq->blit_lock, 3*DRM_HZ,
!via_dmablit_active(blitq, engine, handle, NULL));
- if (ret < 0) /* Failure: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Succeeded (ret > 0): return 0. */
- ret = 0;
}
spin_unlock(&blitq->blit_lock);
#else
@@ -881,15 +874,9 @@
spin_lock_irqsave(&blitq->blit_lock, irqsave);
while (blitq->num_free == 0) {
#ifdef __NetBSD__
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, &blitq->busy_queue,
- &blitq->blit_lock, DRM_HZ,
+ DRM_SPIN_WAIT_ON(ret, &blitq->busy_queue, &blitq->blit_lock,
+ DRM_HZ,
blitq->num_free > 0);
- if (ret < 0) /* Failure: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Success (ret > 0): return 0. */
- ret = 0;
/* Map -EINTR to -EAGAIN. */
if (ret == -EINTR)
ret = -EAGAIN;
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/via/via_drv.h
--- a/sys/external/bsd/drm2/dist/drm/via/via_drv.h Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/via/via_drv.h Sat Feb 28 18:25:39 2015 +0000
@@ -73,7 +73,7 @@
drm_local_map_t *mmio;
unsigned long agpAddr;
#ifdef __NetBSD__
- struct mutex decoder_lock[VIA_NR_XVMC_LOCKS];
+ spinlock_t decoder_lock[VIA_NR_XVMC_LOCKS];
drm_waitqueue_t decoder_queue[VIA_NR_XVMC_LOCKS];
#else
wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/via/via_irq.c
--- a/sys/external/bsd/drm2/dist/drm/via/via_irq.c Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/via/via_irq.c Sat Feb 28 18:25:39 2015 +0000
@@ -249,23 +249,17 @@
#ifdef __NetBSD__
spin_lock(&cur_irq->irq_lock);
if (masks[real_irq][2] && !force_sequence) {
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, &cur_irq->irq_queue,
- &cur_irq->irq_lock, 3 * DRM_HZ,
+ DRM_SPIN_WAIT_ON(ret, &cur_irq->irq_queue, &cur_irq->irq_lock,
+ 3 * DRM_HZ,
((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
masks[irq][4]));
cur_irq_sequence = cur_irq->irq_received;
} else {
- DRM_SPIN_TIMED_WAIT_UNTIL(ret, &cur_irq->irq_queue,
- &cur_irq->irq_lock, 3 * DRM_HZ,
+ DRM_SPIN_WAIT_ON(ret, &cur_irq->irq_queue, &cur_irq->irq_lock,
+ 3 * DRM_HZ,
(((cur_irq_sequence = cur_irq->irq_received) -
*sequence) <= (1 << 23)));
}
- if (ret < 0) /* Failure: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Success (ret > 0): return 0. */
- ret = 0;
spin_unlock(&cur_irq->irq_lock);
#else
if (masks[real_irq][2] && !force_sequence) {
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/dist/drm/via/via_video.c
--- a/sys/external/bsd/drm2/dist/drm/via/via_video.c Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/dist/drm/via/via_video.c Sat Feb 28 18:25:39 2015 +0000
@@ -37,7 +37,7 @@
for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
#ifdef __NetBSD__
- linux_mutex_init(&dev_priv->decoder_lock[i]);
+ spin_lock_init(&dev_priv->decoder_lock[i]);
DRM_INIT_WAITQUEUE(&dev_priv->decoder_queue[i], "viadec");
#else
init_waitqueue_head(&(dev_priv->decoder_queue[i]));
@@ -53,7 +53,7 @@
for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
DRM_DESTROY_WAITQUEUE(&dev_priv->decoder_queue[i]);
- linux_mutex_destroy(&dev_priv->decoder_lock[i]);
+ spin_lock_destroy(&dev_priv->decoder_lock[i]);
}
#endif
}
@@ -72,10 +72,10 @@
if (_DRM_LOCK_IS_HELD(*lock)
&& (*lock & _DRM_LOCK_CONT)) {
#ifdef __NetBSD__
- mutex_lock(&dev_priv->decoder_lock[i]);
- DRM_WAKEUP_ALL(&dev_priv->decoder_queue[i],
+ spin_lock(&dev_priv->decoder_lock[i]);
+ DRM_SPIN_WAKEUP_ALL(&dev_priv->decoder_queue[i],
&dev_priv->decoder_lock[i]);
- mutex_unlock(&dev_priv->decoder_lock[i]);
+ spin_unlock(&dev_priv->decoder_lock[i]);
#else
wake_up(&(dev_priv->decoder_queue[i]));
#endif
@@ -103,18 +103,12 @@
switch (fx->func) {
case VIA_FUTEX_WAIT:
#ifdef __NetBSD__
- mutex_lock(&dev_priv->decoder_lock[fx->lock]);
- DRM_TIMED_WAIT_UNTIL(ret, &dev_priv->decoder_queue[fx->lock],
+ spin_lock(&dev_priv->decoder_lock[fx->lock]);
+ DRM_SPIN_WAIT_ON(ret, &dev_priv->decoder_queue[fx->lock],
&dev_priv->decoder_lock[fx->lock],
(fx->ms / 10) * (DRM_HZ / 100),
*lock != fx->val);
- if (ret < 0) /* Failure: return negative error as is. */
- ;
- else if (ret == 0) /* Timed out: return -EBUSY like Linux. */
- ret = -EBUSY;
- else /* Success (ret > 0): return 0. */
- ret = 0;
- mutex_unlock(&dev_priv->decoder_lock[fx->lock]);
+ spin_unlock(&dev_priv->decoder_lock[fx->lock]);
#else
DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
(fx->ms / 10) * (HZ / 100), *lock != fx->val);
diff -r cf4c5e813ff4 -r 940bf003bc1f sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h
--- a/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h Sat Feb 28 15:45:12 2015 +0000
+++ b/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h Sat Feb 28 18:25:39 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drm_wait_netbsd.h,v 1.8 2015/02/28 04:57:12 riastradh Exp $ */
+/* $NetBSD: drm_wait_netbsd.h,v 1.9 2015/02/28 18:25:39 riastradh Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -105,31 +105,80 @@
}
/*
- * WARNING: These DRM_*WAIT*_UNTIL macros are designed to replace the
- * Linux wait_event* macros. They have a different return value
- * convention from the legacy portability DRM_WAIT_ON macro and a
+ * DRM_SPIN_WAIT_ON is a replacement for the legacy DRM_WAIT_ON
+ * portability macro. It requires a spin interlock, which may require
+ * changes to the surrounding code so that the waits actually are
+ * interlocked by a spin lock. It also polls the condition at every
+ * tick, which masks missing wakeups. Since DRM_WAIT_ON is going away,
+ * in favour of Linux's native wait_event* API, waits in new code
+ * should be written to use the DRM_*WAIT*_UNTIL macros below.
+ *
+ * Like the legacy DRM_WAIT_ON, DRM_SPIN_WAIT_ON returns
+ *
+ * . -EBUSY if timed out (yes, -EBUSY, not -ETIMEDOUT or -EWOULDBLOCK),
+ * . -EINTR/-ERESTART if interrupted by a signal, or
+ * . 0 if the condition was true before or just after the timeout.
+ *
+ * Note that cv_timedwait* return -EWOULDBLOCK, not -EBUSY, on timeout.
+ */
+
+#define DRM_SPIN_WAIT_ON(RET, Q, INTERLOCK, TICKS, CONDITION) do \
+{ \
+ extern int hardclock_ticks; \
+ const int _dswo_start = hardclock_ticks; \
+ const int _dswo_end = _dswo_start + (TICKS); \
+ \
+ KASSERT(spin_is_locked((INTERLOCK))); \
+ KASSERT(!cpu_intr_p()); \
+ KASSERT(!cpu_softintr_p()); \
+ KASSERT(!cold); \
+ \
+ for (;;) { \
+ if (CONDITION) { \
+ (RET) = 0; \
+ break; \
+ } \
+ const int _dswo_now = hardclock_ticks; \
+ if (_dswo_end < _dswo_now) { \
+ (RET) = -EBUSY; /* Match Linux... */ \
+ break; \
+ } \
+ /* XXX errno NetBSD->Linux */ \
+ (RET) = -cv_timedwait_sig((Q), &(INTERLOCK)->sl_lock, \
+ (_dswo_end - _dswo_now)); \
+ if (RET) { \
+ if ((RET) == -EWOULDBLOCK) \
+ (RET) = (CONDITION) ? 0 : -EBUSY; \
+ \
+ break; \
+ } \
+ } \
+} while (0)
+
+/*
+ * The DRM_*WAIT*_UNTIL macros are replacements for the Linux
+ * wait_event* macros. Like DRM_SPIN_WAIT_ON, they add an interlock,
+ * and so may require some changes to the surrounding code. They have
+ * a different return value convention from DRM_SPIN_WAIT_ON and a
* different return value convention from cv_*wait*.
*
- * Specifically, the untimed macros
+ * The untimed DRM_*WAIT*_UNTIL macros return
*
- * - return negative error code on failure (interruption), and
- * - return zero on sucess.
+ * . -EINTR/-ERESTART if interrupted by a signal, or
+ * . zero if the condition evaluated
*
- * The timed macros
+ * The timed DRM_*TIMED_WAIT*_UNTIL macros return
*
- * - return negative error code on failure (interruption),
- * - return zero on timeout, and
- * - return one on success.
+ * . -EINTR/-ERESTART if interrupted by a signal,
+ * . 0 if the condition was false after the timeout,
+ * . 1 if the condition was true just after the timeout, or
+ * . the number of ticks remaining if the condition was true before the
+ * timeout.
*
- * Contrast DRM_WAIT_ON which returns -EINTR/-ERESTART on interruption,
+ * Contrast DRM_SPIN_WAIT_ON which returns -EINTR/-ERESTART on signal,
* -EBUSY on timeout, and zero on success; and cv_*wait*, which return
- * -EINTR/-ERESTART on interruption, -EWOULDBLOCK on timeout, and zero
- * on success.
- *
- * We don't simply implement DRM_WAIT_ON because, like Linux
- * wait_event*, it lacks an interlock, whereas we require an interlock
- * for any waits in order to avoid the standard race conditions
- * associated with non-interlocked waits that plague Linux drivers.
+ * -EINTR/-ERESTART on signal, -EWOULDBLOCK on timeout, and zero on
+ * success.
*
* XXX In retrospect, giving the timed and untimed macros a different
* return convention from one another to match Linux may have been a
@@ -162,19 +211,6 @@
#define DRM_WAIT_UNTIL(RET, Q, I, C) \
_DRM_WAIT_UNTIL(RET, cv_wait_sig, Q, I, C)
-/*
- * Timed wait. Return:
Home |
Main Index |
Thread Index |
Old Index